From c54b2b768d4787d6dc49c4fe76ed92e3edaf021c Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Sun, 14 Jan 2024 21:36:05 -0800 Subject: [PATCH 01/49] Microfusion Energy Guns (#9638) * RELOADING! * Update skillchip.dm * a * Update master.dm * Update master.dm * Part one * E * E * EOR * Oops * EEEH * Fixes. * begone oldcode from old times * fixes * cell attatchments * haha u cant spell * Gun attachments! * Fastest gun in the west * Update multi_cell_charger.dm * ESA * Stability * phase emitters * foixes * More fixes * Update microfusion_gun_attachments.dm * Update microfusion_gun_attachments.dm * eee * Intermediate interactions. * Update microfusion_energy_master.dm * wooh * EEE * Update microfusion_cell.dm * Map edits * Merge branch 'master' into gun_reloads * E * attachment removal * Update _basemap.dm * proper parent gun interactions * Update code/game/machinery/recharger.dm Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com> * E * Update modular_skyrat/modules/gunsgalore/code/guns/ballistic_master.dm Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com> * Update modular_skyrat/modules/microfusion/code/microfusion_cell.dm Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com> * Update modular_skyrat/modules/microfusion/code/microfusion_cell.dm Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com> * Review comments pt2 * review comments pt2 * review part 3 * review part 4 * review 4.1 * review fixes * Update microfusion_designs.dm * ffs * Update code/__DEFINES/~skyrat_defines/traits.dm Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> * Nearly there * final review commit * Update multi_cell_charger.dm * Update microfusion_energy_master.dm * E * insight * Fixes, rgb, remove instability on cells * de epic * Update _basemap.dm * TGUI in the houise * Update MicrofusionGunControl.js * FULL STEAM AHEAD CHOO CHOO (Adds zooming) * FUU bayonets and flights * e * Nearly * microCHANGES * Update gun.dm * Minidate. - Shooting the gun while it's overheating can cause it to [REDACTED]. - Shooting the gun while it's overheating will burn your hand! - Some cells will now notify you when they're empty using an alarm sound. - Gun barrel attachments now change the sound of the laser! - An overheating emitter slows down! - Emitters now control fire time more! * 0 * owo * FFF * Update code/game/machinery/recharger.dm Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> * Update modular_skyrat/modules/gunhud/code/gun_hud_component.dm Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> * no spolsion * Generally we want the cell in our hands * 0 * Update microfusion_gun_attachments.dm * E * E * FINAL * superheater * Update projectiles.dm * Update microfusion_energy_master.dm * Update projectiles.dm * Update microfusion_gun40x32.dmi * Update laser_1.ogg * E * whoop * Cargo crates! * Review plus material updates * Update microfusion_designs.dm * E * E * E * E * EEEE * Update gun_spawns.dm * Some fine tuining * Update gun_spawns.dm * Update recharger.dm * E * Update microfusion_gun_attachments.dm * E * E * Update microfusion_gun_attachments.dmi * Update code/game/machinery/recharger.dm Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com> * E * You can now actually insert different cells into advanced guns! * 0 * E * Update microfusion_gun_attachments.dm * Update microfusion_energy_master.dm * Update modular_skyrat/modules/microfusion/code/microfusion_cell.dm Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> * Update modular_skyrat/modules/microfusion/code/microfusion_cell.dm Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> * E * Update microfusion_energy_master.dm * Update microfusion_gun_attachments.dm Co-Authored-By: Tom <8881105+tf-4@users.noreply.github.com> Co-Authored-By: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> --- code/__DEFINES/inventory.dm | 29 +- code/__DEFINES/~skyrat_defines/traits.dm | 63 ++ code/game/machinery/cell_charger.dm | 7 +- code/game/machinery/recharger.dm | 15 + code/game/objects/items/storage/belt.dm | 3 +- code/modules/power/cell.dm | 64 +- code/modules/projectiles/guns/energy.dm | 23 +- .../code/modules/projectiles/guns/gun.dm | 862 ++++++++++++++++++ .../modules/aesthetics/cells/cell.dm | 7 + .../modules/goofsec/code/projectiles.dm | 203 +++++ .../modules/gunhud/code/gun_hud_component.dm | 203 +++++ .../modules/gunhud/icons/gun_hud.dmi | Bin 0 -> 11023 bytes .../modules/modular_items/code/bags.dm | 42 + .../code/multi_cell_charger.dm | 197 ++++ .../modules/robohand/code/robohand.dm | 112 +++ .../modules/sec_haul/code/guns/gun_spawns.dm | 95 ++ .../gunsgalore/code/guns/ballistic_master.dm | 272 ++++++ .../modules/gunsgalore/code/guns/skillchip.dm | 9 + .../microfusion/code/_microfusion_defines.dm | 52 ++ .../modules/microfusion/code/cargo_stuff.dm | 51 ++ .../modules/microfusion/code/gun_types.dm | 41 + .../microfusion/code/microfusion_cell.dm | 189 ++++ .../code/microfusion_cell_attachments.dm | 132 +++ .../microfusion/code/microfusion_designs.dm | 218 +++++ .../code/microfusion_energy_master.dm | 806 ++++++++++++++++ .../code/microfusion_gun_attachments.dm | 447 +++++++++ .../microfusion/code/microfusion_techweb.dm | 87 ++ .../modules/microfusion/code/phase_emitter.dm | 211 +++++ .../modules/microfusion/code/projectiles.dm | 44 + .../microfusion/icons/guns_lefthand.dmi | Bin 0 -> 840 bytes .../microfusion/icons/guns_righthand.dmi | Bin 0 -> 814 bytes .../microfusion/icons/microfusion_cells.dmi | Bin 0 -> 1724 bytes .../icons/microfusion_gun40x32.dmi | Bin 0 -> 4051 bytes .../icons/microfusion_gun_attachments.dmi | Bin 0 -> 3393 bytes .../modules/microfusion/icons/projectiles.dmi | Bin 0 -> 416 bytes .../code/modules/microfusion/sound/burn.ogg | Bin 0 -> 34599 bytes .../modules/microfusion/sound/incinerate.ogg | Bin 0 -> 29379 bytes .../modules/microfusion/sound/laser_1.ogg | Bin 0 -> 14749 bytes .../modules/microfusion/sound/mag_insert.ogg | Bin 0 -> 9407 bytes .../code/modules/microfusion/sound/melt.ogg | Bin 0 -> 26683 bytes .../modules/microfusion/sound/overheat.ogg | Bin 0 -> 64084 bytes .../modules/microfusion/sound/vaporize.ogg | Bin 0 -> 35624 bytes .../tgui/interfaces/MicrofusionGunControl.js | 269 ++++++ 43 files changed, 4678 insertions(+), 75 deletions(-) create mode 100644 code/__DEFINES/~skyrat_defines/traits.dm create mode 100644 modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm create mode 100644 modular_skyrat/modules/aesthetics/cells/cell.dm create mode 100644 modular_skyrat/modules/goofsec/code/projectiles.dm create mode 100644 modular_skyrat/modules/gunhud/code/gun_hud_component.dm create mode 100644 modular_skyrat/modules/gunhud/icons/gun_hud.dmi create mode 100644 modular_skyrat/modules/modular_items/code/bags.dm create mode 100644 modular_skyrat/modules/multicellcharger/code/multi_cell_charger.dm create mode 100644 modular_skyrat/modules/robohand/code/robohand.dm create mode 100644 modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm create mode 100644 monkestation/code/modules/gunsgalore/code/guns/ballistic_master.dm create mode 100644 monkestation/code/modules/gunsgalore/code/guns/skillchip.dm create mode 100644 monkestation/code/modules/microfusion/code/_microfusion_defines.dm create mode 100644 monkestation/code/modules/microfusion/code/cargo_stuff.dm create mode 100644 monkestation/code/modules/microfusion/code/gun_types.dm create mode 100644 monkestation/code/modules/microfusion/code/microfusion_cell.dm create mode 100644 monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm create mode 100644 monkestation/code/modules/microfusion/code/microfusion_designs.dm create mode 100644 monkestation/code/modules/microfusion/code/microfusion_energy_master.dm create mode 100644 monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm create mode 100644 monkestation/code/modules/microfusion/code/microfusion_techweb.dm create mode 100644 monkestation/code/modules/microfusion/code/phase_emitter.dm create mode 100644 monkestation/code/modules/microfusion/code/projectiles.dm create mode 100644 monkestation/code/modules/microfusion/icons/guns_lefthand.dmi create mode 100644 monkestation/code/modules/microfusion/icons/guns_righthand.dmi create mode 100644 monkestation/code/modules/microfusion/icons/microfusion_cells.dmi create mode 100644 monkestation/code/modules/microfusion/icons/microfusion_gun40x32.dmi create mode 100644 monkestation/code/modules/microfusion/icons/microfusion_gun_attachments.dmi create mode 100644 monkestation/code/modules/microfusion/icons/projectiles.dmi create mode 100644 monkestation/code/modules/microfusion/sound/burn.ogg create mode 100644 monkestation/code/modules/microfusion/sound/incinerate.ogg create mode 100644 monkestation/code/modules/microfusion/sound/laser_1.ogg create mode 100644 monkestation/code/modules/microfusion/sound/mag_insert.ogg create mode 100644 monkestation/code/modules/microfusion/sound/melt.ogg create mode 100644 monkestation/code/modules/microfusion/sound/overheat.ogg create mode 100644 monkestation/code/modules/microfusion/sound/vaporize.ogg create mode 100644 tgui/packages/tgui/interfaces/MicrofusionGunControl.js diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index b34fc1e5b16d..0646ca918571 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -165,7 +165,31 @@ //Allowed equipment lists for security vests. -GLOBAL_LIST_INIT(detective_vest_allowed, list( +GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list( + /obj/item/ammo_box, + /obj/item/ammo_casing, + /obj/item/flashlight, + /obj/item/gun, + /obj/item/melee/baton, + /obj/item/reagent_containers/spray/pepper, + /obj/item/restraints/handcuffs, + /obj/item/tank/internals, + ))) + +GLOBAL_LIST_INIT(security_hardsuit_allowed, typecacheof(list( + /obj/item/ammo_box, + /obj/item/ammo_casing, + /obj/item/flashlight, + /obj/item/gun/ballistic, + /obj/item/gun/energy, + /obj/item/melee/baton, + /obj/item/reagent_containers/spray/pepper, + /obj/item/restraints/handcuffs, + /obj/item/tank/internals, + /obj/item/gun/microfusion, //SKYRAT EDIT ADDITION + ))) + +GLOBAL_LIST_INIT(detective_vest_allowed, typecacheof(list( /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/detective_scanner, @@ -182,6 +206,7 @@ GLOBAL_LIST_INIT(detective_vest_allowed, list( /obj/item/tank/internals/plasmaman, /obj/item/storage/belt/holster/detective, /obj/item/storage/belt/holster/nukie, + /obj/item/gun/microfusion, //SKYRAT EDIT ADDITION /obj/item/storage/belt/holster/energy, )) @@ -199,6 +224,7 @@ GLOBAL_LIST_INIT(security_vest_allowed, list( /obj/item/tank/internals/plasmaman, /obj/item/storage/belt/holster/detective, /obj/item/storage/belt/holster/nukie, + /obj/item/gun/microfusion, //SKYRAT EDIT ADDITION /obj/item/storage/belt/holster/energy, /obj/item/clothing/mask/breath/sec_bandana )) @@ -213,6 +239,7 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, list( /obj/item/restraints/handcuffs, /obj/item/storage/belt/holster/detective, /obj/item/storage/belt/holster/nukie, + /obj/item/gun/microfusion, //SKYRAT EDIT ADDITION /obj/item/storage/belt/holster/energy, )) diff --git a/code/__DEFINES/~skyrat_defines/traits.dm b/code/__DEFINES/~skyrat_defines/traits.dm new file mode 100644 index 000000000000..74b1f61949a8 --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/traits.dm @@ -0,0 +1,63 @@ +// Defines for some extra traits +#define TRAIT_NO_HUSK "no_husk" +#define TRAIT_NORUNNING "norunning" // You walk! +#define TRAIT_EXCITABLE "wagwag" //Will wag when patted! +#define TRAIT_OXYIMMUNE "oxyimmune" // Immune to oxygen damage, ideally give this to all non-breathing species or bad stuff will happen +#define TRAIT_IRONASS "ironass" +#define TRAIT_MOOD_NOEXAMINE "mood_noexamine" // Can't assess your own mood +#define TRAIT_DNR "cant_revive" //You just can't be revived without supernatural means +#define TRAIT_HARD_SOLES "hard_soles" // No step on glass +#define TRAIT_SENSITIVESNOUT "sensitive_snout" // Snout hurts when booped +#define TRAIT_DETECTIVE "detective_ability" //Given to the detective, if they have this, they can see syndicate special descriptions. +#define TRAIT_FREE_GHOST "free_ghost" // Can ghost and return freely with this trait +#define QUIRK_LINGUIST "Linguist" // Extra language point. +#define GLUED_ITEM_TRAIT "glued-item" // This is for glued items, undroppable. Syndie glue applies this. +#define TRAIT_STICKY_FINGERS "sticky_fingers" //This is so a mob can strip items faster and picks them up after +/// This makes trait makes it so that the person cannot be infected by the zombie virus. +#define TRAIT_MUTANT_IMMUNE "mutant_immune" + +//AdditionalEmotes *turf traits +#define TRAIT_WATER_ASPECT "water_aspect" +#define TRAIT_WEBBING_ASPECT "webbing_aspect" +#define TRAIT_FLORAL_ASPECT "floral_aspect" +#define TRAIT_ASH_ASPECT "ash_aspect" +#define TRAIT_SPARKLE_ASPECT "sparkle_aspect" + +/// Allows the user to instantly reload. +#define TRAIT_INSTANT_RELOAD "instant_reload" + +// Trait sources +#define GHOSTROLE_TRAIT "ghostrole" // SKYRAT EDIT ADDITION -- Ghost Cafe Traits + +/// One can breath under water, you get me? +#define TRAIT_WATER_BREATHING "water_breathing" + +/// Under the effect of a numbling agent, such as morphine, for surgery. +#define TRAIT_NUMBED "numbed" + +// felinid traits +#define TRAIT_FELINE "feline_aspect" + +// chameleon mutation +#define TRAIT_CHAMELEON_SKIN "chameleon_skin" + +//Makes sure that people cant be cult sacrificed twice. +#define TRAIT_SACRIFICED "sacrificed" + +//Adds 2 seconds to the Goliath tentacle stun timer. +#define TRAIT_GOLIATH_STUN "goliath_stun" + +//to determine if someone is a fishing master, or not +#define TRAIT_FISHING_MASTER "fishing_master" + +//to determine if someone is a ceramics master, or not +#define TRAIT_CERAMIC_MASTER "ceramic_master" + +//to determine if someone is a glassblowing master, or not +#define TRAIT_GLASSBLOWING_MASTER "glassblowing_master" + +/// The trait that determines if someone has the oversized quirk. +#define TRAIT_OVERSIZED "trait_oversized" + +/// Caninid trait +#define TRAIT_CANINE "trait_canine" diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 7773b3c1b587..c9b41d58cf06 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -52,6 +52,12 @@ if(charging) to_chat(user, span_warning("There is already a cell in the charger!")) return + //SKYRAT EDIT ADDITION + var/obj/item/stock_parts/cell/inserting_cell = W + if(inserting_cell.chargerate <= 0) + to_chat(user, span_warning("[inserting_cell] cannot be recharged!")) + return + //SKYRAT EDIT END else var/area/a = loc.loc // Gets our locations location, like a dream within a dream if(!isarea(a)) @@ -133,7 +139,6 @@ /obj/machinery/cell_charger/process(seconds_per_tick) if(!charging || !anchored || (machine_stat & (BROKEN|NOPOWER))) return - if(charging.percent() >= 100) return diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 1beee62d473a..14db68c70633 100755 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -13,6 +13,8 @@ var/finished_recharging = FALSE var/static/list/allowed_devices = typecacheof(list( + /obj/item/stock_parts/cell/microfusion, //SKYRAT EDIT ADDITION + /obj/item/gun/microfusion, // SKYRAT EDIT ADDITION /obj/item/gun/energy, /obj/item/melee/baton/security, /obj/item/ammo_box/magazine/recharge, @@ -85,6 +87,19 @@ to_chat(user, span_notice("Your gun has no external power connector.")) return 1 + //SKYRAT EDIT ADDITION + if (istype(G, /obj/item/gun/microfusion)) + var/obj/item/gun/microfusion/microfusion_gun = G + if(microfusion_gun.cell?.chargerate <= 0) + to_chat(user, span_notice("[microfusion_gun] cannot be recharged!")) + return TRUE + + if(istype(G, /obj/item/stock_parts/cell/microfusion)) + var/obj/item/stock_parts/cell/microfusion/inserting_cell = G + if(inserting_cell.chargerate <= 0) + to_chat(user, span_notice("[inserting_cell] cannot be recharged!")) + return TRUE + //SKYRAT EDIT END if(!user.transferItemToLoc(G, src)) return 1 setCharging(G) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 21fc18326239..d1770b4aafae 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -343,7 +343,8 @@ /obj/item/reagent_containers/spray/pepper, /obj/item/restraints/handcuffs, /obj/item/restraints/legcuffs/bola, - /obj/item/food/spaghetti/security, //monkestation change: tactical belt spaghetti + /obj/item/food/spaghetti/security, //monkestation change: tactical belt spaghetti, + /obj/item/stock_parts/cell/microfusion, //SKYRAT EDIT ADDITION )) /obj/item/storage/belt/security/full/PopulateContents() diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 21e16d955382..270675bc91a4 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -51,44 +51,11 @@ create_reagents(5, INJECTABLE | DRAINABLE) if (override_maxcharge) maxcharge = override_maxcharge - rating = max(round(maxcharge / 10000, 1), 1) - if(!charge) - charge = maxcharge - if(empty) - charge = 0 - if(ratingdesc) - desc += " This one has a rating of [display_energy(maxcharge)][prob(10) ? ", and you should not swallow it" : ""]." //joke works better if it's not on every cell - update_appearance() - - RegisterSignal(src, COMSIG_ITEM_MAGICALLY_CHARGED, PROC_REF(on_magic_charge)) - var/static/list/loc_connections = list( - COMSIG_ITEM_MAGICALLY_CHARGED = PROC_REF(on_magic_charge), - ) - AddElement(/datum/element/connect_loc, loc_connections) - -/** - * Signal proc for [COMSIG_ITEM_MAGICALLY_CHARGED] - * - * If we, or the item we're located in, is subject to the charge spell, gain some charge back - */ -/obj/item/stock_parts/cell/proc/on_magic_charge(datum/source, datum/action/cooldown/spell/charge/spell, mob/living/caster) - SIGNAL_HANDLER - - // This shouldn't be running if we're not being held by a mob, - // or if we're not within an object being held by a mob, but just in case... - if(!ismovable(loc)) - return - - . = COMPONENT_ITEM_CHARGED - - if(prob(80)) - maxcharge -= 200 - - if(maxcharge <= 1) // Div by 0 protection - maxcharge = 1 - . |= COMPONENT_ITEM_BURNT_OUT - charge = maxcharge + /* SKYRAT EDIT REMOVAL + if(ratingdesc) + desc += " This one has a rating of [display_energy(maxcharge)], and you should not swallow it." + */ // SKYRAT EDIT END update_appearance() // Guns need to process their chamber when we've been charged @@ -119,20 +86,7 @@ . += mutable_appearance('icons/obj/power.dmi', "grown_wires") if((charge < 0.01) || !charge_light_type) return - . += mutable_appearance('icons/obj/power.dmi', "cell-[charge_light_type]-o[(percent() >= 99.5) ? 2 : 1]") - -/obj/item/stock_parts/cell/vv_edit_var(vname, vval) - if(vname == NAMEOF(src, charge)) - charge = clamp(vval, 0, maxcharge) - return TRUE - if(vname == NAMEOF(src, maxcharge)) - if(charge > vval) - charge = vval - if(vname == NAMEOF(src, corrupted) && vval && !corrupted) - corrupt(TRUE) - return TRUE - return ..() - + . += mutable_appearance(charge_overlay_icon, "cell-o[((charge / maxcharge) >= 0.995) ? 2 : 1]") //SKYRAT EDIT CHANGE /obj/item/stock_parts/cell/proc/percent() // return % charge of cell return 100 * charge / maxcharge @@ -162,8 +116,16 @@ /obj/item/stock_parts/cell/examine(mob/user) . = ..() + // SKYRAT EDIT ADDITION + if(ratingdesc && !microfusion_readout) + . += "This one has a rating of [display_energy(maxcharge)], and you should not swallow it." + // SKYRAT EDIT END if(rigged) . += span_danger("This power cell seems to be faulty!") + // SKYRAT EDIT ADDITION + else if(microfusion_readout) + . += "The charge meter reads [charge]/[maxcharge] MF." + // SKYRAT EDIT END else . += "The charge meter reads [CEILING(percent(), 0.1)]%." //so it doesn't say 0% charge when the overlay indicates it still has charge diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 0b1d70941b8b..bb02b130c6ac 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -34,26 +34,6 @@ ///set to true so the gun is given an empty cell var/dead_cell = FALSE -/obj/item/gun/energy/fire_sounds() - // What frequency the energy gun's sound will make - var/frequency_to_use - - var/obj/item/ammo_casing/energy/shot = ammo_type[select] - // What percentage of the full battery a shot will expend - var/shot_cost_percent = round(clamp(shot.e_cost / cell.maxcharge, 0, 1) * 100) - // Ignore this on oversized/infinite cells or ammo without cost - if(shot_cost_percent > 0) - // The total amount of shots the fully charged energy gun can fire before running out - var/max_shots = round(100/shot_cost_percent) - // How many shots left before the energy gun's current battery runs out of energy - var/shots_left = round((round(clamp(cell.charge / cell.maxcharge, 0, 1) * 100))/shot_cost_percent) - frequency_to_use = sin((90/max_shots) * shots_left) - - if(suppressed) - playsound(src, suppressed_sound, suppressed_volume, vary_fire_sound, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_distance = 0, frequency = frequency_to_use) - else - playsound(src, fire_sound, fire_sound_volume, vary_fire_sound, frequency = frequency_to_use) - /obj/item/gun/energy/emp_act(severity) . = ..() if(!(. & EMP_PROTECT_CONTENTS)) @@ -121,6 +101,7 @@ ammo_type[i] = shot shot = ammo_type[select] fire_sound = shot.fire_sound + fire_sound_volume = shot.fire_sound_volume //SKYRAT EDIT ADDITION fire_delay = shot.delay /obj/item/gun/energy/Destroy() @@ -202,6 +183,7 @@ select = 1 var/obj/item/ammo_casing/energy/shot = ammo_type[select] fire_sound = shot.fire_sound + fire_sound_volume = shot.fire_sound_volume //SKYRAT EDIT ADDITION fire_delay = shot.delay if (shot.select_name && user) balloon_alert(user, "set to [shot.select_name]") @@ -229,7 +211,6 @@ worn_icon_state = temp_icon_to_use return ..() - /obj/item/gun/energy/update_overlays() . = ..() if(!automatic_charge_overlays) diff --git a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm new file mode 100644 index 000000000000..0623ae88fcfd --- /dev/null +++ b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm @@ -0,0 +1,862 @@ + +#define DUALWIELD_PENALTY_EXTRA_MULTIPLIER 1.4 +#define FIRING_PIN_REMOVAL_DELAY 50 + +/obj/item/gun + name = "gun" + desc = "It's a gun. It's pretty terrible, though." + icon = 'modular_skyrat/modules/fixing_missing_icons/ballistic.dmi' //skyrat edit + icon_state = "detective" + inhand_icon_state = "gun" + worn_icon_state = "gun" + flags_1 = CONDUCT_1 + slot_flags = ITEM_SLOT_BELT + custom_materials = list(/datum/material/iron = 2000) + w_class = WEIGHT_CLASS_NORMAL + throwforce = 5 + throw_speed = 3 + throw_range = 5 + force = 5 + item_flags = NEEDS_PERMIT + attack_verb_continuous = list("strikes", "hits", "bashes") + attack_verb_simple = list("strike", "hit", "bash") + + var/gun_flags = NONE + var/fire_sound = 'sound/weapons/gun/pistol/shot.ogg' + var/vary_fire_sound = TRUE + var/fire_sound_volume = 50 + var/dry_fire_sound = 'sound/weapons/gun/general/dry_fire.ogg' + var/suppressed = null //whether or not a message is displayed when fired + var/can_suppress = FALSE + var/suppressed_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' + var/suppressed_volume = 60 + var/can_unsuppress = TRUE + var/recoil = 0 //boom boom shake the room + var/clumsy_check = TRUE + var/obj/item/ammo_casing/chambered = null + trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers + var/sawn_desc = null //description change if weapon is sawn-off + var/sawn_off = FALSE + var/burst_size = 1 //how large a burst is + var/fire_delay = 0 //rate of fire for burst firing and semi auto + var/firing_burst = 0 //Prevent the weapon from firing again while already firing + var/semicd = 0 //cooldown handler + var/weapon_weight = WEAPON_LIGHT + var/dual_wield_spread = 24 //additional spread when dual wielding + + /// Just 'slightly' snowflakey way to modify projectile damage for projectiles fired from this gun. + var/projectile_damage_multiplier = 1 + + var/spread = 0 //Spread induced by the gun itself. + var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once. + + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + + var/obj/item/firing_pin/pin = /obj/item/firing_pin //standard firing pin for most guns + + var/can_flashlight = FALSE //if a flashlight can be added or removed if it already has one. + /// True if a gun dosen't need a pin, mostly used for abstract guns like tentacles and meathooks + var/pinless = FALSE + var/obj/item/flashlight/seclite/gun_light + var/datum/action/item_action/toggle_gunlight/alight + var/gunlight_state = "flight" + var/gunlight_icon = 'icons/obj/guns/flashlights.dmi' + + var/can_bayonet = FALSE //if a bayonet can be added or removed if it already has one. + var/bayonet_state = "bayonet" + var/bayonet_icon = 'icons/obj/guns/bayonets.dmi' + var/obj/item/knife/bayonet + var/knife_x_offset = 0 + var/knife_y_offset = 0 + + var/ammo_x_offset = 0 //used for positioning ammo count overlay on sprite + var/ammo_y_offset = 0 + var/flight_x_offset = 0 + var/flight_y_offset = 0 + + //Zooming + var/zoomable = FALSE //whether the gun generates a Zoom action on creation + var/zoomed = FALSE //Zoom toggle + var/zoom_amt = 3 //Distance in TURFs to move the user's screen forward (the "zoom" effect) + var/zoom_out_amt = 0 + var/datum/action/toggle_scope_zoom/azoom + var/pb_knockback = 0 + + var/safety = FALSE ///Internal variable for keeping track whether the safety is on or off + var/has_gun_safety = FALSE ///Whether the gun actually has a gun safety + var/datum/action/item_action/toggle_safety/tsafety + + var/datum/action/item_action/toggle_firemode/firemode_action + ///Current fire selection, can choose between burst, single, and full auto. + var/fire_select = SELECT_SEMI_AUTOMATIC + var/fire_select_index = 1 + ///What modes does this weapon have? Put SELECT_FULLY_AUTOMATIC in here to enable fully automatic behaviours. + var/list/fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + ///if i`1t has an icon for a selector switch indicating current firemode. + var/selector_switch_icon = FALSE + +/datum/action/item_action/toggle_safety + name = "Toggle Safety" + icon_icon = 'modular_skyrat/modules/gunsafety/icons/actions.dmi' + button_icon_state = "safety_on" + +/obj/item/gun/ui_action_click(mob/user, actiontype) + if(istype(actiontype, /datum/action/item_action/toggle_firemode)) + fire_select() + else if(istype(actiontype, tsafety)) + toggle_safety(user) + else + ..() + +/obj/item/gun/Initialize() + . = ..() + if(pin && !pinless) + pin = new pin(src) + + if(gun_light) + alight = new(src) + + build_zooming() + + if(has_gun_safety) + safety = TRUE + tsafety = new(src) + + if(burst_size > 1 && !(SELECT_BURST_SHOT in fire_select_modes)) + fire_select_modes.Add(SELECT_BURST_SHOT) + else if(burst_size <= 1 && (SELECT_BURST_SHOT in fire_select_modes)) + fire_select_modes.Remove(SELECT_BURST_SHOT) + + burst_size = 1 + + sort_list(fire_select_modes, /proc/cmp_numeric_asc) + + if(fire_select_modes.len > 1) + firemode_action = new(src) + firemode_action.button_icon_state = "fireselect_[fire_select]" + firemode_action.UpdateButtonIcon() + +/obj/item/gun/ComponentInitialize() + . = ..() + if(SELECT_FULLY_AUTOMATIC in fire_select_modes) + AddComponent(/datum/component/automatic_fire, fire_delay) + +/obj/item/gun/Destroy() + if(isobj(pin)) //Can still be the initial path, then we skip + QDEL_NULL(pin) + if(gun_light) + QDEL_NULL(gun_light) + if(bayonet) + QDEL_NULL(bayonet) + if(chambered) //Not all guns are chambered (EMP'ed energy guns etc) + QDEL_NULL(chambered) + if(azoom) + QDEL_NULL(azoom) + if(isatom(suppressed)) + QDEL_NULL(suppressed) + if(tsafety) + QDEL_NULL(tsafety) + if(firemode_action) + QDEL_NULL(firemode_action) + . = ..() + +/obj/item/gun/handle_atom_del(atom/gun_atom) + if(gun_atom == pin) + pin = null + if(gun_atom == chambered) + chambered = null + update_appearance() + if(gun_atom == bayonet) + clear_bayonet() + if(gun_atom == gun_light) + clear_gunlight() + if(gun_atom == suppressed) + clear_suppressor() + . = ..() + +///Clears var and updates icon. In the case of ballistic weapons, also updates the gun's weight. +/obj/item/gun/proc/clear_suppressor() + if(!can_unsuppress) + return + suppressed = null + update_appearance() + +/obj/item/gun/examine(mob/user) + . = ..() + if(!pinless) + if(pin) + . += "It has \a [pin] installed." + . += span_info("[pin] looks like it could be removed with some tools.") + else + . += "It doesn't have a firing pin installed, and won't fire." + + if(gun_light) + . += "It has \a [gun_light] [can_flashlight ? "" : "permanently "]mounted on it." + if(can_flashlight) //if it has a light and this is false, the light is permanent. + . += span_info("[gun_light] looks like it can be unscrewed from [src].") + else if(can_flashlight) + . += "It has a mounting point for a seclite." + + if(bayonet) + . += "It has \a [bayonet] [can_bayonet ? "" : "permanently "]affixed to it." + if(can_bayonet) //if it has a bayonet and this is false, the bayonet is permanent. + . += span_info("[bayonet] looks like it can be unscrewed from [src].") + if(can_bayonet) + . += "It has a bayonet lug on it." + if(has_gun_safety) + . += "The safety is [safety ? "ON" : "OFF"]." + +/obj/item/gun/equipped(mob/living/user, slot) + . = ..() + if(zoomed && user.get_active_held_item() != src) + zoom(user, user.dir, FALSE) //we can only stay zoomed in if it's in our hands //yeah and we only unzoom if we're actually zoomed using the gun!! + +/obj/item/gun/proc/fire_select() + var/mob/living/carbon/human/user = usr + + var/max_mode = fire_select_modes.len + + if(max_mode <= 1) + to_chat(user, span_warning("[src] is not capable of switching firemodes!")) + return + + fire_select_index = 1 + fire_select_index % max_mode //Magic math to cycle through this shit! + + fire_select = fire_select_modes[fire_select_index] + + switch(fire_select) + if(SELECT_SEMI_AUTOMATIC) + burst_size = 1 + fire_delay = 0 + SEND_SIGNAL(src, COMSIG_GUN_AUTOFIRE_DESELECTED, user) + to_chat(user, span_notice("You switch [src] to semi-automatic.")) + if(SELECT_BURST_SHOT) + burst_size = initial(burst_size) + fire_delay = initial(fire_delay) + SEND_SIGNAL(src, COMSIG_GUN_AUTOFIRE_DESELECTED, user) + to_chat(user, span_notice("You switch [src] to [burst_size]-round burst.")) + if(SELECT_FULLY_AUTOMATIC) + burst_size = 1 + SEND_SIGNAL(src, COMSIG_GUN_AUTOFIRE_SELECTED, user) + to_chat(user, span_notice("You switch [src] to automatic.")) + + playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) + update_appearance() + firemode_action.button_icon_state = "fireselect_[fire_select]" + firemode_action.UpdateButtonIcon() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + return TRUE + +//called after the gun has successfully fired its chambered ammo. +/obj/item/gun/proc/process_chamber(empty_chamber = TRUE, from_firing = TRUE, chamber_next_round = TRUE) + handle_chamber(empty_chamber, from_firing, chamber_next_round) + SEND_SIGNAL(src, COMSIG_GUN_CHAMBER_PROCESSED) + +/obj/item/gun/proc/handle_chamber(empty_chamber = TRUE, from_firing = TRUE, chamber_next_round = TRUE) + return + + +//check if there's enough ammo/energy/whatever to shoot one time +//i.e if clicking would make it shoot +/obj/item/gun/proc/can_shoot() + return TRUE + +/obj/item/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj) + to_chat(user, span_danger("*click*")) + playsound(src, dry_fire_sound, 30, TRUE) + + +/obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = 0, atom/pbtarget = null, message = 1) + if(recoil) + shake_camera(user, recoil + 1, recoil) + + if(suppressed) + playsound(user, suppressed_sound, suppressed_volume, vary_fire_sound, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_distance = 0) + else + playsound(user, fire_sound, fire_sound_volume, vary_fire_sound) + if(message) + if(pointblank) + user.visible_message(span_danger("[user] fires [src] point blank at [pbtarget]!"), \ + span_danger("You fire [src] point blank at [pbtarget]!"), \ + span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE, pbtarget) + to_chat(pbtarget, span_userdanger("[user] fires [src] point blank at you!")) + if(pb_knockback > 0 && ismob(pbtarget)) + var/mob/PBT = pbtarget + var/atom/throw_target = get_edge_target_turf(PBT, user.dir) + PBT.throw_at(throw_target, pb_knockback, 2) + else + user.visible_message(span_danger("[user] fires [src]!"), \ + span_danger("You fire [src]!"), \ + span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE) + if(user.resting) // SKYRAT EDIT ADD - no crawlshooting + user.Immobilize(20, TRUE) // SKYRAT EDIT END + +/obj/item/gun/emp_act(severity) + . = ..() + if(!(. & EMP_PROTECT_CONTENTS)) + for(var/obj/iterated_object in contents) + iterated_object.emp_act(severity) + +/obj/item/gun/attack_secondary(mob/living/victim, mob/living/user, params) + if(user.GetComponent(/datum/component/gunpoint)) + to_chat(user, span_warning("You are already holding someone up!")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(user == victim) + to_chat(user, span_warning("You can't hold yourself up!")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + user.AddComponent(/datum/component/gunpoint, victim, src) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/item/gun/afterattack(atom/target, mob/living/user, flag, params) + . = ..() + return fire_gun(target, user, flag, params) + +/obj/item/gun/proc/fire_gun(atom/target, mob/living/user, flag, params) + if(QDELETED(target)) + return + if(firing_burst) + return + if(flag) //It's adjacent, is the user, or is on the user's person + if(target in user.contents) //can't shoot stuff inside us. + return + if(!ismob(target) || user.combat_mode) //melee attack + return + if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) + return + if(iscarbon(target)) + var/mob/living/carbon/carbon_target = target + for(var/i in carbon_target.all_wounds) + var/datum/wound/target_wound = i + if(target_wound.try_treating(src, user)) + return // another coward cured! + + if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can. + var/mob/living/living_user = user + if(!can_trigger_gun(living_user)) + return + if(flag) + if(user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + handle_suicide(user, target, params) + return + + if(!can_shoot()) //Just because you can pull the trigger doesn't mean it can shoot. + shoot_with_empty_chamber(user) + return + + if(check_botched(user)) + return + + var/obj/item/bodypart/other_hand = user.has_hand_for_held_index(user.get_inactive_hand_index()) //returns non-disabled inactive hands + if(weapon_weight == WEAPON_HEAVY && (user.get_inactive_held_item() || !other_hand)) + to_chat(user, span_warning("You need two hands to fire [src]!")) + return + //DUAL (or more!) WIELDING + var/bonus_spread = 0 + var/loop_counter = 0 + if(ishuman(user) && user.combat_mode) + var/mob/living/carbon/human/human_user = user + for(var/obj/item/gun/held_gun in human_user.held_items) + if(held_gun == src || held_gun.weapon_weight >= WEAPON_MEDIUM) + continue + else if(held_gun.can_trigger_gun(user)) + bonus_spread += dual_wield_spread + loop_counter++ + addtimer(CALLBACK(held_gun, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter) + + return process_fire(target, user, TRUE, params, null, bonus_spread) + +/obj/item/gun/proc/check_botched(mob/living/user, params) + if(clumsy_check) + if(istype(user)) + if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(40)) + to_chat(user, span_userdanger("You shoot yourself in the foot with [src]!")) + var/shot_leg = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + process_fire(user, user, FALSE, params, shot_leg) + SEND_SIGNAL(user, COMSIG_MOB_CLUMSY_SHOOT_FOOT) + user.dropItemToGround(src, TRUE) + return TRUE + +/obj/item/gun/can_trigger_gun(mob/living/user) + . = ..() + if(!handle_pins(user)) + return FALSE + if(has_gun_safety && safety) + to_chat(user, span_warning("The safety is on!")) + return FALSE + +/obj/item/gun/proc/toggle_safety(mob/user, override) + if(!has_gun_safety) + return + if(override) + if(override == "off") + safety = FALSE + else + safety = TRUE + else + safety = !safety + tsafety.button_icon_state = "safety_[safety ? "on" : "off"]" + tsafety.UpdateButtonIcon() + playsound(src, 'sound/weapons/empty.ogg', 100, TRUE) + user.visible_message(span_notice("[user] toggles [src]'s safety [safety ? "ON" : "OFF"]."), + span_notice("You toggle [src]'s safety [safety ? "ON" : "OFF"].")) + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + +/obj/item/gun/proc/handle_pins(mob/living/user) + if(pinless) + return TRUE + if(pin) + if(pin.pin_auth(user) || (pin.obj_flags & EMAGGED)) + return TRUE + else + pin.auth_fail(user) + return FALSE + else + to_chat(user, span_warning("[src]'s trigger is locked. This weapon doesn't have a firing pin installed!")) + return FALSE + +/obj/item/gun/proc/recharge_newshot() + return + +/obj/item/gun/proc/process_burst(mob/living/user, atom/target, message = TRUE, params = null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0) + if(!user || !firing_burst) + firing_burst = FALSE + return FALSE + if(!issilicon(user)) + if(iteration > 1 && !(user.is_holding(src))) //for burst firing + firing_burst = FALSE + return FALSE + if(chambered?.loaded_projectile) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal. + if(chambered.harmful) // Is the bullet chambered harmful? + to_chat(user, span_warning("[src] is lethally chambered! You don't want to risk harming anyone...")) + return + if(randomspread) + sprd = round((rand(0, 1) - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + else //Smart spread + sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread)) + before_firing(target, user) + if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd, src)) + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + if (iteration >= burst_size) + firing_burst = FALSE + else + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + process_chamber() + update_appearance() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + return TRUE + +/obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) + if(user) + SEND_SIGNAL(user, COMSIG_MOB_FIRED_GUN, user, target, params, zone_override) + + SEND_SIGNAL(src, COMSIG_GUN_FIRED, user, target, params, zone_override) + + add_fingerprint(user) + + if(semicd) + return + + //Vary by at least this much + var/base_bonus_spread = 0 + var/sprd = 0 + var/randomized_gun_spread = 0 + var/rand_spr = rand() + if(user && HAS_TRAIT(user, TRAIT_POOR_AIM)) //Nice job hotshot + bonus_spread += 35 + base_bonus_spread += 10 + + if(spread) + randomized_gun_spread = rand(0, spread) + var/randomized_bonus_spread = rand(base_bonus_spread, bonus_spread) + + if(burst_size > 1) + firing_burst = TRUE + for(var/i = 1 to burst_size) + addtimer(CALLBACK(src, .proc/process_burst, user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i), fire_delay * (i - 1)) + else + if(chambered) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal. + if(chambered.harmful) // Is the bullet chambered harmful? + to_chat(user, span_warning("[src] is lethally chambered! You don't want to risk harming anyone...")) + return + sprd = round((rand(0, 1) - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + before_firing(target, user) + if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd, src)) + shoot_with_empty_chamber(user) + return + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + else + shoot_with_empty_chamber(user) + return + process_chamber() + update_appearance() + semicd = TRUE + addtimer(CALLBACK(src, .proc/reset_semicd), fire_delay) + + if(user) + user.update_inv_hands() + SSblackbox.record_feedback("tally", "gun_fired", 1, type) + + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + + return TRUE + +/obj/item/gun/proc/reset_semicd() + semicd = FALSE + +/obj/item/gun/attack(mob/target, mob/living/user) + if(user.combat_mode) //Flogging + if(bayonet) + target.attackby(bayonet, user) + return + else + return ..() + return + +/obj/item/gun/attack_atom(obj/target, mob/living/user, params) + if(user.combat_mode) + if(bayonet) + target.attackby(bayonet, user) + return + return ..() + +/obj/item/gun/attackby(obj/item/attacking_item, mob/living/user, params) + if(user.combat_mode) + return ..() + else if(istype(attacking_item, /obj/item/flashlight/seclite)) + if(!can_flashlight) + return ..() + var/obj/item/flashlight/seclite/attaching_seclite = attacking_item + if(!gun_light) + if(!user.transferItemToLoc(attacking_item, src)) + return + to_chat(user, span_notice("You click [attaching_seclite] into place on [src].")) + set_gun_light(attaching_seclite) + update_gunlight() + alight = new(src) + if(loc == user) + alight.Grant(user) + else if(istype(attacking_item, /obj/item/knife)) + var/obj/item/knife/attaching_knife = attacking_item + if(!can_bayonet || !attaching_knife.bayonet || bayonet) //ensure the gun has an attachment point available, and that the knife is compatible with it. + return ..() + if(!user.transferItemToLoc(attacking_item, src)) + return + to_chat(user, span_notice("You attach [attaching_knife] to [src]'s bayonet lug.")) + bayonet = attaching_knife + update_appearance() + + else + return ..() + +/obj/item/gun/screwdriver_act(mob/living/user, obj/item/tool) + . = ..() + if(.) + return + if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + if((can_flashlight && gun_light) && (can_bayonet && bayonet)) //give them a choice instead of removing both + var/list/possible_items = list(gun_light, bayonet) + var/obj/item/item_to_remove = input(user, "Select an attachment to remove", "Attachment Removal") as null|obj in sort_names(possible_items) + if(!item_to_remove || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + return remove_gun_attachment(user, tool, item_to_remove) + + else if(gun_light && can_flashlight) //if it has a gun_light and can_flashlight is false, the flashlight is permanently attached. + return remove_gun_attachment(user, tool, gun_light, "unscrewed") + + else if(bayonet && can_bayonet) //if it has a bayonet, and the bayonet can be removed + return remove_gun_attachment(user, tool, bayonet, "unfix") + + else if(pin && user.is_holding(src)) + user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [tool]."), + span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3) + if(tool.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, volume = 50)) + if(!pin) //check to see if the pin is still there, or we can spam messages by clicking multiple times during the tool delay + return + user.visible_message(span_notice("[pin] is pried out of [src] by [user], destroying the pin in the process."), + span_warning("You pry [pin] out with [tool], destroying the pin in the process."), null, 3) + QDEL_NULL(pin) + return TRUE + +/obj/item/gun/welder_act(mob/living/user, obj/item/tool) + . = ..() + if(.) + return + if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + if(pin && user.is_holding(src)) + user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [tool]."), + span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3) + if(tool.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, 5, volume = 50)) + if(!pin) //check to see if the pin is still there, or we can spam messages by clicking multiple times during the tool delay + return + user.visible_message(span_notice("[pin] is spliced out of [src] by [user], melting part of the pin in the process."), + span_warning("You splice [pin] out of [src] with [tool], melting part of the pin in the process."), null, 3) + QDEL_NULL(pin) + return TRUE + +/obj/item/gun/wirecutter_act(mob/living/user, obj/item/tool) + . = ..() + if(.) + return + if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + if(pin && user.is_holding(src)) + user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [tool]."), + span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3) + if(tool.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, volume = 50)) + if(!pin) //check to see if the pin is still there, or we can spam messages by clicking multiple times during the tool delay + return + user.visible_message(span_notice("[pin] is ripped out of [src] by [user], mangling the pin in the process."), + span_warning("You rip [pin] out of [src] with [tool], mangling the pin in the process."), null, 3) + QDEL_NULL(pin) + return TRUE + +/obj/item/gun/proc/remove_gun_attachment(mob/living/user, obj/item/tool_item, obj/item/item_to_remove, removal_verb) + if(tool_item) + tool_item.play_tool_sound(src) + to_chat(user, span_notice("You [removal_verb ? removal_verb : "remove"] [item_to_remove] from [src].")) + item_to_remove.forceMove(drop_location()) + + if(Adjacent(user) && !issilicon(user)) + user.put_in_hands(item_to_remove) + + if(item_to_remove == bayonet) + return clear_bayonet() + else if(item_to_remove == gun_light) + return clear_gunlight() + +/obj/item/gun/proc/clear_bayonet() + if(!bayonet) + return + bayonet = null + update_appearance() + return TRUE + +/obj/item/gun/proc/clear_gunlight() + if(!gun_light) + return + var/obj/item/flashlight/seclite/removed_light = gun_light + set_gun_light(null) + update_gunlight() + removed_light.update_brightness() + QDEL_NULL(alight) + return TRUE + + +/** + * Swaps the gun's seclight, dropping the old seclight if it has not been qdel'd. + * + * Returns the former gun_light that has now been replaced by this proc. + * Arguments: + * * new_light - The new light to attach to the weapon. Can be null, which will mean the old light is removed with no replacement. + */ +/obj/item/gun/proc/set_gun_light(obj/item/flashlight/seclite/new_light) + // Doesn't look like this should ever happen? We're replacing our old light with our old light? + if(gun_light == new_light) + CRASH("Tried to set a new gun light when the old gun light was also the new gun light.") + + . = gun_light + + // If there's an old gun light that isn't being QDELETED, detatch and drop it to the floor. + if(!QDELETED(gun_light)) + gun_light.set_light_flags(gun_light.light_flags & ~LIGHT_ATTACHED) + if(gun_light.loc == src) + gun_light.forceMove(get_turf(src)) + + // If there's a new gun light to be added, attach and move it to the gun. + if(new_light) + new_light.set_light_flags(new_light.light_flags | LIGHT_ATTACHED) + if(new_light.loc != src) + new_light.forceMove(src) + + gun_light = new_light + +/obj/item/gun/ui_action_click(mob/user, actiontype) + if(istype(actiontype, alight)) + toggle_gunlight() + else + ..() + +/obj/item/gun/proc/toggle_gunlight() + if(!gun_light) + return + + var/mob/living/carbon/human/user = usr + gun_light.on = !gun_light.on + gun_light.update_brightness() + to_chat(user, span_notice("You toggle the gunlight [gun_light.on ? "on":"off"].")) + + playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) + update_gunlight() + +/obj/item/gun/proc/update_gunlight() + update_appearance() + update_action_buttons() + +/obj/item/gun/pickup(mob/user) + . = ..() + if(azoom) + azoom.Grant(user) + if(w_class > WEIGHT_CLASS_SMALL && !suppressed) + user.visible_message(span_warning("[user] grabs [src]!"), + span_warning("You grab [src]!")) + +/obj/item/gun/dropped(mob/user) + . = ..() + if(azoom) + azoom.Remove(user) + if(zoomed) + zoom(user, user.dir, FALSE) + +/obj/item/gun/update_overlays() + . = ..() + if(gun_light) + var/mutable_appearance/flashlight_overlay + var/state = "[gunlight_state][gun_light.on? "_on":""]" //Generic state. + if(gun_light.icon_state in icon_states(gunlight_icon)) //Snowflake state? + state = gun_light.icon_state + flashlight_overlay = mutable_appearance(gunlight_icon, state) + flashlight_overlay.pixel_x = flight_x_offset + flashlight_overlay.pixel_y = flight_y_offset + . += flashlight_overlay + + if(bayonet) + var/mutable_appearance/knife_overlay + var/state = bayonet_state + if(bayonet.icon_state in icon_states(bayonet_icon)) //Snowflake state? + state = bayonet.icon_state + knife_overlay = mutable_appearance(bayonet_icon, state) + knife_overlay.pixel_x = knife_x_offset + knife_overlay.pixel_y = knife_y_offset + . += knife_overlay + +/obj/item/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer) + if(!ishuman(user) || !ishuman(target)) + return + + if(semicd) + return + + if(user == target) + target.visible_message(span_warning("[user] sticks [src] in [user.p_their()] mouth, ready to pull the trigger..."), \ + span_userdanger("You stick [src] in your mouth, ready to pull the trigger...")) + else + target.visible_message(span_warning("[user] points [src] at [target]'s head, ready to pull the trigger..."), \ + span_userdanger("[user] points [src] at your head, ready to pull the trigger...")) + + semicd = TRUE + + if(!bypass_timer && (!do_mob(user, target, 120) || user.zone_selected != BODY_ZONE_PRECISE_MOUTH)) + if(user) + if(user == target) + user.visible_message(span_notice("[user] decided not to shoot.")) + else if(target?.Adjacent(user)) + target.visible_message(span_notice("[user] has decided to spare [target]"), span_notice("[user] has decided to spare your life!")) + semicd = FALSE + return + + semicd = FALSE + + target.visible_message(span_warning("[user] pulls the trigger!"), span_userdanger("[(user == target) ? "You pull" : "[user] pulls"] the trigger!")) + + if(chambered?.loaded_projectile) + chambered.loaded_projectile.damage *= 5 + if(chambered.loaded_projectile.wound_bonus != CANT_WOUND) + chambered.loaded_projectile.wound_bonus += 5 // much more dramatic on multiple pellet'd projectiles really + + var/fired = process_fire(target, user, TRUE, params, BODY_ZONE_HEAD) + if(!fired && chambered?.loaded_projectile) + chambered.loaded_projectile.damage /= 5 + if(chambered.loaded_projectile.wound_bonus != CANT_WOUND) + chambered.loaded_projectile.wound_bonus -= 5 + +/obj/item/gun/proc/unlock() //used in summon guns and as a convience for admins + if(pin) + qdel(pin) + pin = new /obj/item/firing_pin + +//Happens before the actual projectile creation +/obj/item/gun/proc/before_firing(atom/target, mob/user) + return + +///////////// +// ZOOMING // +///////////// + +/datum/action/toggle_scope_zoom + name = "Toggle Scope" + check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_LYING + icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon_state = "sniper_zoom" + var/obj/item/gun/gun = null + +/datum/action/toggle_scope_zoom/Trigger() + . = ..() + if(!.) + return + gun.zoom(owner, owner.dir) + +/datum/action/toggle_scope_zoom/IsAvailable() + . = ..() + if(owner.get_active_held_item() != gun) + . = FALSE + if(!. && gun) + gun.zoom(owner, owner.dir, FALSE) + +/datum/action/toggle_scope_zoom/Remove(mob/living/user) + gun.zoom(user, user.dir, FALSE) + ..() + +/obj/item/gun/proc/rotate(atom/thing, old_dir, new_dir) + SIGNAL_HANDLER + + if(ismob(thing)) + var/mob/lad = thing + lad.client?.view_size.zoomOut(zoom_out_amt, zoom_amt, new_dir) + +/obj/item/gun/proc/zoom(mob/living/user, direc, forced_zoom) + if(!user || !user.client) + return + + if(isnull(forced_zoom)) + zoomed = !zoomed + else + zoomed = forced_zoom + + if(zoomed) + RegisterSignal(user, COMSIG_ATOM_DIR_CHANGE, .proc/rotate) + user.client?.view_size.zoomOut(zoom_out_amt, zoom_amt, direc) + else + UnregisterSignal(user, COMSIG_ATOM_DIR_CHANGE) + user.client?.view_size.zoomIn() + return zoomed + +//Proc, so that gun accessories/scopes/etc. can easily add zooming. +/obj/item/gun/proc/build_zooming() + if(azoom) + return + + if(zoomable) + azoom = new() + azoom.gun = src + +#undef FIRING_PIN_REMOVAL_DELAY +#undef DUALWIELD_PENALTY_EXTRA_MULTIPLIER diff --git a/modular_skyrat/modules/aesthetics/cells/cell.dm b/modular_skyrat/modules/aesthetics/cells/cell.dm new file mode 100644 index 000000000000..bdc9214d8109 --- /dev/null +++ b/modular_skyrat/modules/aesthetics/cells/cell.dm @@ -0,0 +1,7 @@ +/obj/item/stock_parts/cell + icon = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' + /// The charge overlay icon file for the cell charge lights + var/charge_overlay_icon = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' + +/obj/machinery/cell_charger + icon = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' diff --git a/modular_skyrat/modules/goofsec/code/projectiles.dm b/modular_skyrat/modules/goofsec/code/projectiles.dm new file mode 100644 index 000000000000..5c6ff37f26d8 --- /dev/null +++ b/modular_skyrat/modules/goofsec/code/projectiles.dm @@ -0,0 +1,203 @@ +/obj/item/ammo_casing/energy/laser/hardlight_bullet + name = "hardlight bullet casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet + e_cost = 83 // 12 shots with a normal cell. + select_name = "hardlight bullet" + fire_sound = 'sound/weapons/gun/pistol/shot.ogg' + + // Not a real bullet, but visually looks like one. For the aesthetic of bullets, while keeping the balance intact. + // Every piece of armor in the game is currently balanced around "sec has lasers, syndies have bullets". This allows us to keep that balance + // without sacrificing the bullet aesthetic. +/obj/projectile/beam/laser/hardlight_bullet + icon = 'modular_skyrat/modules/sec_haul/icons/guns/projectiles.dmi' + icon_state = "bullet" + name = "hardlight bullet" + pass_flags = PASSTABLE // All of the below is to not break kayfabe about it not being a bullet. + hitsound ='sound/weapons/pierce.ogg' + hitsound_wall = "ricochet" + light_system = NO_LIGHT_SUPPORT + light_range = 0 + light_power = 0 + damage_type = BRUTE // So they do brute damage but still hit laser armor! + sharpness = SHARP_POINTY + impact_effect_type = /obj/effect/temp_visual/impact_effect + shrapnel_type = /obj/item/shrapnel/bullet + embedding = list(embed_chance=20, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10) + +// For calculating ammo, remember that these guns have 1000 unit power cells. + +/// Vintorez +/obj/item/gun/energy/vintorez + name = "\improper VKC 'Vintorez'" + desc = "The VKC Vintorez is a lightweight integrally-suppressed scoped carbine usually employed in stealth operations from the long since past 20th century." + icon = 'modular_skyrat/modules/goofsec/icons/gun_sprites.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + icon_state = "vintorez" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/norwind.dmi' + worn_icon_state = "norwind_worn" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + inhand_icon_state = "vintorez" + burst_size = 2 + fire_delay = 4 + zoomable = TRUE + zoom_amt = 7 + zoom_out_amt = 5 + fire_sound = null + ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/vintorez) + shaded_charge = TRUE + cell_type = /obj/item/stock_parts/cell/super + +/obj/item/ammo_casing/energy/laser/hardlight_bullet/vintorez + name = "hardlight bullet vintorez casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet/vintorez + e_cost = 1666 // 27 damage so 12 shots. + fire_sound = 'sound/weapons/gun/smg/shot_suppressed.ogg' + +/obj/projectile/beam/laser/hardlight_bullet/vintorez + damage = 27 // All security armory firearms need to do, at minimum, laser gun damage. + +/obj/item/gun/energy/norwind + name = "\improper M112 'Norwind'" + desc = "A rare M112 DMR rechambered to 12.7x30mm for peacekeeping work, it comes with a scope for medium-long range engagements. A bayonet lug is visible." + icon = 'modular_skyrat/modules/goofsec/icons/gun_sprites.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/norwind.dmi' + worn_icon_state = "norwind_worn" + icon_state = "norwind" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + inhand_icon_state = "norwind" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/norwind.dmi' + worn_icon_state = "norwind_worn" + can_bayonet = TRUE + can_flashlight = TRUE + zoomable = TRUE + zoom_amt = 7 + zoom_out_amt = 5 + fire_sound = null + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/norwind) + burst_size = 1 + fire_delay = 10 + shaded_charge = TRUE + cell_type = /obj/item/stock_parts/cell/super + +/obj/item/ammo_casing/energy/laser/hardlight_bullet/norwind + name = "hardlight bullet norwind casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet/norwind + e_cost = 2857 // 7 shots, does 1.6x damage normal laser so fire cost increased by 1.6x + fire_sound = 'modular_skyrat/modules/sec_haul/sound/ltrifle_fire.ogg' + +/obj/projectile/beam/laser/hardlight_bullet/norwind + damage = 45 + +/obj/item/gun/energy/ostwind + name = "\improper DTR-6 rifle" + desc = "A 6.3mm special-purpose rifle designed for specific situations." + icon = 'modular_skyrat/modules/goofsec/icons/gun_sprites.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + inhand_icon_state = "ostwind" + icon_state = "ostwind" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/ostwind.dmi' + worn_icon_state = "ostwind_worn" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + fire_delay = 2 + burst_size = 2 + fire_sound = null + can_bayonet = TRUE + ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/ostwind) + cell_type = /obj/item/stock_parts/cell/super +/obj/item/ammo_casing/energy/laser/hardlight_bullet/ostwind + name = "hardlight bullet norostwindwind casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet/ostwind + e_cost = 1666 // 27 damage so 12 shots. + fire_sound = 'sound/weapons/gun/smg/shot.ogg' + +/obj/projectile/beam/laser/hardlight_bullet/ostwind + damage = 27 // Minimum damage increase to at least base /tg/ laser gun damage. + embedding = list(embed_chance=10, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) + +/obj/item/gun/energy/pitbull + name = "\improper Pitbull PDW" + desc = "A sturdy personal defense weapon designed to fire 10mm Auto rounds." + icon = 'modular_skyrat/modules/goofsec/icons/gun_sprites.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + inhand_icon_state = "pitbull" + icon_state = "pitbull" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/ostwind.dmi' + worn_icon_state = "ostwind_worn" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + fire_delay = 4.20 + burst_size = 3 + fire_sound = null + can_bayonet = TRUE + can_flashlight = TRUE + ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/pitbull) + shaded_charge = TRUE + cell_type = /obj/item/stock_parts/cell/super + +/obj/item/ammo_casing/energy/laser/hardlight_bullet/pitbull + name = "hardlight bullet pitbull casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet/pitbull + e_cost = 1666 // 27 damage so 12 shots. + fire_sound = 'modular_skyrat/modules/sec_haul/sound/sfrifle_fire.ogg' + +/obj/projectile/beam/laser/hardlight_bullet/pitbull + damage = 27 + +/obj/item/gun/energy/pcr + name = "\improper PCR-9 SMG" + desc = "An accurate, fast-firing SMG chambered in 9x19mm." + icon = 'modular_skyrat/modules/goofsec/icons/gun_sprites.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/ostwind.dmi' + worn_icon_state = "ostwind_worn" + inhand_icon_state = "pcr" + icon_state = "pcr" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + fire_delay = 1.80 + burst_size = 5 + can_flashlight = TRUE + ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/pcr) + shaded_charge = TRUE + cell_type = /obj/item/stock_parts/cell/super + +/obj/item/ammo_casing/energy/laser/hardlight_bullet/pcr + name = "hardlight bullet pcr casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet/pcr + e_cost = 1666 // 27 damage so 12 shots. + fire_sound = 'modular_skyrat/modules/sec_haul/sound/smg_fire.ogg' + +/obj/projectile/beam/laser/hardlight_bullet/pcr + damage = 27 // Minimum damage increase to at least base /tg/ laser gun damage. + +/* TODO: Use for SolFed. +/obj/item/gun/energy/peacemaker + name = "\improper Peacemaker" + desc = "The gun that won the space frontier. Four shots, and with a long firing delay, but packs an extreme punch." + icon = 'modular_skyrat/modules/goofsec/icons/gun_sprites.dmi' + icon_state = "peacemaker" + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_OCLOTHING + fire_delay = 2 SECONDS + ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/peacemaker) + shaded_charge = TRUE + +/obj/item/ammo_casing/energy/laser/hardlight_bullet/peacemaker + name = "hardlight bullet peacemaker casing" + projectile_type = /obj/projectile/beam/laser/hardlight_bullet/peacemaker + e_cost = 250 // 4 shots. + fire_sound = 'sound/weapons/gun/revolver/shot_alt.ogg' + +/obj/projectile/beam/laser/hardlight_bullet/peacemaker + damage = 60 +*/ + diff --git a/modular_skyrat/modules/gunhud/code/gun_hud_component.dm b/modular_skyrat/modules/gunhud/code/gun_hud_component.dm new file mode 100644 index 000000000000..4c6a0e87b7ec --- /dev/null +++ b/modular_skyrat/modules/gunhud/code/gun_hud_component.dm @@ -0,0 +1,203 @@ +/datum/component/ammo_hud + var/atom/movable/screen/ammo_counter/hud + +/datum/component/ammo_hud/Initialize() + . = ..() + if(!istype(parent, /obj/item/gun) && !istype(parent, /obj/item/weldingtool)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/wake_up) + +/datum/component/ammo_hud/Destroy() + turn_off() + return ..() + +/datum/component/ammo_hud/proc/wake_up(datum/source, mob/user, slot) + SIGNAL_HANDLER + + RegisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_ITEM_DROPPED), .proc/turn_off) + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.is_holding(parent)) + if(H.hud_used) + hud = H.hud_used.ammo_counter + turn_on() + else + turn_off() + +/datum/component/ammo_hud/proc/turn_on() + SIGNAL_HANDLER + + RegisterSignal(parent, COMSIG_UPDATE_AMMO_HUD, .proc/update_hud) + + hud.turn_on() + update_hud() + +/datum/component/ammo_hud/proc/turn_off() + SIGNAL_HANDLER + + UnregisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_ITEM_DROPPED, COMSIG_UPDATE_AMMO_HUD)) + + if(hud) + hud.turn_off() + hud = null + +/datum/component/ammo_hud/proc/update_hud() + SIGNAL_HANDLER + if(istype(parent, /obj/item/gun/ballistic)) + var/obj/item/gun/ballistic/pew = parent + hud.maptext = null + hud.icon_state = "backing" + var/backing_color = COLOR_CYAN + if(!pew.magazine) + hud.set_hud(backing_color, "oe", "te", "he", "no_mag") + return + if(!pew.get_ammo()) + hud.set_hud(backing_color, "oe", "te", "he", "empty_flash") + return + + var/indicator + var/rounds = num2text(pew.get_ammo(TRUE)) + var/oth_o + var/oth_t + var/oth_h + + switch(pew.fire_select) + if(SELECT_SEMI_AUTOMATIC) + indicator = "semi" + if(SELECT_BURST_SHOT) + indicator = "burst" + if(SELECT_FULLY_AUTOMATIC) + indicator = "auto" + + if(pew.safety) + indicator = "safe" + + if(pew.jammed) + indicator = "jam" + + switch(length(rounds)) + if(1) + oth_o = "o[rounds[1]]" + if(2) + oth_o = "o[rounds[2]]" + oth_t = "t[rounds[1]]" + if(3) + oth_o = "o[rounds[3]]" + oth_t = "t[rounds[2]]" + oth_h = "h[rounds[1]]" + else + oth_o = "o9" + oth_t = "t9" + oth_h = "h9" + hud.set_hud(backing_color, oth_o, oth_t, oth_h, indicator) + + else if(istype(parent, /obj/item/gun/energy)) + var/obj/item/gun/energy/pew = parent + hud.icon_state = "eammo_counter" + hud.cut_overlays() + hud.maptext_x = -12 + var/obj/item/ammo_casing/energy/shot = pew.ammo_type[pew.select] + var/batt_percent = FLOOR(clamp(pew.cell.charge / pew.cell.maxcharge, 0, 1) * 100, 1) + var/shot_cost_percent = FLOOR(clamp(shot.e_cost / pew.cell.maxcharge, 0, 1) * 100, 1) + if(batt_percent > 99 || shot_cost_percent > 99) + hud.maptext_x = -12 + else + hud.maptext_x = -8 + if(!pew.can_shoot()) + hud.icon_state = "eammo_counter_empty" + hud.maptext = span_maptext("
[batt_percent]%
[shot_cost_percent]%
") + return + if(batt_percent <= 25) + hud.maptext = span_maptext("
[batt_percent]%
[shot_cost_percent]%
") + return + hud.maptext = span_maptext("
[batt_percent]%
[shot_cost_percent]%
") + + else if(istype(parent, /obj/item/weldingtool)) + var/obj/item/weldingtool/welder = parent + hud.maptext = null + var/backing_color = COLOR_TAN_ORANGE + hud.icon_state = "backing" + + if(welder.get_fuel() < 1) + hud.set_hud(backing_color, "oe", "te", "he", "empty_flash") + return + + var/indicator + var/fuel = num2text(welder.get_fuel()) + var/oth_o + var/oth_t + var/oth_h + + if(welder.welding) + indicator = "flame_on" + else + indicator = "flame_off" + + fuel = num2text(welder.get_fuel()) + + switch(length(fuel)) + if(1) + oth_o = "o[fuel[1]]" + if(2) + oth_o = "o[fuel[2]]" + oth_t = "t[fuel[1]]" + if(3) + oth_o = "o[fuel[3]]" + oth_t = "t[fuel[2]]" + oth_h = "h[fuel[1]]" + else + oth_o = "o9" + oth_t = "t9" + oth_h = "h9" + hud.set_hud(backing_color, oth_o, oth_t, oth_h, indicator) + + else if(istype(parent, /obj/item/gun/microfusion)) + var/obj/item/gun/microfusion/parent_gun = parent + if(!parent_gun.phase_emitter) + hud.icon_state = "microfusion_counter_no_emitter" + hud.maptext = null + return + if(parent_gun.phase_emitter.damaged) + hud.icon_state = "microfusion_counter_damaged" + hud.maptext = null + return + if(!parent_gun.cell) + hud.icon_state = "microfusion_counter_no_emitter" + hud.maptext = null + return + if(!parent_gun.cell.charge) + hud.icon_state = "microfusion_counter_no_emitter" + hud.maptext = null + return + var/phase_emitter_state = parent_gun.phase_emitter.get_heat_icon_state() + hud.icon_state = "microfusion_counter_[phase_emitter_state]" + hud.cut_overlays() + hud.maptext_x = -12 + var/obj/item/ammo_casing/energy/shot = parent_gun.microfusion_lens + var/battery_percent = FLOOR(clamp(parent_gun.cell.charge / parent_gun.cell.maxcharge, 0, 1) * 100, 1) + var/shot_cost_percent = FLOOR(clamp(shot.e_cost / parent_gun.cell.maxcharge, 0, 1) * 100, 1) + if(battery_percent > 99 || shot_cost_percent > 99) + hud.maptext_x = -12 + else + hud.maptext_x = -8 + if(!parent_gun.can_shoot()) + hud.icon_state = "microfusion_counter_no_emitter" + return + if(battery_percent <= 25) + hud.maptext = span_maptext("
[battery_percent]%
[shot_cost_percent]%
") + return + hud.maptext = span_maptext("
[battery_percent]%
[shot_cost_percent]%
") + + +/obj/item/gun/ballistic/ComponentInitialize() + . = ..() + AddComponent(/datum/component/ammo_hud) + +/obj/item/gun/energy/ComponentInitialize() + . = ..() + AddComponent(/datum/component/ammo_hud) + +/obj/item/weldingtool/ComponentInitialize() + . = ..() + AddComponent(/datum/component/ammo_hud) diff --git a/modular_skyrat/modules/gunhud/icons/gun_hud.dmi b/modular_skyrat/modules/gunhud/icons/gun_hud.dmi new file mode 100644 index 0000000000000000000000000000000000000000..6bd861100e2e161b1527aafdae9592c5607d190e GIT binary patch literal 11023 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 1, i--) + var/obj/item/stock_parts/cell/charging = charging_batteries[i] + var/newlevel = round(charging.percent() * 4 / 100) + var/mutable_appearance/charge_overlay = mutable_appearance(icon, "cchargermulti-o[newlevel]") + var/mutable_appearance/cell_overlay = mutable_appearance(icon, "cchargermulti-cell") + charge_overlay.pixel_x = 5 * (i - 1) + cell_overlay.pixel_x = 5 * (i - 1) + . += new /mutable_appearance(charge_overlay) + . += new /mutable_appearance(cell_overlay) + +/obj/machinery/cell_charger_multi/attack_hand_secondary(mob/user, list/modifiers) + if(!can_interact(user) || !charging_batteries.len) + return + to_chat(user, span_notice("You press the quick release as all the cells pop out!")) + for(var/i in charging_batteries) + removecell() + return COMPONENT_CANCEL_ATTACK_CHAIN + +/obj/machinery/cell_charger_multi/examine(mob/user) + . = ..() + if(!charging_batteries.len) + . += "There are no cells in [src]." + else + . += "There are [charging_batteries.len] cells in [src]." + for(var/obj/item/stock_parts/cell/charging in charging_batteries) + . += "There's [charging] cell in the charger, current charge: [round(charging.percent(), 1)]%." + if(in_range(user, src) || isobserver(user)) + . += span_notice("The status display reads: Charging power: [charge_rate]W.") + . += span_notice("Right click it to remove all the cells at once!") + +/obj/machinery/cell_charger_multi/attackby(obj/item/tool, mob/user, params) + if(istype(tool, /obj/item/stock_parts/cell) && !panel_open) + if(machine_stat & BROKEN) + to_chat(user, span_warning("[src] is broken!")) + return + if(!anchored) + to_chat(user, span_warning("[src] isn't attached to the ground!")) + return + var/obj/item/stock_parts/cell/inserting_cell = tool + if(inserting_cell.chargerate <= 0) + to_chat(user, span_warning("[inserting_cell] cannot be recharged!")) + return + if(charging_batteries.len >= 4) + to_chat(user, span_warning("[src] is full, and cannot hold anymore cells!")) + return + else + var/area/current_area = loc.loc // Gets our locations location, like a dream within a dream + if(!isarea(current_area)) + return + if(current_area.power_equip == 0) // There's no APC in this area, don't try to cheat power! + to_chat(user, span_warning("[src] blinks red as you try to insert the cell!")) + return + if(!user.transferItemToLoc(tool,src)) + return + + charging_batteries += tool + user.visible_message(span_notice("[user] inserts a cell into [src]."), span_notice("You insert a cell into [src].")) + update_appearance() + else + if(!charging_batteries.len && default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + return + if(default_deconstruction_crowbar(tool)) + return + if(!charging_batteries.len && default_unfasten_wrench(user, tool)) + return + return ..() + +/obj/machinery/cell_charger_multi/process(delta_time) + if(!charging_batteries.len || !anchored || (machine_stat & (BROKEN|NOPOWER))) + return + + for(var/obj/item/stock_parts/cell/charging in charging_batteries) + if(charging.percent() >= 100) + continue + var/main_draw = use_power_from_net(charge_rate * delta_time, take_any = TRUE) //Pulls directly from the Powernet to dump into the cell + if(!main_draw) + return + charging.give(main_draw) + use_power(charge_rate / 100) //use a small bit for the charger itself, but power usage scales up with the part tier + + update_appearance() + +/obj/machinery/cell_charger_multi/attack_tk(mob/user) + if(!charging_batteries.len) + return + + to_chat(user, span_notice("You telekinetically remove [removecell(user)] from [src].")) + + return COMPONENT_CANCEL_ATTACK_CHAIN + +/obj/machinery/cell_charger_multi/RefreshParts() + charge_rate = 0 // No, you cant get free charging speed! + for(var/obj/item/stock_parts/capacitor/C in component_parts) + charge_rate += charge_rate_base * C.rating + if(charge_rate >= charge_rate_max) // We've hit the charge speed cap, stop iterating. + charge_rate = charge_rate_max + break + if(charge_rate < charge_rate_base) // This should never happen; but we need to pretend it can. + charge_rate = charge_rate_base + +/obj/machinery/cell_charger_multi/emp_act(severity) + . = ..() + + if(machine_stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_CONTENTS) + return + + for(var/obj/item/stock_parts/cell/charging in charging_batteries) + charging.emp_act(severity) + +/obj/machinery/cell_charger_multi/deconstruct() + for(var/obj/item/stock_parts/cell/charging in charging_batteries) + charging.forceMove(drop_location()) + charging_batteries = null + return ..() + + +/obj/machinery/cell_charger_multi/attack_ai(mob/user) + return + +/obj/machinery/cell_charger_multi/attack_hand(mob/user, list/modifiers) + . = ..() + if(.) + return + + var/obj/item/stock_parts/cell/charging = removecell(user) + + if(!charging) + return + + user.put_in_hands(charging) + charging.add_fingerprint(user) + + user.visible_message(span_notice("[user] removes [charging] from [src]."), span_notice("You remove [charging] from [src].")) + +/obj/machinery/cell_charger_multi/proc/removecell(mob/user) + if(!charging_batteries.len) + return FALSE + var/obj/item/stock_parts/cell/charging + if(charging_batteries.len > 1 && user) + var/list/buttons = list() + for(var/obj/item/stock_parts/cell/battery in charging_batteries) + buttons["[battery] [battery.percent()]%"] = battery + var/cell_name = tgui_input_list(user, "Please choose what cell you'd like to remove.", "Remove a cell", buttons) + charging = buttons[cell_name] + else + charging = charging_batteries[1] + if(!charging) + return FALSE + charging.forceMove(drop_location()) + charging.update_appearance() + charging_batteries -= charging + update_appearance() + return charging + +/obj/machinery/cell_charger_multi/Destroy() + for(var/obj/item/stock_parts/cell/charging in charging_batteries) + QDEL_NULL(charging) + charging_batteries = null + return ..() + +/obj/item/circuitboard/machine/cell_charger_multi + name = "Multi-Cell Charger (Machine Board)" + icon_state = "engineering" + build_path = /obj/machinery/cell_charger_multi + req_components = list(/obj/item/stock_parts/capacitor = 4) + needs_anchored = FALSE + + +/datum/design/board/cell_charger_multi + name = "Machine Design (Multi-Cell Charger Board)" + desc = "The circuit board for a multi-cell charger." + id = "multi_cell_charger" + build_path = /obj/item/circuitboard/machine/cell_charger_multi + category = list ("Misc. Machinery") diff --git a/modular_skyrat/modules/robohand/code/robohand.dm b/modular_skyrat/modules/robohand/code/robohand.dm new file mode 100644 index 000000000000..60cc7d434643 --- /dev/null +++ b/modular_skyrat/modules/robohand/code/robohand.dm @@ -0,0 +1,112 @@ +#define CALIBRE_14MM "14mm" + +/* +* Malorian Arms 3516 14MM +* If you have this, you're a badass. +*/ + +/obj/item/gun/ballistic/automatic/pistol/robohand + name = "Malorian Arms 3516" + desc = "The Malorian Arms 3516 is a 14mm heavy pistol, sporting a titanium frame and unique wooden grip. A custom Dyna-porting and \ + direct integral cyber-interlink means only someone with a cyberarm and smartgun link can take full advantage of the pistol's features." + icon = 'modular_skyrat/modules/robohand/icons/3516.dmi' + icon_state = "3516" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/m14mm + can_suppress = FALSE + fire_sound = 'modular_skyrat/modules/robohand/sound/fire2.ogg' + load_sound = 'modular_skyrat/modules/robohand/sound/reload.ogg' + load_empty_sound = 'modular_skyrat/modules/robohand/sound/reload.ogg' + eject_sound = 'modular_skyrat/modules/robohand/sound/release.ogg' + eject_empty_sound = 'modular_skyrat/modules/robohand/sound/release.ogg' + vary_fire_sound = FALSE + rack_sound = 'modular_skyrat/modules/robohand/sound/slide.ogg' + fire_sound_volume = 100 + bolt_wording = "fuckin' slide" + reload_time = 0 //FAST AS FUCK BOIS! + +//Gun actions + +//The gun cannot shoot if you do not have a cyborg arm. +/obj/item/gun/ballistic/automatic/pistol/robohand/afterattack(atom/target, mob/living/user, flag, params) + //This is where we are checking if the user has a cybernetic arm to USE the gun. ROBOHAND HAS A ROBO HAND + if(ishuman(user)) + return ..() + var/mob/living/carbon/human/human_user = user + var/obj/item/bodypart/selected_hand = human_user.get_active_hand() + if(selected_hand.status != BODYPART_ROBOTIC) + to_chat(user, span_warning("You can't seem to figure out how to use [src], perhaps you need to check the manual?")) + return + . = ..() + +/obj/item/gun/ballistic/automatic/pistol/robohand/insert_magazine(mob/user, obj/item/ammo_box/magazine/inserted_mag, display_message) + if(!istype(inserted_mag, mag_type)) + to_chat(user, span_warning("\The [inserted_mag] doesn't seem to fit into \the [src]...")) + return FALSE + if(!user.transferItemToLoc(inserted_mag, src)) + to_chat(user, span_warning("You cannot seem to get \the [src] out of your hands!")) + return FALSE + magazine = inserted_mag + if(display_message) + to_chat(user, span_notice("You load a new [magazine_wording] into \the [src].")) + playsound(src, load_empty_sound, load_sound_volume, load_sound_vary) + if(bolt_type == BOLT_TYPE_OPEN && !bolt_locked) + chamber_round(TRUE) + drop_bolt(user) + update_appearance() + animate(src, 0.2 SECONDS, 1, transform = turn(matrix(), 120)) //Le johnny robohand woosh woosh twirl + animate(time = 0.2 SECONDS, transform = turn(matrix(), 240)) + animate(time = 0.2 SECONDS, transform = null) + return TRUE + +/obj/item/gun/ballistic/automatic/pistol/robohand/eject_magazine(mob/user, display_message, obj/item/ammo_box/magazine/tac_load) + if(bolt_type == BOLT_TYPE_OPEN) + chambered = null + if(magazine.ammo_count()) + playsound(src, eject_sound, eject_sound_volume, eject_sound_volume) //This is why we've copied this proc, it should play the eject sound when ejecting. + else + playsound(src, eject_empty_sound, eject_sound_volume, eject_sound_volume) + magazine.forceMove(drop_location()) + var/obj/item/ammo_box/magazine/old_mag = magazine + if(tac_load) + if (insert_magazine(user, tac_load, FALSE)) + to_chat(user, span_notice("You perform an elite tactical reload on \the [src].")) + else + to_chat(user, span_warning("You dropped the old [magazine_wording], but the new one doesn't fit. How embarassing.")) + magazine = null + else + magazine = null + user.put_in_hands(old_mag) + old_mag.update_appearance() + if(display_message) + to_chat(user, span_notice("You pull the [magazine_wording] out of \the [src].")) + update_appearance() + animate(src, transform = turn(matrix(), 120), time = 2, loop = 1) //Le johnny robohand again + animate(transform = turn(matrix(), 240), time = 2) + animate(transform = null, time = 2) + +//Magazine stuff + +/obj/item/ammo_box/magazine/m14mm + name = "pistol magazine (14mm)" + icon = 'modular_skyrat/modules/robohand/icons/3516_mag.dmi' + icon_state = "14mm" + base_icon_state = "14mm" + ammo_type = /obj/item/ammo_casing/c14mm + caliber = CALIBRE_14MM + max_ammo = 10 + multiple_sprites = AMMO_BOX_FULL_EMPTY + +/obj/item/ammo_casing/c14mm + name = "14mm bullet casing" + desc = "A 14mm bullet casing. Badass." + caliber = CALIBRE_14MM + projectile_type = /obj/projectile/bullet/c14mm + +/obj/projectile/bullet/c14mm + name = "14mm bullet" + damage = 60 + embedding = list(embed_chance = 90, fall_chance = 3, jostle_chance = 4, ignore_throwspeed_threshold = TRUE, pain_stam_pct = 0.4, pain_mult = 5, jostle_pain_mult = 9, rip_time = 10) + dismemberment = 50 + pierces = 1 + projectile_piercing = PASSCLOSEDTURF|PASSGRILLE|PASSGLASS diff --git a/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm b/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm new file mode 100644 index 000000000000..4af51d2c4fa3 --- /dev/null +++ b/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm @@ -0,0 +1,95 @@ +/obj/effect/spawner/armory_spawn + icon = 'modular_skyrat/modules/sec_haul/icons/guns/spawner.dmi' + icon_state = "random_gun" + layer = OBJ_LAYER + /// How many guns will be spawned here. + var/gun_count = 1 + /// If the same gun can be spawned twice. + var/gun_doubles = TRUE + /// A list of possible guns to spawn. + var/list/guns + /// Do we fan out the items spawned for a natural effect? + var/fan_out_items = TRUE + /// How many mags per gun do we spawn, if it takes magazines. + var/mags_to_spawn = 3 + /// Do we want to angle it so that it is horizontal? + var/vertical_guns = TRUE + + +/obj/effect/spawner/armory_spawn/Initialize(mapload) + ..() + if(guns) + var/current_offset = -10 + var/offset_percent = 20 / guns.len + for(var/gun in guns) // 11/20/21: Gun spawners now spawn 1 of each gun in it's list no matter what, so as to reduce the RNG of the armory stock. + var/obj/item/gun/spawned_gun = new gun(loc) + + if(vertical_guns) + spawned_gun.place_on_rack() + spawned_gun.pixel_x = current_offset + current_offset += offset_percent + + if(istype(spawned_gun, /obj/item/gun/ballistic)) + var/obj/item/gun/ballistic/spawned_ballistic_gun = spawned_gun + if(spawned_ballistic_gun.magazine && !istype(spawned_ballistic_gun.magazine, /obj/item/ammo_box/magazine/internal)) + var/obj/item/storage/box/ammo_box/spawned_box = new(loc) + spawned_box.name = "ammo box - [spawned_ballistic_gun.name]" + for(var/i in 1 to mags_to_spawn) + new spawned_ballistic_gun.mag_type (spawned_box) + + if(istype(spawned_gun, /obj/item/gun/microfusion)) + var/obj/item/gun/microfusion/spawned_microfusion_gun = spawned_gun + var/obj/item/storage/box/ammo_box/microfusion/spawned_box = new(loc) + for(var/i in 1 to mags_to_spawn) + new spawned_microfusion_gun.cell_type (spawned_box) + + return INITIALIZE_HINT_QDEL + +/obj/effect/spawner/armory_spawn/shotguns + icon_state = "random_shotgun" + gun_count = 4 + guns = list( + /obj/item/gun/ballistic/shotgun/m23, + /obj/item/gun/ballistic/shotgun/automatic/as2, + /obj/item/gun/ballistic/shotgun/sas14, + ) + +/obj/structure/closet/ammunitionlocker/useful/PopulateContents() + new /obj/item/storage/box/rubbershot_14gauge(src) + new /obj/item/storage/box/rubbershot_14gauge(src) + new /obj/item/storage/box/rubbershot_14gauge(src) + new /obj/item/storage/box/rubbershot_14gauge(src) + +//////////////////////////AMMO BOXES +/obj/item/storage/box/ammo_box + name = "ammo box" + desc = "A box filled with ammunition." + icon_state = "boxhrifle" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/ammoboxes.dmi' + illustration = null + layer = 2.9 + +/obj/item/storage/box/ammo_box/microfusion + name = "microfusion cell container" + desc = "A box filled with microfusion cells." + +/obj/item/storage/box/ammo_box/microfusion/PopulateContents() + new /obj/item/storage/bag/ammo(src) + + +/obj/effect/spawner/armory_spawn/centcom_rifles + icon_state = "random_rifle" + gun_count = 2 + guns = list( + /obj/item/gun/ballistic/automatic/ar, + /obj/item/gun/ballistic/automatic/assault_rifle/m16, + /obj/item/gun/ballistic/automatic/cfa_rifle, + ) + +/obj/effect/spawner/armory_spawn/centcom_lasers + gun_count = 2 + guns = list( + /obj/item/gun/energy/laser, + /obj/item/gun/energy/laser/cfa_paladin, + /obj/item/gun/energy/e_gun, + ) diff --git a/monkestation/code/modules/gunsgalore/code/guns/ballistic_master.dm b/monkestation/code/modules/gunsgalore/code/guns/ballistic_master.dm new file mode 100644 index 000000000000..d24370253500 --- /dev/null +++ b/monkestation/code/modules/gunsgalore/code/guns/ballistic_master.dm @@ -0,0 +1,272 @@ +/obj/item/gun/ballistic + /// Does this gun have mag and nomag on mob variance? + var/alt_icons = FALSE + /// What the icon state is for the on-back guns + var/alt_icon_state + /// Realistic guns that use reliability and dirt + var/realistic = FALSE + /// Is it jammed? + var/jammed = FALSE + /// How dirty a gun is. + var/dirt_level = 0 + /// Tied in with how good a gun is, if firing it causes a lot of dirt to form, then change this accordingly. + var/dirt_modifier = 0.1 + /// Used when calculating if a gun will jam or not. + var/jam_chance = 0 + /// Used when calculating how long a gun takes to unjam. + var/unjam_time = 0 + /// Tracking gun base spred. + var/base_spread = 0 + /// How used this gun is. + var/durability = 100 + /// How quickly a gun will degrade. 0.1 = 1000 shots. Edit this to change a guns base reliability. + var/durability_factor = 0.1 + /// How long it takes to reload a magazine. + var/reload_time = 2 SECONDS + + +/obj/item/gun/ballistic/Initialize() + . = ..() + if(realistic) + base_spread = spread + +/obj/item/gun/ballistic/ComponentInitialize() + . = ..() + if(alt_icons) + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/gun/ballistic/update_overlays() + . = ..() + if(alt_icons) + if(!magazine) + if(alt_icon_state) + inhand_icon_state = "[alt_icon_state]_nomag" + worn_icon_state = "[alt_icon_state]_nomag" + else + inhand_icon_state = "[initial(icon_state)]_nomag" + worn_icon_state = "[initial(icon_state)]_nomag" + else + if(alt_icon_state) + inhand_icon_state = "[alt_icon_state]" + worn_icon_state = "[alt_icon_state]" + else + inhand_icon_state = "[initial(icon_state)]" + worn_icon_state = "[initial(icon_state)]" + +/obj/item/gun/ballistic/insert_magazine(mob/user, obj/item/ammo_box/magazine/AM, display_message) + if(reload_time && !HAS_TRAIT(user, TRAIT_INSTANT_RELOAD) && magazine) //This only happens when you're attempting a tactical reload, e.g. there's a mag already inserted. + to_chat(user, span_notice("You start to insert the magazine into [src]!")) + if(!do_after(user, reload_time, src)) + to_chat(user, span_danger("You fail to insert the magazine into [src]!")) + return + . = ..() + +/obj/item/gun/ballistic/assault_rifle + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magout.ogg' + eject_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magout.ogg' + +/obj/item/gun/ballistic/battle_rifle + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/batrifle_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/batrifle_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/batrifle_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/batrifle_magout.ogg' + eject_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/batrifle_magout.ogg' + +/obj/item/gun/ballistic/machine_gun + rack_sound = 'sound/weapons/gun/l6/l6_rack.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/lmg_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/lmg_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/lmg_magout.ogg' + eject_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/lmg_magout.ogg' + +/obj/item/gun/ballistic/sniper_rifle + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/sfrifle_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/sfrifle_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/sfrifle_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/sfrifle_magout.ogg' + eject_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/sfrifle_magout.ogg' + +/obj/item/gun/ballistic/submachine_gun + rack_sound = 'sound/weapons/gun/smg/smgrack.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magout.ogg' + eject_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magout.ogg' + +/obj/item/gun/ballistic/proc/jam(unjam = FALSE, mob/living/user) + if(unjam && jammed != TRUE) + unjam_time = clamp((jam_chance*10)/(durability/10), 0, 50) + jammed = TRUE + playsound(src, 'sound/effects/stall.ogg', 60, TRUE) + to_chat(user, span_danger("The [src] jams!")) + SEND_SIGNAL(src, COMSIG_GUN_JAMMED) + else if(jammed) + to_chat(user, "You start to unjam the bolt!") + if(do_after(user, unjam_time)) + jammed = FALSE + to_chat(user, span_notice("You unjam the [src]'s bolt.")) + playsound(src, 'sound/weapons/gun/l6/l6_rack.ogg', 60, TRUE) + +/obj/item/gun/ballistic/can_trigger_gun(mob/living/user) + . = ..() + if(realistic && jammed) + to_chat(user, span_warning("[src] is jammed!")) + return FALSE + +/obj/item/gun/ballistic/shoot_live_shot(mob/living/user, pointblank, atom/pbtarget, message) + if(realistic) + if(jammed) + return FALSE + + dirt_level += dirt_modifier + + durability = clamp(durability -= durability_factor, 1, 1000) + + jam_chance = dirt_level/5 + + spread = base_spread + ((jam_chance / durability)*100) + + switch(FLOOR(durability, 1)) + if(0 to 9) + if(prob(90)) + jam(user) + return FALSE + if(10 to 29) + if(prob(10)) + jam(user) + return FALSE + if(30 to 49) + if(prob(5)) + jam(user) + return FALSE + + if(dirt_level > 30 && prob(jam_chance)) + jam(user) + return FALSE + . = ..() + +/obj/item/gun/ballistic/AltClick(mob/user) + if(realistic) + if(!user.canUseTopic(src)) + return + if(jammed) + jam(TRUE, user) + return + if(!internal_magazine && magazine && user.Adjacent(src)) + eject_magazine(user) + . = ..() + +/obj/item/gun/ballistic/examine(mob/user) + . = ..() + if(realistic) + switch(FLOOR(dirt_level, 1)) + if(0 to 10) + . += "It looks clean." + if(11 to 30) + . += "It looks slightly dirty." + if(31 to 50) + . += "It looks dirty." + if(51 to 70) + . += "It looks very dirty." + else + . += span_warning("It is filthy!") + + switch(FLOOR(durability, 1)) + if(0 to 9) + . += span_warning("It is falling apart!") + if(10 to 29) + . += span_warning("It looks battle scarred!") + if(30 to 49) + . += "It looks well worn." + if(50 to 69) + . += "It has minimal wear." + else + . += "It looks factory new." + + if(jammed) + . += span_warning("It is jammed, alt+click it to unjam it!") + else if(durability < 10) + . += span_warning("It is barely functioning!") + else + . += "It is functioning normally." + +/obj/item/gun/ballistic/attackby(obj/item/A, mob/user, params) + . = ..() + if(realistic) + if(istype(A, /obj/item/stack/sheet/cloth)) + var/obj/item/stack/sheet/cloth/C = A + if(!dirt_level) + to_chat(user, "The [src] is already spotless!") + else + if(C.amount < 5) + to_chat(user, "There's not enough [C] to clean the gun with!") + else + to_chat(user, span_notice("You start cleaning the [src].")) + if(do_after(user, 20 SECONDS)) + dirt_level -= 35 + if(dirt_level < 0) + dirt_level = 0 + C.use(5) + to_chat(user, span_notice("You clean the [src], improving it's reliability!")) + if(istype(A, /obj/item/gun_maintenance_supplies)) + to_chat(user, span_notice("You start maintaining the [src].")) + if(do_after(user, 10 SECONDS, target = src)) + user.visible_message(span_notice("[user] finishes maintenance of [src].")) + dirt_level = 0 + qdel(A) + +//CRATES + +//all that shit +/obj/structure/closet/crate/secure/weapon/ww2 + name = "ww2 weapons crate" + desc = "A secure weapons crate. Looks like it's from the old-era world war 2." + icon_state = "weaponcrate" + +/obj/structure/closet/crate/secure/weapon/ww2/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/battle_rifle/fg42(src) + new /obj/item/ammo_box/magazine/fg42(src) + new /obj/item/gun/ballistic/automatic/assault_rifle/akm(src) + new /obj/item/ammo_box/magazine/akm(src) + new /obj/item/gun/ballistic/automatic/assault_rifle/m16(src) + new /obj/item/ammo_box/magazine/m16(src) + new /obj/item/gun/ballistic/automatic/mg34(src) + new /obj/item/ammo_box/magazine/mg34(src) + new /obj/item/gun/ballistic/automatic/submachine_gun/mp40(src) + new /obj/item/ammo_box/magazine/mp40(src) + new /obj/item/gun/ballistic/automatic/assault_rifle/stg(src) + new /obj/item/ammo_box/magazine/stg(src) + new /obj/item/gun/ballistic/automatic/submachine_gun/ppsh(src) + new /obj/item/ammo_box/magazine/ppsh(src) + new /obj/item/gun/ballistic/automatic/submachine_gun/pps(src) + new /obj/item/ammo_box/magazine/pps(src) + +/obj/structure/closet/crate/secure/weapon/ww2 + name = "modern weapons crate" + desc = "A secure weapons crate. Looks like it's from the 25th century." + icon_state = "weaponcrate" + +/obj/structure/closet/crate/secure/weapon/ww2/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/battle_rifle/fg42/modern(src) + new /obj/item/ammo_box/magazine/fg42(src) + new /obj/item/gun/ballistic/automatic/assault_rifle/akm/modern(src) + new /obj/item/ammo_box/magazine/akm(src) + new /obj/item/gun/ballistic/automatic/assault_rifle/m16/modern(src) + new /obj/item/ammo_box/magazine/m16(src) + new /obj/item/gun/ballistic/automatic/submachine_gun/mp40/modern(src) + new /obj/item/ammo_box/magazine/mp40(src) + new /obj/item/gun/ballistic/automatic/assault_rifle/stg/modern(src) + new /obj/item/ammo_box/magazine/stg(src) + new /obj/item/gun/ballistic/automatic/submachine_gun/ppsh/modern(src) + new /obj/item/ammo_box/magazine/ppsh(src) + +/obj/effect/temp_visual/dir_setting/firing_effect + light_system = MOVABLE_LIGHT + light_range = 2 + light_power = 1 + light_color = LIGHT_COLOR_FIRE diff --git a/monkestation/code/modules/gunsgalore/code/guns/skillchip.dm b/monkestation/code/modules/gunsgalore/code/guns/skillchip.dm new file mode 100644 index 000000000000..542114b5c3c0 --- /dev/null +++ b/monkestation/code/modules/gunsgalore/code/guns/skillchip.dm @@ -0,0 +1,9 @@ +/obj/item/skillchip/chameleon/reload + name = "T.A.C.T.I.C00L skillchip" + desc = "If used, allows the user to perform tactical and instant reloads on all weapons with a magazine." + auto_traits = list(TRAIT_INSTANT_RELOAD) + skill_name = "Tactical Reloading" + skill_description = "Fine tune motor skills when performing reloads on weapons to reduce time taken." + skill_icon = "sitemap" + activate_message = span_notice("You suddenly learn the art of tactical reloading.") + deactivate_message = span_danger("You suddenly lose the ability to tactically reload.") diff --git a/monkestation/code/modules/microfusion/code/_microfusion_defines.dm b/monkestation/code/modules/microfusion/code/_microfusion_defines.dm new file mode 100644 index 000000000000..2abc005ea7ef --- /dev/null +++ b/monkestation/code/modules/microfusion/code/_microfusion_defines.dm @@ -0,0 +1,52 @@ +/// The amount of cell charge drained during a drain failure. +#define MICROFUSION_CELL_DRAIN_FAILURE 500 +/// The heavy EMP range for when a cell suffers an EMP failure. +#define MICROFUSION_CELL_EMP_HEAVY_FAILURE 2 +/// The light EMP range for when a cell suffers an EMP failure. +#define MICROFUSION_CELL_EMP_LIGHT_FAILURE 4 +/// The radiation range for when a cell suffers a radiation failure. +#define MICROFUSION_CELL_RADIATION_RANGE_FAILURE 1 + +/// The lower most time for a microfusion cell meltdown. +#define MICROFUSION_CELL_FAILURE_LOWER 10 SECONDS +/// The upper most time for a microfusion cell meltdown. +#define MICROFUSION_CELL_FAILURE_UPPER 15 SECONDS + +/// A charge drain failure. +#define MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN 1 +/// A small explosion failure. +#define MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION 2 +/// EMP failure. +#define MICROFUSION_CELL_FAILURE_TYPE_EMP 3 +/// Radiation failure. +#define MICROFUSION_CELL_FAILURE_TYPE_RADIATION 4 + +/// Returned when the phase emtiter process is successful. +#define SHOT_SUCCESS "success" +/// Returned when a gun is fired but there is no phase emitter. +#define SHOT_FAILURE_NO_EMITTER "No phase emitter installed!" + +/// The error message returned when the phase emitter is processed but damaged. +#define PHASE_FAILURE_DAMAGED "PHASE EMITTER: Emitter damaged!" +/// The error message returned when the phase emitter has reached it's htermal throttle. +#define PHASE_FAILURE_THROTTLE "PHASE EMITTER: Thermal throttle active!" + +/// The heat dissipation bonus of an emitter being in space! +#define PHASE_HEAT_DISSIPATION_BONUS_SPACE 30 +/// The heat dissipation bonus of an emitter being in air! +#define PHASE_HEAT_DISSIPATION_BONUS_AIR 10 + +// Slot defines for the gun. +/// The gun barrel slot. +#define GUN_SLOT_BARREL "barrel" +/// The gun underbarrel slot. +#define GUN_SLOT_UNDERBARREL "underbarrel" +/// The gun rail slot. +#define GUN_SLOT_RAIL "rail" +/// Unique slots, can hold as many as you want. +#define GUN_SLOT_UNIQUE "unique" + +/// Max name size for changing names +#define GUN_MAX_NAME_CHARS 20 +/// Min name size for changing names +#define GUN_MIN_NAME_CHARS 3 diff --git a/monkestation/code/modules/microfusion/code/cargo_stuff.dm b/monkestation/code/modules/microfusion/code/cargo_stuff.dm new file mode 100644 index 000000000000..b29213fa2325 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/cargo_stuff.dm @@ -0,0 +1,51 @@ +/datum/supply_pack/security/armory/mcr01 + name = "MCR-01 Microfusion Crate" + desc = "Micron Control Systems Incorporated supplied MCR-01 Microfusion weapons platform. Comes with 4 guns and 4 advanced cells!" + cost = CARGO_CRATE_VALUE * 20 + contains = list( + /obj/item/gun/microfusion/mcr01/advanced, + /obj/item/gun/microfusion/mcr01/advanced, + /obj/item/gun/microfusion/mcr01/advanced, + /obj/item/gun/microfusion/mcr01/advanced, + /obj/item/storage/box/ammo_box/microfusion/advanced, + /obj/item/storage/box/ammo_box/microfusion/advanced, + /obj/item/storage/box/ammo_box/microfusion/advanced, + /obj/item/storage/box/ammo_box/microfusion/advanced, + ) + crate_name = "MCR-01 Microfusion Crate" + +/datum/supply_pack/security/microfusion + name = "Assorted Microfusion Cell Crate" + desc = "Micron Control Systems Incorporated supplied Microfusion cells and attachments!" + cost = CARGO_CRATE_VALUE * 5 + contains = list( + /obj/item/stock_parts/cell/microfusion/advanced, + /obj/item/stock_parts/cell/microfusion/advanced, + /obj/item/stock_parts/cell/microfusion/advanced, + /obj/item/stock_parts/cell/microfusion/advanced, + /obj/item/stock_parts/cell/microfusion/advanced, + /obj/item/stock_parts/cell/microfusion/advanced, + /obj/item/microfusion_cell_attachment/rechargeable, + /obj/item/microfusion_cell_attachment/rechargeable, + /obj/item/microfusion_cell_attachment/rechargeable, + /obj/item/microfusion_cell_attachment/rechargeable, + /obj/item/microfusion_cell_attachment/rechargeable, + /obj/item/microfusion_cell_attachment/rechargeable, + ) + crate_name = "Microfusion Cell Crate" + +/datum/supply_pack/security/mcr01_attachments + name = "MCR-01 Military Attachments Crate" + desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments!" + cost = CARGO_CRATE_VALUE * 15 + contains = list( + /obj/item/microfusion_gun_attachment/scope, + /obj/item/microfusion_gun_attachment/scope, + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/rail, + /obj/item/microfusion_gun_attachment/rail, + /obj/item/microfusion_gun_attachment/repeater, + /obj/item/microfusion_gun_attachment/repeater, + ) + crate_name = "MCR-01 Military Attachments Crate" diff --git a/monkestation/code/modules/microfusion/code/gun_types.dm b/monkestation/code/modules/microfusion/code/gun_types.dm new file mode 100644 index 000000000000..4745258a564a --- /dev/null +++ b/monkestation/code/modules/microfusion/code/gun_types.dm @@ -0,0 +1,41 @@ +/obj/item/gun/microfusion/mcr01 + name = "MCR-01" + desc = "An advanced, modular energy weapon produced by Allstar Lasers Incorporated. These cutting edge weapons differ from traditional beam weaponry in producing individual bolts, as well as utilizing hotswapped cells rather than being tied to immobile power sources." + icon_state = "mcr01" + inhand_icon_state = "mcr01" + shaded_charge = TRUE + +/// Gun for cargo crates. +/obj/item/gun/microfusion/mcr01/advanced + name = "Advanced MCR-01" + cell_type = /obj/item/stock_parts/cell/microfusion/advanced + phase_emitter_type = /obj/item/microfusion_phase_emitter/advanced + +/obj/item/gun/microfusion/mcr01/nanocarbon + name = "Nanocarbon Destroyer" + desc = "The pinnacle of the Nanocarbon weapon line. This weapon is the ultimate in power and performance. It is capable of firing a wide variety of beams, including a wide range of energy types, and is capable of firing a wide variety of frequencies." + icon_state = "mcr01" + inhand_icon_state = "mcr01" + shaded_charge = TRUE + +/obj/item/storage/box/ammo_box/microfusion/advanced + name = "advanced microfusion cell container" + desc = "A box filled with microfusion cells." + +/obj/item/storage/box/ammo_box/microfusion/advanced/PopulateContents() + new /obj/item/storage/bag/ammo(src) + new /obj/item/stock_parts/cell/microfusion/advanced(src) + new /obj/item/stock_parts/cell/microfusion/advanced(src) + new /obj/item/stock_parts/cell/microfusion/advanced(src) + +//////////////MICROFUSION SPAWNERS +/obj/effect/spawner/armory_spawn/microfusion + icon_state = "random_rifle" + gun_count = 4 + guns = list( + /obj/item/gun/microfusion/mcr01, + /obj/item/gun/microfusion/mcr01, + /obj/item/gun/microfusion/mcr01, + /obj/item/gun/microfusion/mcr01, + ) + diff --git a/monkestation/code/modules/microfusion/code/microfusion_cell.dm b/monkestation/code/modules/microfusion/code/microfusion_cell.dm new file mode 100644 index 000000000000..f0953d7d9590 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/microfusion_cell.dm @@ -0,0 +1,189 @@ +/* +MICROFUSION CELL SYSTEM + +Microfusion cells are small battery units that house controlled nuclear fusion within, and that fusion is converted into useable energy. + +They cannot be charged as standard, and require upgrades to do so. + +These are basically advanced cells. +*/ + +/obj/item/stock_parts/cell/microfusion //Just a standard cell. + name = "microfusion cell" + desc = "A standard-issue microfusion cell, produced by Micron Control Systems. Smaller than a can of soda, these fulfill the need for a power source where plugging into a recharger is inconvenient or unavailable; although they will eventually run dry due to being shipped without a fuel source." + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_cells.dmi' + charge_overlay_icon = 'modular_skyrat/modules/microfusion/icons/microfusion_cells.dmi' + icon_state = "microfusion" + w_class = WEIGHT_CLASS_NORMAL + maxcharge = 1200 //12 shots + chargerate = 0 //Standard microfusion cells can't be recharged, they're single use. + microfusion_readout = TRUE + + /// A hard referenced list of upgrades currently attached to the weapon. + var/list/attachments = list() + /// Are we melting down? For icon stuffs. + var/meltdown = FALSE + /// How many upgrades can you have on this cell? + var/max_attachments = 1 + /// Hard ref to the parent gun. + var/obj/item/gun/microfusion/parent_gun + /// Do we play an alarm when empty? + var/empty_alarm = TRUE + /// What sound do we play when empty? + var/empty_alarm_sound = 'sound/weapons/gun/general/empty_alarm.ogg' + /// Do we have the self charging upgrade? + var/self_charging = FALSE + +/obj/item/stock_parts/cell + /// Is this cell stabilised? (used in microfusion guns) + var/stabilised = FALSE + /// Do we show the microfusion readout instead of KJ? + var/microfusion_readout = FALSE + +/obj/item/stock_parts/cell/microfusion/Destroy() + if(attachments.len) + for(var/obj/item/iterating_item as anything in attachments) + iterating_item.forceMove(get_turf(src)) + attachments = null + parent_gun = null + return ..() + +/obj/item/stock_parts/cell/microfusion/attackby(obj/item/attacking_item, mob/living/user, params) + if(istype(attacking_item, /obj/item/microfusion_cell_attachment)) + add_attachment(attacking_item, user) + return + return ..() + +/obj/item/stock_parts/cell/microfusion/emp_act(severity) + var/prob_percent = charge / 100 * severity + if(prob(prob_percent) && !meltdown && !stabilised && parent_gun) + process_instability() + +/obj/item/stock_parts/cell/microfusion/use(amount) + if(charge >= amount) + var/check_if_empty = charge - amount + if(check_if_empty < amount && empty_alarm && !self_charging) + playsound(src, empty_alarm_sound, 50) + return ..() + +/obj/item/stock_parts/cell/microfusion/proc/process_instability() + var/seconds_to_explode = rand(MICROFUSION_CELL_FAILURE_LOWER, MICROFUSION_CELL_FAILURE_UPPER) + meltdown = TRUE + say("Malfunction in [seconds_to_explode] seconds!") + playsound(src, 'sound/machines/warning-buzzer.ogg', 30, FALSE, FALSE) + add_filter("rad_glow", 2, list("type" = "outline", "color" = "#ff5e0049", "size" = 2)) + addtimer(CALLBACK(src, .proc/process_failure), seconds_to_explode) + +/obj/item/stock_parts/cell/microfusion/proc/process_failure() + var/fuckup_type = rand(1, 4) + remove_filter("rad_glow") + playsound(src, 'sound/effects/spray.ogg', 70) + switch(fuckup_type) + if(MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN) + charge = clamp(charge - MICROFUSION_CELL_DRAIN_FAILURE, 0, maxcharge) + if(MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION) + explode() + if(MICROFUSION_CELL_FAILURE_TYPE_EMP) + empulse(get_turf(src), MICROFUSION_CELL_EMP_HEAVY_FAILURE, MICROFUSION_CELL_EMP_LIGHT_FAILURE, FALSE) + if(MICROFUSION_CELL_FAILURE_TYPE_RADIATION) + radiation_pulse(src, MICROFUSION_CELL_RADIATION_RANGE_FAILURE, RAD_MEDIUM_INSULATION) + meltdown = FALSE + +/obj/item/stock_parts/cell/microfusion/update_overlays() + . = ..() + for(var/obj/item/microfusion_cell_attachment/microfusion_cell_attachment as anything in attachments) + . += microfusion_cell_attachment.attachment_overlay_icon_state + +/obj/item/stock_parts/cell/microfusion/screwdriver_act(mob/living/user, obj/item/tool) + if(!attachments.len) + to_chat(user, span_danger("There are no attachments to remove!")) + return + remove_attachments() + playsound(src, 'sound/items/screwdriver.ogg', 70, TRUE) + to_chat(user, span_notice("You remove the upgrades from [src].")) + +/obj/item/stock_parts/cell/microfusion/process(delta_time) + for(var/obj/item/microfusion_cell_attachment/microfusion_cell_attachment as anything in attachments) + microfusion_cell_attachment.process_attachment(src, delta_time) + +/obj/item/stock_parts/cell/microfusion/examine(mob/user) + . = ..() + . += span_notice("It can hold [max_attachments] attachment(s).") + if(attachments.len) + for(var/obj/item/microfusion_cell_attachment/microfusion_cell_attachment as anything in attachments) + . += span_notice("It has a [microfusion_cell_attachment.name] installed.") + . += span_notice("Use a screwdriver to remove the attachments.") + +/obj/item/stock_parts/cell/microfusion/proc/add_attachment(obj/item/microfusion_cell_attachment/microfusion_cell_attachment, mob/living/user) + if(attachments.len >= max_attachments) + to_chat(user, span_warning("[src] cannot fit any more attachments!")) + return FALSE + if(is_type_in_list(microfusion_cell_attachment, attachments)) + to_chat(user, span_warning("[src] already has [microfusion_cell_attachment] installed!")) + return FALSE + attachments += microfusion_cell_attachment + microfusion_cell_attachment.forceMove(src) + microfusion_cell_attachment.add_attachment(src) + to_chat(user, span_notice("You successfully install [microfusion_cell_attachment] onto [src]!")) + playsound(src, 'sound/effects/structure_stress/pop2.ogg', 70, TRUE) + update_appearance() + return TRUE + +/obj/item/stock_parts/cell/microfusion/proc/remove_attachments() + for(var/obj/item/microfusion_cell_attachment/microfusion_cell_attachment in attachments) + microfusion_cell_attachment.remove_attachment(src) + microfusion_cell_attachment.forceMove(get_turf(src)) + attachments -= microfusion_cell_attachment + update_appearance() + +/datum/crafting_recipe/makeshift/microfusion_cell + name = "Makeshift Microfusion Cell" + tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER, TOOL_WELDER) + result = /obj/item/stock_parts/cell/microfusion/makeshift + reqs = list(/obj/item/trash/can = 1, + /obj/item/stack/sheet/iron = 1, + /obj/item/stack/cable_coil = 1) + time = 12 SECONDS + category = CAT_MISC + +//WHY WOULD YOU MAKE THIS? +/obj/item/stock_parts/cell/microfusion/makeshift + name = "makeshift microfusion cell" + desc = "An... Apparatus, comprised of an everyday aluminum can with several civilian-grade batteries tightly packed together and plugged in. This vaguely resembles a microfusion cell, if you tilt your head to a precise fifty degree angle. While the effects on enemy combatants may be dubious, it will certainly do incredible damage to the gun's warranty. What the hell were you thinking when you came up with this?" + icon_state = "microfusion_makeshift" + maxcharge = 600 + max_attachments = 0 + /// The probability of the cell failing + var/fail_prob = 10 + +/obj/item/stock_parts/cell/microfusion/makeshift/use(amount) + if(prob(fail_prob)) + process_instability() + return ..() + +/obj/item/stock_parts/cell/microfusion/enhanced + name = "enhanced microfusion cell" + desc = "A second generation microfusion cell, weighing about the same as the standard-issue cell and having the same space for attachments; however, it has a higher capacity." + icon_state = "microfusion_enhanced" + maxcharge = 1500 + +/obj/item/stock_parts/cell/microfusion/advanced + name = "advanced microfusion cell" + desc = "A third generation microfusion cell, boasting a much higher shot count. Additionally, these come with support for up to three modifications to the cell itself." + icon_state = "microfusion_advanced" + maxcharge = 1700 + max_attachments = 3 + +/obj/item/stock_parts/cell/microfusion/bluespace + name = "bluespace microfusion cell" + desc = "A fourth generation microfusion cell, employing bluespace technology to store power in a medium that's bigger on the inside. This has the highest capacity of any man-portable cell, and has flexibility for four different attachments to the cell itself." + icon_state = "microfusion_bluespace" + maxcharge = 2000 + max_attachments = 4 + +/obj/item/stock_parts/cell/microfusion/nanocarbon + name = "nanocarbon fusion cell" + desc = "This cell combines both top-of-the-line nanotech and advanced microfusion power to brute force the most common issue of Nanotrasen Asset Protection operatives, ammunition, through sheer volume. Intended for use with Nanotrasen-brand capacitor arrays only. Warranty void if dropped in toilet." + icon_state = "microfusion_nanocarbon" + maxcharge = 30000 + max_attachments = 420 diff --git a/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm new file mode 100644 index 000000000000..711d1db57aa3 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm @@ -0,0 +1,132 @@ +/* +MICROFUSION CELL UPGRADE ATTACHMENTS + +For adding unique abilities to microfusion cells. These cannot directly interact with the gun. +*/ + +/obj/item/microfusion_cell_attachment + name = "microfusion cell attachment" + desc = "broken" + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_cells.dmi' + w_class = WEIGHT_CLASS_NORMAL + /// The overlay that will be automatically added, must be in the cells icon. + var/attachment_overlay_icon_state + /// Does this attachment process with the cell? + var/processing_attachment = FALSE + + +/obj/item/microfusion_cell_attachment/proc/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + SHOULD_CALL_PARENT(TRUE) + START_PROCESSING(SSobj, microfusion_cell) + return + +/obj/item/microfusion_cell_attachment/proc/process_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell, delta_time) + return PROCESS_KILL + +/obj/item/microfusion_cell_attachment/proc/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + SHOULD_CALL_PARENT(TRUE) + STOP_PROCESSING(SSobj, microfusion_cell) + return + +/* +rechargeable ATTACHMENT + +Allows the cell to be recharged at a gun recharger OR cell recharger. +*/ +/obj/item/microfusion_cell_attachment/rechargeable + name = "rechargeable microfusion cell attachment" + desc = "An adapter meant to be plugged into a microfusion cell, allowing the cell to be recharged at recharge stations for both weapons and civilian-grade batteries. Neither Allstar Lasers Incorporated or Micron Control Systems Incorporated suggest licking the prongs." + icon_state = "attachment_rechargeable" + attachment_overlay_icon_state = "microfusion_rechargeable" + /// The bonus charge rate by adding this attachment. + var/bonus_charge_rate = 300 + +/obj/item/microfusion_cell_attachment/rechargeable/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.chargerate += bonus_charge_rate + +/obj/item/microfusion_cell_attachment/rechargeable/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.chargerate -= bonus_charge_rate + +/* +OVERCAPACITY ATTACHMENT + +Increases the cell capacity by a set percentage. +*/ +/obj/item/microfusion_cell_attachment/overcapacity + name = "overcapacity microfusion cell attachment" + desc = "An attachment which increases the capacity of the microfusion cell it's attached to. These are an additional, smaller capacitor, using a system to automatically switch from the cell to the capacitor as it's depleted, maximizing the weapon's charge." + icon_state = "attachment_overcapacity" + attachment_overlay_icon_state = "microfusion_overcapacity" + /// How much the attachment increases the cell's capacity by, as a percentage + var/capacity_increase = 20 + /// The initial capacity of the cell before this upgrade is added! + var/initial_charge_capacity = 0 + +/obj/item/microfusion_cell_attachment/overcapacity/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + initial_charge_capacity = microfusion_cell.maxcharge + var/capacity_to_add = microfusion_cell.maxcharge / 100 * capacity_increase + microfusion_cell.maxcharge += capacity_to_add + +/obj/item/microfusion_cell_attachment/overcapacity/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.charge = min(microfusion_cell.charge, initial_charge_capacity) + microfusion_cell.maxcharge = initial_charge_capacity + initial_charge_capacity = 0 + +/* +STABILISER ATTACHMENT + +The cell is stable and will not emit sparks when firing. +*/ + +/obj/item/microfusion_cell_attachment/stabiliser + name = "stabilising microfusion cell attachment" + desc = "A stabilizer system attachment combining a grounding system with additional containment coils for self-charging purposes, this gives additional safety to the cell it's attached to; preventing both sparks and leakage." + icon_state = "attachment_stabiliser" + attachment_overlay_icon_state = "microfusion_stabiliser" + +/obj/item/microfusion_cell_attachment/stabiliser/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.stabilised = TRUE + +/obj/item/microfusion_cell_attachment/stabiliser/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.stabilised = FALSE + +/* +SELFCHARGE ATTACHMENT + +The cell will charge itself. +If the cell isn't stabilised by a stabiliser, it may emit a radiation pulse. +*/ +/obj/item/microfusion_cell_attachment/selfcharging + name = "self-charging microfusion cell attachment" + desc = "While microfusion cells are normally shipped without their fuel source, this attachment comes with fifteen grams of hydrogen fuel; allowing the cell to sustain a small, yet active reaction to self-charge. These can keep going for weeks to months in ideal conditions, making them more than enough for most campaigns." + icon_state = "attachment_selfcharge" + attachment_overlay_icon_state = "microfusion_selfcharge" + /// The amount of charge this cell will passively gain! + var/self_charge_amount = 20 + +/obj/item/microfusion_cell_attachment/selfcharging/examine(mob/user) + . = ..() + . += span_warning("WARNING: May cause radiation burns and weapon instability if not stabilized with recommended attachment!") + +/obj/item/microfusion_cell_attachment/selfcharging/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.self_charging = TRUE + +/obj/item/microfusion_cell_attachment/selfcharging/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.self_charging = FALSE + +/obj/item/microfusion_cell_attachment/selfcharging/process_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell, delta_time) + if(microfusion_cell.charge < microfusion_cell.maxcharge) + microfusion_cell.charge = clamp(microfusion_cell.charge + (self_charge_amount * delta_time), 0, microfusion_cell.maxcharge) + if(microfusion_cell.parent_gun) + microfusion_cell.parent_gun.update_appearance() + if(!microfusion_cell.stabilised && DT_PROB(1, delta_time)) + radiation_pulse(src, 1, RAD_MEDIUM_INSULATION) + diff --git a/monkestation/code/modules/microfusion/code/microfusion_designs.dm b/monkestation/code/modules/microfusion/code/microfusion_designs.dm new file mode 100644 index 000000000000..773777199434 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/microfusion_designs.dm @@ -0,0 +1,218 @@ +// CELLS AND EMITTERS +/datum/design/basic_microfusion_cell + name = "Basic Microfusion Cell" + desc = "A basic microfusion cell with a capacity of 1200 MF and and 1 attachment points." + id = "basic_microfusion_cell" + build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 200) + construction_time = 10 SECONDS + build_path = /obj/item/stock_parts/cell/microfusion + category = list("Misc", "Power Designs", "Machinery", "initial") + +/datum/design/microfusion_phase_emitter_undercharger + name = "Microfusion Phase Emitter Undercharger" + desc = "Inverts the output beam of the phase emitter, popular amongst law enforcement as a non-lethal upgrade." + id = "microfusion_phase_emitter_undercharger" + build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 200) + construction_time = 10 SECONDS + build_path = /obj/item/microfusion_gun_attachment/undercharger + category = list("Misc", "Power Designs", "Machinery", "initial") + +/datum/design/enhanced_microfusion_cell + name = "Enhanced Microfusion Cell" + desc = "An enhanced microfusion cell with a capacity of 1500 MF and 2 attachment points." + id = "enhanced_microfusion_cell" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 200, /datum/material/uranium = 200) + construction_time = 10 SECONDS + build_path = /obj/item/stock_parts/cell/microfusion/enhanced + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/enhanced_microfusion_phase_emitter + name = "Enhanced Microfusion Phase Emitter" + desc = "The core of a microfusion projection weapon, produces the laser." + id = "enhanced_microfusion_phase_emitter" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) + construction_time = 10 SECONDS + build_path = /obj/item/microfusion_phase_emitter/enhanced + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/advanced_microfusion_cell + name = "Advanced Microfusion Cell" + desc = "An advanced microfusion cell with a capacity of 1700 MF and 3 attachment points." + id = "advanced_microfusion_cell" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/gold = 300, /datum/material/silver = 300, /datum/material/glass = 300, /datum/material/uranium = 300) + construction_time = 10 SECONDS + build_path = /obj/item/stock_parts/cell/microfusion/advanced + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/advanced_microfusion_phase_emitter + name = "Advanced Microfusion Phase Emitter" + desc = "The core of a microfusion projection weapon, produces the laser." + id = "advanced_microfusion_phase_emitter" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) + construction_time = 10 SECONDS + build_path = /obj/item/microfusion_phase_emitter/advanced + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/bluespace_microfusion_cell + name = "Bluespace Microfusion Cell" + desc = "A bluespace microfusion cell with a capacity of 2000 MF and 4 attachment points." + id = "bluespace_microfusion_cell" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/gold = 300, /datum/material/glass = 300, /datum/material/diamond = 300, /datum/material/uranium = 300, /datum/material/titanium = 300, /datum/material/bluespace = 300) + construction_time = 10 SECONDS + build_path = /obj/item/stock_parts/cell/microfusion/bluespace + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/bluespace_microfusion_phase_emitter + name = "Bluespace Microfusion Phase Emitter" + desc = "The core of a microfusion projection weapon, produces the laser." + id = "bluespace_microfusion_phase_emitter" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500, /datum/material/diamond = 500) + construction_time = 10 SECONDS + build_path = /obj/item/microfusion_phase_emitter/bluespace + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +// CELL UPGRADES +/datum/design/microfusion_cell_attachment_rechargeable + name = "Rechargeable Microfusion Cell Attachment" + desc = "An attachment for microfusion cells that allows conversion of KJ to MF in standard chargers." + id = "microfusion_cell_attachment_rechargeable" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/gold = 1000) + build_path = /obj/item/microfusion_cell_attachment/rechargeable + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_cell_attachment_stabiliser + name = "Stabilising Microfusion Cell Attachment" + desc = "Stabilises the internal fusion reaction of microfusion cells." + id = "microfusion_cell_attachment_stabiliser" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000) + build_path = /obj/item/microfusion_cell_attachment/stabiliser + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_cell_attachment_overcapacity + name = "Overcapacity Microfusion Cell Attachment" + desc = "An attachment for microfusion cells that increases MF capacity." + id = "microfusion_cell_attachment_overcapacity" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 500, /datum/material/gold = 500) + build_path = /obj/item/microfusion_cell_attachment/overcapacity + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_cell_attachment_selfcharging + name = "Self-Charging Microfusion Cell Attachment" + desc = "Contains a small amount of infinitely decaying nuclear material, causing the fusion reaction to be self sustaining. WARNING: May cause radiation burns if not stabilised." + id = "microfusion_cell_attachment_selfcharging" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/uranium = 1000) + build_path = /obj/item/microfusion_cell_attachment/selfcharging + category = list("Misc", "Power Designs") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +// GUN UPGRADES +/datum/design/microfusion_gun_attachment_grip + name = "Microfusion Weapon Grip" + desc = "A grip... for microfusion weapon platforms." + id = "microfusion_gun_attachment_grip" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) + build_path = /obj/item/microfusion_gun_attachment/grip + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_scope + name = "Microfusion Weapon Scope" + desc = "A scope... for microfusion weapon platforms." + id = "microfusion_gun_attachment_scope" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) + build_path = /obj/item/microfusion_gun_attachment/scope + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_black_camo + name = "Black Camo Microfusion Frame" + desc = "A frame modification for the MCR-10, changing the color of the gun to black." + id = "microfusion_gun_attachment_black_camo" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/gold = 500) + build_path = /obj/item/microfusion_gun_attachment/black_camo + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_rail + name = "Microfusion Weapon Rail" + desc = "A rail system for any additional attachments, such as a torch." + id = "microfusion_gun_attachment_rail" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) + build_path = /obj/item/microfusion_gun_attachment/rail + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_heatsink + name = "Phase Emitter Heatsink" + desc = "A heatsink attachment for your microfusion weapon. Massively increases cooling potential." + id = "microfusion_gun_attachment_heatsink" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/bronze = 500) + build_path = /obj/item/microfusion_gun_attachment/heatsink + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_scatter + name = "Diffuser Microfusion Lens Attachment" + desc = "Splits the microfusion laser beam entering the lens!" + id = "microfusion_gun_attachment_scatter" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/silver = 500) + build_path = /obj/item/microfusion_gun_attachment/scatter + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_superheat + name = "Superheating Phase Emitter Upgrade" + desc = "Superheats the beam, causing targets to ignite!" + id = "microfusion_gun_attachment_superheat" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 500) + build_path = /obj/item/microfusion_gun_attachment/superheat + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_repeater + name = "Repeating Phase Emitter Upgrade" + desc = "Upgrades the central phase emitter to repeat twice." + id = "microfusion_gun_attachment_repeater" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/bluespace = 500) + build_path = /obj/item/microfusion_gun_attachment/repeater + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_xray + name = "Phase Inverter Emitter Array" + desc = "Experimental technology that inverts the central phase emitter causing the wave frequency to shift into X-ray. CAUTION: Phase emitter heats up very quickly." + id = "microfusion_gun_attachment_xray" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 1000, /datum/material/uranium = 500, /datum/material/bluespace = 500) + build_path = /obj/item/microfusion_gun_attachment/xray + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE diff --git a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm new file mode 100644 index 000000000000..836459c4cc47 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm @@ -0,0 +1,806 @@ +#define DUALWIELD_PENALTY_EXTRA_MULTIPLIER 1.4 + +// Master file for cell loadable energy guns. PROCS ONLY YOU MONKEYS! +// This file is a copy/paste of _energy.dm with extensive modification. + +/obj/item/gun/microfusion + name = "prototype detatchable cell energy projection aparatus" + desc = "The coders have obviously failed to realise this is broken." + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun40x32.dmi' + icon_state = "mcr01" + bayonet_icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun40x32.dmi' + gunlight_icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun40x32.dmi' + lefthand_file = 'modular_skyrat/modules/microfusion/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/microfusion/icons/guns_lefthand.dmi' + has_gun_safety = TRUE + can_flashlight = FALSE + can_bayonet = FALSE + w_class = WEIGHT_CLASS_BULKY + + /// What type of power cell this uses + var/obj/item/stock_parts/cell/microfusion/cell + /// The cell we will spawn with + var/cell_type = /obj/item/stock_parts/cell/microfusion + /// The cell type we check when inserting a cell + var/base_cell_type = /obj/item/stock_parts/cell/microfusion + /// If the weapon has custom icons for individual ammo types it can switch between. ie disabler beams, taser, laser/lethals, ect. + var/modifystate = FALSE + /// Can it be charged in a recharger? + var/can_charge = TRUE + /// How many charge sections do we have? + var/charge_sections = 4 + ammo_x_offset = 2 + /// if this gun uses a stateful charge bar for more detail + var/shaded_charge = FALSE + /// If this gun has a "this is loaded with X" overlay alongside chargebars and such + var/single_shot_type_overlay = TRUE + /// Should we give an overlay to empty guns? + var/display_empty = TRUE + /// whether the gun's cell drains the cyborg user's cell to recharge + var/dead_cell = FALSE + + // MICROFUSION SPECIFIC VARS + + /// The microfusion lens used for generating the beams. + var/obj/item/ammo_casing/energy/laser/microfusion/microfusion_lens + /// The time it takes for someone to (tactically) reload this gun. In deciseconds. + var/reload_time = 2 SECONDS + /// The sound played when you insert a cell. + var/sound_cell_insert = 'modular_skyrat/modules/microfusion/sound/mag_insert.ogg' + /// Should the insertion sound played vary? + var/sound_cell_insert_vary = TRUE + /// The volume at which we will play the insertion sound. + var/sound_cell_insert_volume = 50 + /// The sound played when you remove a cell. + var/sound_cell_remove = 'modular_skyrat/modules/microfusion/sound/mag_insert.ogg' + /// Should the removal sound played vary? + var/sound_cell_remove_vary = TRUE + /// The volume at which we will play the removal sound. + var/sound_cell_remove_volume = 50 + /// A list of attached upgrades + var/list/attachments = list() + /// The starting phase emitter in this weapon. + var/phase_emitter_type = /obj/item/microfusion_phase_emitter + /// The base emitter type that we check when putting a new emitter in. + var/base_phase_emitter_type = /obj/item/microfusion_phase_emitter + /// The phase emitter that this gun currently has. + var/obj/item/microfusion_phase_emitter/phase_emitter + /// The amount of heat produced per shot + var/heat_per_shot = 100 + /// The heat dissipation bonus granted by the weapon. + var/heat_dissipation_bonus = 0 + /// What slots does this gun have? + var/attachment_slots = list(GUN_SLOT_BARREL, GUN_SLOT_UNDERBARREL, GUN_SLOT_RAIL, GUN_SLOT_UNIQUE) + /// Our base firedelay. + var/base_fire_delay = 0 + /// Do we use more power because of attachments? + var/extra_power_usage = 0 + +/obj/item/gun/microfusion/emp_act(severity) + . = ..() + if(!(. & EMP_PROTECT_CONTENTS)) + cell.use(round(cell.charge / severity)) + chambered = null //we empty the chamber + recharge_newshot() //and try to charge a new shot + update_appearance() + +/obj/item/gun/microfusion/Initialize(mapload) + . = ..() + if(cell_type) + cell = new cell_type(src) + else + cell = new(src) + cell.parent_gun = src + if(!dead_cell) + cell.give(cell.maxcharge) + if(phase_emitter_type) + phase_emitter = new phase_emitter_type(src) + else + phase_emitter = new(src) + phase_emitter.parent_gun = src + update_microfusion_lens() + recharge_newshot(TRUE) + update_appearance() + AddComponent(/datum/component/ammo_hud) + RegisterSignal(src, COMSIG_ITEM_RECHARGED, .proc/instant_recharge) + base_fire_delay = fire_delay + +/obj/item/gun/microfusion/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/gun/microfusion/add_weapon_description() + AddElement(/datum/element/weapon_description, attached_proc = .proc/add_notes_energy) + +/obj/item/gun/microfusion/Destroy() + if(microfusion_lens) + QDEL_NULL(microfusion_lens) + if(cell) + cell.parent_gun = null + QDEL_NULL(cell) + if(attachments.len) + for(var/obj/item/iterating_item in attachments) + qdel(iterating_item) + attachments = null + if(phase_emitter) + QDEL_NULL(phase_emitter) + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/gun/microfusion/handle_atom_del(atom/to_handle) + if(to_handle == cell) + cell = null + update_appearance() + if(to_handle == phase_emitter) + phase_emitter = null + update_appearance() + return ..() + +/obj/item/gun/microfusion/can_shoot() + return !QDELETED(cell) ? (cell.charge >= microfusion_lens.e_cost) : FALSE + +/obj/item/gun/microfusion/recharge_newshot() + if (!microfusion_lens || !cell || !phase_emitter) + return + chambered = microfusion_lens + if(!chambered.loaded_projectile) + chambered.newshot() + +/obj/item/gun/microfusion/handle_chamber() + if(chambered && !chambered.loaded_projectile && cell) //if loaded_projectile is null, i.e the shot has been fired... + var/obj/item/ammo_casing/energy/shot = chambered + cell.use(shot.e_cost + extra_power_usage)//... drain the cell + chambered = null //either way, released the prepared shot + recharge_newshot() //try to charge a new shot + +/obj/item/gun/microfusion/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) + if(!chambered && can_shoot()) + process_chamber() // If the gun was drained and then recharged, load a new shot. + return ..() + +/obj/item/gun/microfusion/update_icon_state() + var/skip_inhand = initial(inhand_icon_state) //only build if we aren't using a preset inhand icon + var/skip_worn_icon = initial(worn_icon_state) //only build if we aren't using a preset worn icon + + if(skip_inhand && skip_worn_icon) //if we don't have either, don't do the math. + return ..() + + var/ratio = get_charge_ratio() + var/temp_icon_to_use = initial(icon_state) + if(modifystate) + temp_icon_to_use += "[microfusion_lens.select_name]" + + temp_icon_to_use += "[ratio]" + if(!skip_inhand) + inhand_icon_state = temp_icon_to_use + if(!skip_worn_icon) + worn_icon_state = temp_icon_to_use + return ..() + +/obj/item/gun/microfusion/update_overlays() + . = ..() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) //update the ammo hud since it's heavily dependent on the gun's state + if(!phase_emitter) + . += "[icon_state]_phase_emitter_missing" + else if(phase_emitter.damaged) + . += "[icon_state]_phase_emitter_damaged" + else if(cell) + var/ratio = get_charge_ratio() + if(ratio == 0 && display_empty) + . += "[icon_state]_empty" + else if(shaded_charge) + . += "[icon_state]_charge[ratio]_[phase_emitter.icon_state]" + else + . += "[icon_state]_phase_emitter_missing" + + + for(var/obj/item/microfusion_gun_attachment/microfusion_gun_attachment in attachments) + . += "[icon_state]_[microfusion_gun_attachment.attachment_overlay_icon_state]" + + +/obj/item/gun/microfusion/ignition_effect(atom/to_ignite, mob/living/user) + if(!can_shoot() || !microfusion_lens) + shoot_with_empty_chamber() + . = "" + else + var/obj/projectile/energy/loaded_projectile = microfusion_lens.loaded_projectile + if(!loaded_projectile) + . = "" + else if(loaded_projectile.nodamage || !loaded_projectile.damage || loaded_projectile.damage_type == STAMINA) + user.visible_message(span_danger("[user] tries to light [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src], but it doesn't do anything. Dumbass.")) + playsound(user, microfusion_lens.fire_sound, 50, TRUE) + playsound(user, loaded_projectile.hitsound, 50, TRUE) + cell.use(microfusion_lens.e_cost) + . = "" + else if(loaded_projectile.damage_type != BURN) + user.visible_message(span_danger("[user] tries to light [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src], but only succeeds in utterly destroying it. Dumbass.")) + playsound(user, microfusion_lens.fire_sound, 50, TRUE) + playsound(user, loaded_projectile.hitsound, 50, TRUE) + cell.use(microfusion_lens.e_cost) + qdel(to_ignite) + . = "" + else + playsound(user, microfusion_lens.fire_sound, 50, TRUE) + playsound(user, loaded_projectile.hitsound, 50, TRUE) + cell.use(microfusion_lens.e_cost) + . = span_danger("[user] casually lights [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src]. Damn.") + +/obj/item/gun/microfusion/attackby(obj/item/attacking_item, mob/user, params) + . = ..() + if (.) + return + if(istype(attacking_item, base_cell_type)) + insert_cell(user, attacking_item) + if(istype(attacking_item, /obj/item/microfusion_gun_attachment)) + add_attachment(attacking_item, user) + if(istype(attacking_item, base_phase_emitter_type)) + insert_emitter(attacking_item, user) + +/obj/item/gun/microfusion/process_chamber(empty_chamber, from_firing, chamber_next_round) + . = ..() + if(!cell?.stabilised && prob(40)) + do_sparks(2, FALSE, src) //Microfusion guns create sparks! + +/obj/item/gun/microfusion/attack_hand(mob/user, list/modifiers) + if(loc == user && user.is_holding(src) && cell) + eject_cell(user) + return + return ..() + +/obj/item/gun/microfusion/crowbar_act(mob/living/user, obj/item/tool) + if(!phase_emitter) + to_chat(user, span_danger("There is no phase emitter for you to remove!")) + return + playsound(src, 'sound/items/crowbar.ogg', 70, TRUE) + remove_emitter() + +/obj/item/gun/microfusion/AltClick(mob/user) + . = ..() + if(can_interact(user)) + var/obj/item/microfusion_gun_attachment/to_remove = input(user, "Please select what part you'd like to remove.", "Remove attachment") as null|obj in sort_names(attachments) + if(!to_remove) + return + remove_attachment(to_remove, user) + +/obj/item/gun/microfusion/proc/remove_all_attachments() + if(attachments.len) + for(var/obj/item/microfusion_gun_attachment/attachment in attachments) + attachment.remove_attachment(src) + attachment.forceMove(get_turf(src)) + attachments -= attachment + update_appearance() + +/obj/item/gun/microfusion/examine(mob/user) + . = ..() + if(attachments.len) + for(var/obj/item/microfusion_gun_attachment/microfusion_gun_attachment in attachments) + . += span_notice("It has a [microfusion_gun_attachment.name] installed.") + . += span_notice("Alt+click it to remove an upgrade.") + if(phase_emitter) + . += span_notice("It has a [phase_emitter.name] installed, at [phase_emitter.get_heat_percent()]% heat capacity.") + . += span_notice("The [phase_emitter.name] is at [phase_emitter.integrity]% integrity.") + . += span_notice("The [phase_emitter.name] will thermal throttle at [phase_emitter.throttle_percentage]% heat capacity.") + . += span_notice("Use a crowbar to remove the phase emitter.") + else + . += span_danger("It does not have a phase emitter installed!") + + if(cell) + . += span_notice("It has a [cell.name] installed, with a capacity of [cell.charge]/[cell.maxcharge] MF.") + +/obj/item/gun/microfusion/suicide_act(mob/living/user) + if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD)) + user.visible_message(span_suicide("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!")) + sleep(25) + if(user.is_holding(src)) + user.visible_message(span_suicide("[user] melts [user.p_their()] face off with [src]!")) + playsound(loc, fire_sound, 50, TRUE, -1) + cell.use(microfusion_lens.e_cost) + update_appearance() + return(FIRELOSS) + else + user.visible_message(span_suicide("[user] panics and starts choking to death!")) + return(OXYLOSS) + else + user.visible_message(span_suicide("[user] is pretending to melt [user.p_their()] face off with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) + playsound(src, dry_fire_sound, 30, TRUE) + return (OXYLOSS) + +// To maintain modularity, I am moving this proc override here. +/obj/item/gun/microfusion/fire_gun(atom/target, mob/living/user, flag, params) + if(QDELETED(target)) + return + if(firing_burst) + return + if(flag) //It's adjacent, is the user, or is on the user's person + if(target in user.contents) //can't shoot stuff inside us. + return + if(!ismob(target) || user.combat_mode) //melee attack + return + if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) + return + if(iscarbon(target)) + var/mob/living/carbon/carbon = target + for(var/i in carbon.all_wounds) + var/datum/wound/W = i + if(W.try_treating(src, user)) + return // another coward cured! + + if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can. + var/mob/living/living = user + if(!can_trigger_gun(living)) + return + if(flag) + if(user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + handle_suicide(user, target, params) + return + + if(!can_shoot()) //Just because you can pull the trigger doesn't mean it can shoot. + shoot_with_empty_chamber(user) + return + + if(check_botched(user)) + return + + var/obj/item/bodypart/other_hand = user.has_hand_for_held_index(user.get_inactive_hand_index()) //returns non-disabled inactive hands + if(weapon_weight == WEAPON_HEAVY && (user.get_inactive_held_item() || !other_hand)) + to_chat(user, span_warning("You need two hands to fire [src]!")) + return + + var/attempted_shot = process_emitter() + if(attempted_shot != SHOT_SUCCESS) + if(attempted_shot) + to_chat(user, span_danger(attempted_shot)) + return + + //DUAL (or more!) WIELDING + var/bonus_spread = 0 + var/loop_counter = 0 + if(ishuman(user) && user.combat_mode) + var/mob/living/carbon/human/H = user + for(var/obj/item/gun/gun in H.held_items) + if(gun == src || gun.weapon_weight >= WEAPON_MEDIUM) + continue + else if(gun.can_trigger_gun(user)) + bonus_spread += dual_wield_spread + loop_counter++ + addtimer(CALLBACK(gun, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter) + + return process_fire(target, user, TRUE, params, null, bonus_spread) + +// To maintain modularity, I am moving this proc override here. +/obj/item/gun/microfusion/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) + if(user) + SEND_SIGNAL(user, COMSIG_MOB_FIRED_GUN, user, target, params, zone_override) + + SEND_SIGNAL(src, COMSIG_GUN_FIRED, user, target, params, zone_override) + + add_fingerprint(user) + + if(semicd) + return + + //Vary by at least this much + var/base_bonus_spread = 0 + var/calculated_spread = 0 + var/randomized_gun_spread = 0 + var/random_spread = rand() + if(user && HAS_TRAIT(user, TRAIT_POOR_AIM)) //Nice job hotshot + bonus_spread += 35 + base_bonus_spread += 10 + + if(spread) + randomized_gun_spread = rand(0,spread) + var/randomized_bonus_spread = rand(base_bonus_spread, bonus_spread) + + if(burst_size > 1) + firing_burst = TRUE + var/fire_delay_to_add = 0 + if(phase_emitter) + fire_delay_to_add = phase_emitter.fire_delay + for(var/i = 1 to burst_size) + addtimer(CALLBACK(src, .proc/process_burst, user, target, message, params, zone_override, calculated_spread, randomized_gun_spread, randomized_bonus_spread, random_spread, i), (fire_delay + fire_delay_to_add) * (i - 1)) + else + if(chambered) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal. + if(chambered.harmful) // Is the bullet chambered harmful? + to_chat(user, span_warning("[src] is lethally chambered! You don't want to risk harming anyone...")) + return + calculated_spread = round((rand(0, 1) - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + before_firing(target,user) + process_microfusion() + if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, calculated_spread, src)) + shoot_with_empty_chamber(user) + return + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + else + shoot_with_empty_chamber(user) + return + process_chamber() + update_appearance() + semicd = TRUE + var/fire_delay_to_add = 0 + if(phase_emitter) + fire_delay_to_add = phase_emitter.fire_delay + addtimer(CALLBACK(src, .proc/reset_semicd), fire_delay + fire_delay_to_add) + + if(user) + user.update_inv_hands() + SSblackbox.record_feedback("tally", "gun_fired", 1, type) + + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + + return TRUE + +// Same goes for this! +/obj/item/gun/microfusion/process_burst(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", calculated_spread = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, random_spread= 0, iteration = 0) + if(!user || !firing_burst) + firing_burst = FALSE + return FALSE + if(!can_shoot()) + firing_burst = FALSE + return FALSE + if(!chambered) + process_chamber() // Ditto. + if(!issilicon(user)) + if(iteration > 1 && !(user.is_holding(src))) //for burst firing + firing_burst = FALSE + return FALSE + if(chambered?.loaded_projectile) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal. + if(chambered.harmful) // Is the bullet chambered harmful? + to_chat(user, span_warning("[src] is lethally chambered! You don't want to risk harming anyone...")) + return + if(randomspread) + calculated_spread = round((rand(0, 1) - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + else //Smart spread + calculated_spread = round((((random_spread/burst_size) * iteration) - (0.5 + (random_spread * 0.25))) * (randomized_gun_spread + randomized_bonus_spread)) + before_firing(target,user) + process_microfusion() + if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, calculated_spread, src)) + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + if (iteration >= burst_size) + firing_burst = FALSE + else + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + process_chamber() + update_appearance() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + return TRUE + +/obj/item/gun/microfusion/shoot_live_shot(mob/living/user, pointblank, atom/pbtarget, message) + if(recoil) + shake_camera(user, recoil + 1, recoil) + + var/sound_freq_to_add = 0 + + if(phase_emitter && phase_emitter.sound_freq > 1) + sound_freq_to_add = phase_emitter.sound_freq + + if(suppressed) + playsound(user, suppressed_sound, suppressed_volume, vary_fire_sound, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, frequency = sound_freq_to_add, falloff_distance = 0) + else + playsound(user, fire_sound, fire_sound_volume, vary_fire_sound, frequency = sound_freq_to_add) + if(message) + if(pointblank) + user.visible_message(span_danger("[user] fires [src] point blank at [pbtarget]!"), \ + span_danger("You fire [src] point blank at [pbtarget]!"), \ + span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE, pbtarget) + to_chat(pbtarget, span_userdanger("[user] fires [src] point blank at you!")) + if(pb_knockback > 0 && ismob(pbtarget)) + var/mob/PBT = pbtarget + var/atom/throw_target = get_edge_target_turf(PBT, user.dir) + PBT.throw_at(throw_target, pb_knockback, 2) + else + user.visible_message(span_danger("[user] fires [src]!"), \ + span_danger("You fire [src]!"), \ + span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE) + if(user.resting) + user.Immobilize(20, TRUE) + + phase_emitter.add_heat(heat_per_shot) + + if(phase_emitter.current_heat > phase_emitter.max_heat) + if(ishuman(user)) + var/mob/living/carbon/human/human = user + var/obj/item/bodypart/affecting = human.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") + if(affecting?.receive_damage( 0, 5 )) // 1 burn damage + to_chat(user, span_warning("[src] burns your hand, it's too hot!")) + +/obj/item/gun/microfusion/proc/process_microfusion() + if(attachments.len) + for(var/obj/item/microfusion_gun_attachment/attachment in attachments) + attachment.process_fire(src, chambered) + return TRUE + +/obj/item/gun/microfusion/proc/process_emitter() + if(!phase_emitter) + return SHOT_FAILURE_NO_EMITTER + var/phase_emitter_process = phase_emitter.check_emitter() + if(phase_emitter_process != SHOT_SUCCESS) + return phase_emitter_process + return SHOT_SUCCESS + +/obj/item/gun/microfusion/proc/instant_recharge() + SIGNAL_HANDLER + if(!cell) + return + cell.charge = cell.maxcharge + recharge_newshot() + update_appearance() + +///Used by update_icon_state() and update_overlays() +/obj/item/gun/microfusion/proc/get_charge_ratio() + return can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0 + // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if its power cell is removed. + +/** + * + * Outputs type-specific weapon stats for energy-based firearms based on its firing modes + * and the stats of those firing modes. Esoteric firing modes like ion are currently not supported + * but can be added easily + * + */ +/obj/item/gun/microfusion/proc/add_notes_energy() + var/list/readout = list() + // Make sure there is something to actually retrieve + if(!microfusion_lens) + return + var/obj/projectile/exam_proj + readout += "Our heroic interns have shown that one can theoretically stay standing after..." + exam_proj = GLOB.proj_by_path_key[microfusion_lens?.projectile_type] + + if(!istype(exam_proj)) + return readout.Join("\n") + + if(exam_proj.damage > 0) // Don't divide by 0!!!!! + readout += "[span_warning("[HITS_TO_CRIT(exam_proj.damage * microfusion_lens.pellets)] shot\s")] on [span_warning("[microfusion_lens.select_name]")] mode before collapsing from [exam_proj.damage_type == STAMINA ? "immense pain" : "their wounds"]." + if(exam_proj.stamina > 0) // In case a projectile does damage AND stamina damage (Energy Crossbow) + readout += "[span_warning("[HITS_TO_CRIT(exam_proj.stamina * microfusion_lens.pellets)] shot\s")] on [span_warning("[microfusion_lens.select_name]")] mode before collapsing from immense pain." + else + readout += "a theoretically infinite number of shots on [span_warning("[microfusion_lens.select_name]")] mode." + + return readout.Join("\n") // Sending over the singular string, rather than the whole list + +/obj/item/gun/microfusion/proc/update_microfusion_lens() + if(!microfusion_lens) + microfusion_lens = new(src) + fire_sound = microfusion_lens.fire_sound + fire_sound_volume = microfusion_lens.fire_sound_volume + fire_delay = microfusion_lens.delay + +// Cell, emitter and upgrade interactions + +/obj/item/gun/microfusion/proc/remove_emitter(mob/user) + playsound(src, sound_cell_insert, 50, TRUE) + phase_emitter.forceMove(get_turf(src)) + if(user) + user.put_in_hands(phase_emitter) + to_chat(user, span_notice("You remove [phase_emitter] from [src]!")) + phase_emitter.parent_gun = null + phase_emitter = null + update_appearance() + +/obj/item/gun/microfusion/proc/insert_emitter(obj/item/microfusion_phase_emitter/inserting_phase_emitter, mob/living/user) + if(phase_emitter) + to_chat(user, span_danger("There is already a phase emitter installed!")) + return FALSE + to_chat(user, span_notice("You carefully insert [inserting_phase_emitter] into the slot.")) + playsound(src, sound_cell_remove, 50, TRUE) + inserting_phase_emitter.forceMove(src) + phase_emitter = inserting_phase_emitter + phase_emitter.parent_gun = src + update_appearance() + + +/// Try to insert the cell into the gun, if successful, return TRUE +/obj/item/gun/microfusion/proc/insert_cell(mob/user, obj/item/stock_parts/cell/microfusion/inserting_cell, display_message = TRUE) + var/tactical_reload = FALSE //We need to do this so that cells don't fall on the ground. + var/obj/item/stock_parts/cell/old_cell = cell + if(cell) + if(reload_time && !HAS_TRAIT(user, TRAIT_INSTANT_RELOAD)) //This only happens when you're attempting a tactical reload, e.g. there's a mag already inserted. + if(display_message) + to_chat(user, span_notice("You start to insert [inserting_cell] into [src]!")) + if(!do_after(user, reload_time, src)) + if(display_message) + to_chat(user, span_warning("You fail to insert [inserting_cell] into [src]!")) + return FALSE + if(display_message) + to_chat(user, span_notice("You tactically reload [src], replacing [cell] inside!")) + tactical_reload = TRUE + eject_cell(user, FALSE, FALSE) + else if(display_message) + to_chat(user, span_notice("You insert [inserting_cell] into [src]!")) + if(sound_cell_insert) + playsound(src, sound_cell_insert, sound_cell_insert_volume, sound_cell_insert_vary) + cell = inserting_cell + inserting_cell.forceMove(src) + cell.parent_gun = src + if(tactical_reload) + user.put_in_hands(old_cell) + recharge_newshot() + update_appearance() + return TRUE + +/// Ejecting a cell. +/obj/item/gun/microfusion/proc/eject_cell(mob/user, display_message = TRUE, put_in_hands = TRUE) + var/obj/item/stock_parts/cell/microfusion/old_cell = cell + old_cell.forceMove(get_turf(src)) + if(user) + if(put_in_hands) + user.put_in_hands(old_cell) + if(display_message) + to_chat(user, span_notice("You remove [old_cell] from [src]!")) + if(sound_cell_remove) + playsound(src, sound_cell_remove, sound_cell_remove_volume, sound_cell_remove_vary) + old_cell.update_appearance() + cell.parent_gun = null + cell = null + update_appearance() + +/// Attatching an upgrade. +/obj/item/gun/microfusion/proc/add_attachment(obj/item/microfusion_gun_attachment/microfusion_gun_attachment, mob/living/user) + if(is_type_in_list(microfusion_gun_attachment, attachments)) + to_chat(user, span_warning("[src] already has [microfusion_gun_attachment] installed!")) + return FALSE + if(!(microfusion_gun_attachment.slot in attachment_slots)) + to_chat(user, span_warning("[src] cannot install [microfusion_gun_attachment]!")) + return FALSE + for(var/obj/item/microfusion_gun_attachment/iterating_attachment in attachments) + if(is_type_in_list(microfusion_gun_attachment, iterating_attachment.incompatable_attachments)) + to_chat(user, span_warning("[microfusion_gun_attachment] is not compatible with [iterating_attachment]!")) + return FALSE + if(iterating_attachment.slot != GUN_SLOT_UNIQUE && iterating_attachment.slot == microfusion_gun_attachment.slot) + to_chat(user, span_warning("[microfusion_gun_attachment] cannot be installed in the same slot as [iterating_attachment]!")) + return FALSE + attachments += microfusion_gun_attachment + microfusion_gun_attachment.forceMove(src) + microfusion_gun_attachment.run_attachment(src) + to_chat(user, span_notice("You successfully install [microfusion_gun_attachment] onto [src]!")) + playsound(src, 'sound/effects/structure_stress/pop2.ogg', 70, TRUE) + return TRUE + +/obj/item/gun/microfusion/proc/remove_attachment(obj/item/microfusion_gun_attachment/microfusion_gun_attachment, mob/living/user) + to_chat(user, span_notice("You remove [microfusion_gun_attachment] from [src]!")) + playsound(src, 'sound/items/screwdriver.ogg', 70) + microfusion_gun_attachment.forceMove(get_turf(src)) + attachments -= microfusion_gun_attachment + microfusion_gun_attachment.remove_attachment(src) + user?.put_in_hands(microfusion_gun_attachment) + update_appearance() + +/obj/item/gun/microfusion/proc/change_name(mob/user) + var/new_name = input(user, "Enter new name:", "Change gun name") as null|text + if(!new_name) + return + var/name_length = length(new_name) + if(name_length > GUN_MAX_NAME_CHARS && name_length < GUN_MIN_NAME_CHARS) + to_chat(user, span_warning("New name cannot be longer than 20 or shorter than 5 characters!")) + return + + name = sanitize(new_name) + update_appearance() + +// UI CONTROL + +/obj/item/gun/microfusion/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "MicrofusionGunControl") + ui.open() + +/obj/item/gun/microfusion/ui_data(mob/user) + var/list/data = list() + + data["gun_name"] = name + data["gun_desc"] = desc + data["gun_heat_dissipation"] = heat_dissipation_bonus + + if(phase_emitter) + data["has_emitter"] = TRUE + data["phase_emitter_data"] = list( + "type" = capitalize(phase_emitter.name), + "integrity" = phase_emitter.integrity, + "current_heat" = phase_emitter.current_heat, + "throttle_percentage" = phase_emitter.throttle_percentage, + "heat_dissipation_per_tick" = phase_emitter.heat_dissipation_per_tick, + "max_heat" = phase_emitter.max_heat, + "damaged" = phase_emitter.damaged, + "hacked" = phase_emitter.hacked, + "heat_percent" = phase_emitter.get_heat_percent(), + "process_time" = phase_emitter.fire_delay, + "cooling_system" = phase_emitter.cooling_system, + "cooling_system_rate" = phase_emitter.cooling_system_rate, + ) + else + data["has_emitter"] = FALSE + + if(cell) + var/list/attachments = list() + for(var/obj/item/microfusion_cell_attachment/attachment in cell.attachments) + attachments += attachment.name + data["has_cell"] = TRUE + data["cell_data"] = list( + "type" = capitalize(cell.name), + "charge" = cell.charge, + "max_charge" = cell.maxcharge, + "status" = cell.meltdown, + "attachments" = attachments, + ) + else + data["has_cell"] = FALSE + + + + if(attachments.len) + data["has_attachments"] = TRUE + data["attachments"] = list() + for(var/obj/item/microfusion_gun_attachment/attachment in attachments) + var/list/attachment_functions = attachment.get_modify_data() + var/has_modifications = FALSE + if(attachment_functions?.len > 0) + has_modifications = TRUE + data["attachments"] += list(list( + "name" = uppertext(attachment.name), + "desc" = attachment.desc, + "slot" = capitalize(attachment.slot), + "information" = attachment.get_information_data(), + "has_modifications" = has_modifications, + "modify" = attachment_functions, + "ref" = REF(attachment), + )) + + else + data["has_attachments"] = FALSE + + return data + +/obj/item/gun/microfusion/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("eject_cell") + if(!cell) + return + eject_cell(usr) + if("change_gun_name") + change_name(usr) + if("overclock_emitter") + if(!phase_emitter) + return + if(!phase_emitter.hacked) + return + phase_emitter.set_overclock(usr) + if("eject_emitter") + if(!phase_emitter) + return + remove_emitter(usr) + if("remove_attachment") + var/obj/item/microfusion_gun_attachment/to_remove = locate(params["attachment_ref"]) in src + if(!to_remove) + return + remove_attachment(to_remove, usr) + if("modify_attachment") + var/obj/item/microfusion_gun_attachment/to_modify = locate(params["attachment_ref"]) in src + if(!to_modify) + return + to_modify.run_modify_data(params["modify_ref"], usr, src) + if("toggle_cooling_system") + if(!phase_emitter) + return + phase_emitter.toggle_cooling_system(usr) + diff --git a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm new file mode 100644 index 000000000000..b7f3e85967ca --- /dev/null +++ b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm @@ -0,0 +1,447 @@ +/** +*MICROFUSION GUN UPGRADE ATTACHMENTS +*For adding unique abilities to microfusion guns, these can directly interact with the gun! +*/ + +/obj/item/microfusion_gun_attachment + name = "microfusion gun attachment" + desc = "broken" + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun_attachments.dmi' + w_class = WEIGHT_CLASS_NORMAL + /// The attachment overlay icon state. + var/attachment_overlay_icon_state + /// Any incompatable upgrade types. + var/list/incompatable_attachments = list() + /// The added heat produced by having this module installed. + var/heat_addition = 0 + /// The slot this attachment is installed in. + var/slot = GUN_SLOT_UNIQUE + /// How much extra power do we use? + var/power_usage = 0 + +/obj/item/microfusion_gun_attachment/examine(mob/user) + . = ..() + . += "Compatible slot: [slot]." + +/obj/item/microfusion_gun_attachment/proc/run_attachment(obj/item/gun/microfusion/microfusion_gun) + SHOULD_CALL_PARENT(TRUE) + microfusion_gun.heat_per_shot += heat_addition + microfusion_gun.update_appearance() + microfusion_gun.extra_power_usage += power_usage + return + +/obj/item/microfusion_gun_attachment/proc/process_attachment(obj/item/gun/microfusion/microfusion_gun) + return + +//Firing the gun right before we let go of it, tis is called. +/obj/item/microfusion_gun_attachment/proc/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + return + +/obj/item/microfusion_gun_attachment/proc/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + SHOULD_CALL_PARENT(TRUE) + microfusion_gun.heat_per_shot -= heat_addition + microfusion_gun.update_appearance() + microfusion_gun.extra_power_usage -= power_usage + return + +/* +Returns a list of modifications of this attachment, it must return a list within a list list(list()). +All of the following must be returned. +list(list("title" = "Toggle [toggle ? "OFF" : "ON"]", "icon" = "power-off", "color" = "blue" "reference" = "toggle_on_off")) +title - The title of the modification button +icon - The icon of the modification button +color - The color of the modification button +reference - The reference of the modification button, this is used to call the proc when the run modify data proc is called. +*/ +/obj/item/microfusion_gun_attachment/proc/get_modify_data() + return + +/obj/item/microfusion_gun_attachment/proc/run_modify_data(params, mob/living/user, obj/item/gun/microfusion/microfusion_gun) + return + +/obj/item/microfusion_gun_attachment/proc/get_information_data() + return + +/* +SCATTER ATTACHMENT + +The cell is stable and will not emit sparks when firing. +*/ +/obj/item/microfusion_gun_attachment/scatter + name = "diffuser microfusion lens upgrade" + desc = "A diffusing lens system capable of splitting one beam into three. However, the additional ionizing of the air will cause higher recoil." + icon_state = "attachment_scatter" + attachment_overlay_icon_state = "attachment_scatter" + slot = GUN_SLOT_BARREL + /// How many pellets are we going to add to the existing amount on the gun? + var/pellets_to_add = 2 + /// The variation in pellet scatter. + var/variance_to_add = 20 + /// How much recoil are we adding? + var/recoil_to_add = 1 + /// The spread to add. + var/spread_to_add = 10 + +/obj/item/microfusion_gun_attachment/scatter/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.spread += spread_to_add + microfusion_gun.microfusion_lens.pellets += pellets_to_add + microfusion_gun.microfusion_lens.variance += variance_to_add + +/obj/item/microfusion_gun_attachment/scatter/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile?.damage = chambered.loaded_projectile.damage / chambered.pellets + +/obj/item/microfusion_gun_attachment/scatter/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.spread -= spread_to_add + microfusion_gun.microfusion_lens.pellets -= microfusion_gun.microfusion_lens.pellets + microfusion_gun.microfusion_lens.variance -= microfusion_gun.microfusion_lens.variance + +/* +REPEATER ATTACHMENT + +The gun can fire volleys of shots. +*/ +/obj/item/microfusion_gun_attachment/superheat + name = "superheating phase emitter upgrade" + desc = "A barrel attachment hooked to the phase emitter, this adjusts the beam's wavelength to carry an intense wave of heat; causing targets to ignite." + icon_state = "attachment_superheat" + attachment_overlay_icon_state = "attachment_superheat" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter) + heat_addition = 70 + slot = GUN_SLOT_BARREL + var/projectile_override =/obj/projectile/beam/laser/microfusion/superheated + +/obj/item/microfusion_gun_attachment/superheat/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/vaporize.ogg' + +/obj/item/microfusion_gun_attachment/superheat/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + + +/obj/item/microfusion_gun_attachment/superheat/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + +/* +REPEATER ATTACHMENT + +The gun can fire volleys of shots. +*/ +/obj/item/microfusion_gun_attachment/repeater + name = "repeating phase emitter upgrade" + desc = "This barrel attachment upgrades the central phase emitter to fire off two beams in quick succession. While offering an increased rate of fire, the heat output and recoil rises too." + icon_state = "attachment_repeater" + attachment_overlay_icon_state = "attachment_repeater" + heat_addition = 40 + slot = GUN_SLOT_BARREL + /// The spread to add to the gun. + var/spread_to_add = 15 + /// The recoil to add to the gun. + var/recoil_to_add = 1 + /// The burst to add to the gun. + var/burst_to_add = 1 + /// The delay to add to the firing. + var/delay_to_add = 2 + +/obj/item/microfusion_gun_attachment/repeater/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.burst_size += burst_to_add + microfusion_gun.fire_delay += delay_to_add + microfusion_gun.spread += spread_to_add + +/obj/item/microfusion_gun_attachment/repeater/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.burst_size -= burst_to_add + microfusion_gun.fire_delay -= delay_to_add + microfusion_gun.spread -= spread_to_add + +/* +X-RAY ATTACHMENT + +The gun can fire X-RAY shots. +*/ +/obj/item/microfusion_gun_attachment/xray + name = "quantum phase inverter array" //Yes quantum makes things sound cooler. + desc = "An experimental barrel attachment that modifies the central phase emitter, causing the wave frequency to shift into X-ray. Capable of penetrating both glass and solid matter with ease, though the bolts don't carry a greater effect against armor, due to going through the target and doing more minimal internal damage. These attachments are power-hungry and overheat easily, though engineers have deemed the costs necessary drawbacks." + icon_state = "attachment_xray" + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_xray" + heat_addition = 90 + power_usage = 50 + +/obj/item/microfusion_gun_attachment/xray/examine(mob/user) + . = ..() + . += span_warning("CAUTION: Phase emitter heats up extremely quickly, sustained fire not recommended!") + +/obj/item/microfusion_gun_attachment/xray/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/incinerate.ogg' + +/obj/item/microfusion_gun_attachment/xray/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + +/obj/item/microfusion_gun_attachment/xray/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile.icon_state = "laser_greyscale" + chambered.loaded_projectile.color = COLOR_GREEN + chambered.loaded_projectile.light_color = COLOR_GREEN + chambered.loaded_projectile.projectile_piercing = PASSCLOSEDTURF|PASSGRILLE|PASSGLASS + +/* +GRIP ATTACHMENT + +Greatly reduces recoil and spread. +*/ +/obj/item/microfusion_gun_attachment/grip + name = "grip attachment" + desc = "A simple grip that increases accuracy." + icon_state = "attachment_grip" + attachment_overlay_icon_state = "attachment_grip" + slot = GUN_SLOT_UNDERBARREL + /// How much recoil are we removing? + var/recoil_to_remove = 1 + /// How much spread are we removing? + var/spread_to_remove = 10 + +/obj/item/microfusion_gun_attachment/grip/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_remove + microfusion_gun.spread -= spread_to_remove + +/obj/item/microfusion_gun_attachment/grip/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_remove + microfusion_gun.spread += spread_to_remove + +/* +HEATSINK ATTACHMENT + +"Greatly increases the phase emitter cooling rate." +*/ +/obj/item/microfusion_gun_attachment/heatsink + name = "phase emitter heatsink" + desc = "Greatly increases the phase emitter cooling rate." + icon_state = "attachment_heatsink" + attachment_overlay_icon_state = "attachment_heatsink" + slot = GUN_SLOT_UNDERBARREL + /// Coolant bonus + var/cooling_rate_increase = 50 + +/obj/item/microfusion_gun_attachment/heatsink/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.heat_dissipation_bonus += cooling_rate_increase + +/obj/item/microfusion_gun_attachment/heatsink/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase + +/* +UNDERCHARGER ATTACHMENT + +Massively decreases the output beam of the phase emitter. +Converts shots to STAMNINA damage. +*/ +/obj/item/microfusion_gun_attachment/undercharger + name = "phase emitter undercharger" + desc = "An underbarrel system hooked to the phase emitter, this allows the weapon to also fire an electron bolt, producing a short-lived underpowered electric charge capable of stunning targets. These shots are less demanding on the weapon, leading to an increase in cooling rate." + icon_state = "attachment_undercharger" + attachment_overlay_icon_state = "attachment_undercharger" + slot = GUN_SLOT_UNDERBARREL + var/toggle = FALSE + var/cooling_rate_increase = 10 + /// The projectile we override + var/projectile_override = /obj/projectile/beam/microfusion_disabler + /// How much recoil are we removing? + var/recoil_to_remove = 1 + /// How much spread are we removing? + var/spread_to_remove = 10 + +/obj/item/microfusion_gun_attachment/undercharger/get_modify_data() + return list(list("title" = "Turn [toggle ? "OFF" : "ON"]", "icon" = "power-off", "color" = "[toggle ? "red" : "green"]", "reference" = "toggle_on_off")) + +/obj/item/microfusion_gun_attachment/undercharger/run_modify_data(params, mob/living/user, obj/item/gun/microfusion/microfusion_gun) + if(params == "toggle_on_off") + toggle(microfusion_gun, user) + +/obj/item/microfusion_gun_attachment/undercharger/proc/toggle(obj/item/gun/microfusion/microfusion_gun, mob/user) + if(toggle) + toggle = FALSE + microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase + microfusion_gun.recoil -= recoil_to_remove + microfusion_gun.spread -= spread_to_remove + else + toggle = TRUE + microfusion_gun.heat_dissipation_bonus += cooling_rate_increase + microfusion_gun.recoil += recoil_to_remove + microfusion_gun.spread += spread_to_remove + + if(user) + to_chat(user, span_notice("You toggle [src] [toggle ? "ON" : "OFF"].")) + +/obj/item/microfusion_gun_attachment/undercharger/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/burn.ogg' + +/obj/item/microfusion_gun_attachment/undercharger/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + if(toggle) + chambered.loaded_projectile = new projectile_override + +/obj/item/microfusion_gun_attachment/undercharger/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + if(toggle) + microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase + microfusion_gun.recoil -= recoil_to_remove + microfusion_gun.spread -= spread_to_remove + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + +/* +RGB ATTACHMENT + +Enables you to change the light color of the laser. +*/ +/obj/item/microfusion_gun_attachment/rgb + name = "phase emitter spectrograph" + desc = "An attachment hooked up to the phase emitter, allowing the user to adjust the color of the beam outputted. This has seen widespread use by various factions capable of getting their hands on microfusion weapons, whether as a calling card or simply for entertainment." + icon_state = "attachment_rgb" + attachment_overlay_icon_state = "attachment_rgb" + /// What color are we changing the sprite to? + var/color_to_apply = COLOR_MOSTLY_PURE_RED + +/obj/item/microfusion_gun_attachment/rgb/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered?.loaded_projectile.icon_state = "laser_greyscale" + chambered?.loaded_projectile.color = color_to_apply + chambered?.loaded_projectile.light_color = color_to_apply + +/obj/item/microfusion_gun_attachment/rgb/proc/select_color(mob/living/user) + var/new_color = input(user, "Please select your new projectile color", "Laser color", color_to_apply) as null|color + + if(!new_color) + return + + color_to_apply = new_color + +/obj/item/microfusion_gun_attachment/rgb/attack_self(mob/user, modifiers) + . = ..() + select_color(user) + +/obj/item/microfusion_gun_attachment/rgb/get_modify_data() + return list(list("title" = "Change Color", "icon" = "wrench", "reference" = "color", "color" = "blue")) + +/obj/item/microfusion_gun_attachment/rgb/run_modify_data(params, mob/living/user) + if(params == "color") + select_color(user) + +/* +RAIL ATTACHMENT + +Allows for flashlights bayonets and adds 1 slot to equipment. +*/ +/obj/item/microfusion_gun_attachment/rail + name = "gun rail attachment" + desc = "A simple set of rails that attaches to weapon hardpoints. Allows for 3 more attachment slots and the instillation of a flashlight or bayonet." + icon_state = "attachment_rail" + attachment_overlay_icon_state = "attachment_rail" + slot = GUN_SLOT_RAIL + +/obj/item/microfusion_gun_attachment/rail/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.can_flashlight = TRUE + microfusion_gun.can_bayonet = TRUE + +/obj/item/microfusion_gun_attachment/rail/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.gun_light = initial(microfusion_gun.can_flashlight) + if(microfusion_gun.gun_light) + microfusion_gun.gun_light.forceMove(get_turf(microfusion_gun)) + microfusion_gun.clear_gunlight() + microfusion_gun.can_bayonet = initial(microfusion_gun.can_bayonet) + if(microfusion_gun.bayonet) + microfusion_gun.bayonet.forceMove(get_turf(microfusion_gun)) + microfusion_gun.clear_bayonet() + microfusion_gun.remove_all_attachments() + +/* +SCOPE ATTACHMENT + +Allows for a scope to be attached to the gun. +DANGER: SNOWFLAKE ZONE +*/ +/obj/item/microfusion_gun_attachment/scope + name = "scope attachment" + desc = "A simple telescopic scope, allowing for long-ranged use of the weapon. However, these do not provide any night vision." + icon_state = "attachment_scope" + attachment_overlay_icon_state = "attachment_scope" + slot = GUN_SLOT_RAIL + +/obj/item/microfusion_gun_attachment/scope/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + if(microfusion_gun.azoom) + return + + microfusion_gun.azoom = new() + microfusion_gun.azoom.gun = microfusion_gun + microfusion_gun.update_action_buttons() + +/obj/item/microfusion_gun_attachment/scope/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + if(microfusion_gun.azoom) + microfusion_gun.azoom.Remove(microfusion_gun.azoom.owner) + QDEL_NULL(microfusion_gun.azoom) + microfusion_gun.update_action_buttons() + +/* +BLACK CAMO ATTACHMENT + +Allows for a black camo to be applied to the gun. +All tactical, all the time. +*/ +/obj/item/microfusion_gun_attachment/black_camo + name = "black camo microfusion frame" + desc = "A frame modification for the MCR-10, changing the color of the gun to black." + icon_state = "attachment_black" + attachment_overlay_icon_state = "attachment_black" + +/* +PULSE ATTACHMENT + +The gun can fire PULSE shots. +*/ +/obj/item/microfusion_gun_attachment/pulse + name = "pulse induction carriage" + desc = "A cutting-edge bluespace capacitor array and distributing lens overhaul produced in laboratories by Nanotrasen scientists that allow microfusion rifles to fire military-grade pulse rounds. Comes equipped with cyclic cooling to ensure maximum combat efficiency, a munitions counter, and an extra-secure drop cage for the power source. May shorten trigger lifetime." + icon_state = "attachment_pulse" + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_pulse" + heat_addition = 150 + power_usage = 50 + var/added_burst_size = 2 + var/added_fire_delay = 2 + +/obj/item/microfusion_gun_attachment/pulse/examine(mob/user) + . = ..() + . += span_warning("CAUTION: Phase emitter heats up extremely quickly, sustained fire not recommended!") + +/obj/item/microfusion_gun_attachment/pulse/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.burst_size += added_burst_size + microfusion_gun.fire_delay += added_fire_delay + +/obj/item/microfusion_gun_attachment/pulse/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.burst_size -= added_burst_size + microfusion_gun.fire_delay -= added_fire_delay + +/obj/item/microfusion_gun_attachment/pulse/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new /obj/projectile/beam/pulse diff --git a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm new file mode 100644 index 000000000000..a673f7fce652 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm @@ -0,0 +1,87 @@ +/datum/techweb_node/basic_microfusion + id = "basic_microfusion" + starting_node = TRUE + display_name = "Basic Microfusion Technology" + description = "Basic microfusion technology allowing for basic microfusion designs." + design_ids = list( + "basic_microfusion_cell", + "microfusion_phase_emitter_undercharger", + ) + +//Enhanced microfusion +/datum/techweb_node/enhanced_microfusion + id = "enhanced_microfusion" + display_name = "Enhanced Microfusion Technology" + description = "Enhanced microfusion technology allowing for upgraded basic microfusion!" + prereq_ids = list( + "basic_microfusion", + "engineering", + "weaponry", + "high_efficiency", + ) + design_ids = list( + "enhanced_microfusion_cell", + "microfusion_cell_attachment_rechargeable", + "enhanced_microfusion_phase_emitter", + "microfusion_gun_attachment_black_camo", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + +//Advanced microfusion +/datum/techweb_node/advanced_microfusion + id = "advanced_microfusion" + display_name = "Advanced Microfusion Technology" + description = "Advanced microfusion technology allowing for advanced microfusion!" + prereq_ids = list( + "enhanced_microfusion", + "adv_engi", + "adv_weaponry", + "adv_power", + "adv_plasma", + ) + design_ids = list( + "advanced_microfusion_cell", + "microfusion_cell_attachment_overcapacity", + "microfusion_cell_attachment_stabiliser", + "microfusion_gun_attachment_scatter", + "microfusion_gun_attachment_superheat", + "advanced_microfusion_phase_emitter", + "microfusion_gun_attachment_grip", + "microfusion_gun_attachment_rail", + "microfusion_gun_attachment_scope", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + + +// Bluespace microfusion +/datum/techweb_node/bluespace_microfusion + id = "bluespace_microfusion" + display_name = "Bluespace Microfusion Technology" + description = "Bluespace tinkering plus microfusion technology!" + prereq_ids = list( + "advanced_microfusion", + "bluespace_power", + "beam_weapons", + "explosive_weapons", + ) + design_ids = list( + "bluespace_microfusion_cell", + "microfusion_gun_attachment_repeater", + "bluespace_microfusion_phase_emitter", + "microfusion_cell_attachment_selfcharging", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + +// Bluespace microfusion +/datum/techweb_node/quantum_microfusion + id = "quantum_microfusion" + display_name = "Quantum Microfusion Technology" + description = "Bleeding edge microfusion tech, making use of the latest in materials and components, bluespace or otherwise." + prereq_ids = list( + "bluespace_microfusion", + "alientech", + ) + design_ids = list( + "microfusion_gun_attachment_xray", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 15000) diff --git a/monkestation/code/modules/microfusion/code/phase_emitter.dm b/monkestation/code/modules/microfusion/code/phase_emitter.dm new file mode 100644 index 000000000000..99a72ec27f05 --- /dev/null +++ b/monkestation/code/modules/microfusion/code/phase_emitter.dm @@ -0,0 +1,211 @@ +////////////////////////////////////////////////////////////// PHASE EMITTERS +/* +Basically the heart of the gun, can be upgraded. +*/ +/obj/item/microfusion_phase_emitter + name = "basic microfusion phase emitter" + desc = "A first-generation phase emitter, this is the core of the weapon and the source of the beam." + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun_attachments.dmi' + icon_state = "phase_emitter" + base_icon_state = "phase_emitter" + w_class = WEIGHT_CLASS_NORMAL + /// Max heat before it breaks + var/max_heat = 2000 + /// Current heat level + var/current_heat = 0 + /// Thermal throttle percentage + var/throttle_percentage = 80 + /// How much heat it dissipates passively + var/heat_dissipation_per_tick = 30 + /// Active cooling system + var/cooling_system = FALSE + /// How quickly does the active cooling system cool - 1/1 ratio of cell charge to cooling point + var/cooling_system_rate = 30 + /// What is our dynamic integrity? + var/integrity = 100 + /// Are we fucked? + var/damaged = FALSE + /// Hard ref to the gun. + var/obj/item/gun/microfusion/parent_gun + /// Are we "hacked" thus allowing overclocking? + var/hacked = FALSE + /// The fire delay this emitter adds to the gun. + var/fire_delay = 0 + /// The sound playback speed, used for overheating sound effects on fire. + var/sound_freq = 0 + + +/obj/item/microfusion_phase_emitter/Initialize(mapload) + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/microfusion_phase_emitter/Destroy() + parent_gun = null + return ..() + +/obj/item/microfusion_phase_emitter/process(delta_time) + if(current_heat == 0) + return + var/calculated_heat_dissipation_per_tick = heat_dissipation_per_tick + if(isspaceturf(get_turf(src))) + calculated_heat_dissipation_per_tick += PHASE_HEAT_DISSIPATION_BONUS_SPACE // Passive cooling in space boost! + if(parent_gun) + calculated_heat_dissipation_per_tick += parent_gun.heat_dissipation_bonus + else + calculated_heat_dissipation_per_tick += PHASE_HEAT_DISSIPATION_BONUS_AIR //We get some passive cooling from being out of the gun. + if(cooling_system && parent_gun && parent_gun.cell && parent_gun.cell.use(cooling_system_rate)) + calculated_heat_dissipation_per_tick += cooling_system_rate + + current_heat = clamp(current_heat - (calculated_heat_dissipation_per_tick * delta_time) * 0.5, 0, INFINITY) + if(current_heat > max_heat) + integrity = integrity - current_heat / 1000 * delta_time * 0.5 + + process_fire_delay_and_sound() + + if(integrity <= 0) + kill() + update_appearance() + parent_gun?.update_appearance() + +/obj/item/microfusion_phase_emitter/proc/toggle_cooling_system(mob/user) + if(!parent_gun) + return + if(!cooling_system && !parent_gun.cell) + if(user) + to_chat(user, span_warning("You need a cell to turn on the cooling system.")) + return + + if(cooling_system) + cooling_system = FALSE + else + cooling_system = TRUE + + if(user) + to_chat(user, span_notice("You toggle the cooling system [cooling_system ? "ON" : "OFF"].")) + +/obj/item/microfusion_phase_emitter/multitool_act(mob/living/user, obj/item/tool) + if(hacked) + to_chat(user, span_warning("[src] is already unlocked!")) + return + to_chat(user, span_notice("You begin to override the thermal overclock safety...")) + if(do_after(user, 5 SECONDS, src)) + hacked = TRUE + to_chat(user, span_notice("You override the thermal overclock safety.")) + +/obj/item/microfusion_phase_emitter/proc/set_overclock(mob/living/user) + if(!hacked) + return + var/new_throttle = clamp(input(user, "Please input a new thermal throttle percentage(0-300):", "Phase Emitter Overclock") as null|num, 1, 300) + + to_chat(user, span_notice("Thermal throttle percent set to: [new_throttle].")) + + if(new_throttle > 100) + to_chat(user, span_danger("WARNING: You have input a throttle percentage of more than 100, this may cause emitter damage.")) + + throttle_percentage = new_throttle + +/obj/item/microfusion_phase_emitter/update_icon_state() + . = ..() + + if(damaged) + icon_state = "[base_icon_state]_damaged" + else + switch(get_heat_percent()) + if(40 to 69) + icon_state = "[base_icon_state]_hot" + if(70 to INFINITY) + icon_state = "[base_icon_state]_critical" + else + icon_state = base_icon_state + +/obj/item/microfusion_phase_emitter/proc/process_fire_delay_and_sound() + var/fire_delay_to_add = 0 + if(integrity < 100) + fire_delay_to_add = fire_delay_to_add + (100 - integrity) / 10 + + if(current_heat > max_heat) + fire_delay_to_add = fire_delay_to_add + (current_heat - max_heat) / 100 //Holy shit this emitter is tanking + + fire_delay = round(fire_delay_to_add, 1.45) + +/obj/item/microfusion_phase_emitter/proc/get_heat_icon_state() + switch(get_heat_percent()) + if(40 to 69) + return "hot" + if(70 to INFINITY) + return "critical" + else + return "normal" + +/obj/item/microfusion_phase_emitter/examine(mob/user) + . = ..() + if(damaged) + . += span_danger("It is damaged beyond repair.") + else + . += span_notice("It has a thermal rating of: [max_heat] C") + . += span_notice("It dissipates heat at: [heat_dissipation_per_tick] C") + . += span_notice("Heat capacity: [get_heat_percent()]%") + . += span_notice("Integrity: [integrity]%") + . += span_notice("Thermal throttle: [throttle_percentage]%") + . += span_notice("Cooling system: [cooling_system ? "enabled, cooling at [cooling_system_rate] C/s" : "disabled"].") + +/obj/item/microfusion_phase_emitter/proc/get_heat_percent() + return round(current_heat / max_heat * 100) + +/obj/item/microfusion_phase_emitter/proc/check_emitter() + if(damaged) + return PHASE_FAILURE_DAMAGED + if(get_heat_percent() >= throttle_percentage) + return PHASE_FAILURE_THROTTLE + return SHOT_SUCCESS + +/obj/item/microfusion_phase_emitter/proc/add_heat(heat_to_add) + current_heat += heat_to_add + update_appearance() + +/obj/item/microfusion_phase_emitter/proc/kill() + damaged = TRUE + name = "damaged [name]" + playsound(src, 'modular_skyrat/modules/microfusion/sound/overheat.ogg', 70) + say("ERROR: Integrity failure!") + STOP_PROCESSING(SSobj, src) + +/obj/item/microfusion_phase_emitter/enhanced + name = "enhanced microfusion phase emitter" + desc = "A second-generation phase emitter, this one is made of more robust materials which allow for a higher capacity for heat, a faster dissipation and cooling of it, and more capacity for thermal throttling." + max_heat = 3000 + throttle_percentage = 85 + heat_dissipation_per_tick = 40 + cooling_system_rate = 40 + integrity = 120 + color = "#ffffcc" + +/obj/item/microfusion_phase_emitter/advanced + name = "advanced microfusion phase emitter" + desc = "A third-generation phase emitter, boasting a high capacity for heat, greater dissipation and cooling, and is built using higher-grade materials for more durability." + max_heat = 4000 + throttle_percentage = 90 + heat_dissipation_per_tick = 50 + cooling_system_rate = 50 + integrity = 150 + color = "#99ffcc" + +/obj/item/microfusion_phase_emitter/bluespace + name = "bluespace microfusion phase emitter" + desc = "A fourth-generation phase emitter, utilizing a bluespace medium to store and manage heat, allowing for much cooler temperatures than realspace would allow. This is made of nothing but the latest materials, leading to the highest durability of any phase emitter on the market." + max_heat = 5000 + throttle_percentage = 95 + heat_dissipation_per_tick = 60 + cooling_system_rate = 60 + integrity = 200 + color = "#66ccff" + +/obj/item/microfusion_phase_emitter/nanocarbon + name = "nanocarbon microfusion phase emitter" + desc = "An experimental phase emitter, made of nanocarbon, which is the most durable material on the market. It is capable of storing and managing heat, and is capable of cooling at a much higher rate than the other phase emitters." + max_heat = 15000 + throttle_percentage = 95 + heat_dissipation_per_tick = 130 + cooling_system_rate = 60 + integrity = 500 + color = "#6966ff" diff --git a/monkestation/code/modules/microfusion/code/projectiles.dm b/monkestation/code/modules/microfusion/code/projectiles.dm new file mode 100644 index 000000000000..b11e1446f25c --- /dev/null +++ b/monkestation/code/modules/microfusion/code/projectiles.dm @@ -0,0 +1,44 @@ +/obj/item/ammo_casing + ///What volume should the sound play at? + var/fire_sound_volume = 50 + +/obj/item/ammo_casing/energy/laser/microfusion + name = "microfusion energy lens" + projectile_type = /obj/projectile/beam/laser/microfusion + e_cost = 100 // 10 shots with a normal cell. + select_name = "laser" + fire_sound = 'modular_skyrat/modules/microfusion/sound/laser_1.ogg' + fire_sound_volume = 100 + +/obj/projectile/beam/laser/microfusion + name = "microfusion laser" + icon = 'modular_skyrat/modules/microfusion/icons/projectiles.dmi' + +/obj/projectile/beam/microfusion_disabler + name = "microfusion disabler laser" + icon = 'modular_skyrat/modules/microfusion/icons/projectiles.dmi' + icon_state = "disabler" + damage = 41 + damage_type = STAMINA + flag = ENERGY + hitsound = 'sound/weapons/tap.ogg' + eyeblur = 0 + impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser + light_color = LIGHT_COLOR_BLUE + tracer_type = /obj/effect/projectile/tracer/disabler + muzzle_type = /obj/effect/projectile/muzzle/disabler + impact_type = /obj/effect/projectile/impact/disabler + +/obj/projectile/beam/laser/microfusion/superheated + name = "superheated microfusion laser" + icon_state = "laser_greyscale" + color = LIGHT_COLOR_FIRE + light_color = LIGHT_COLOR_FIRE + + +/obj/projectile/beam/laser/microfusion/superheated/on_hit(atom/target, blocked) + . = ..() + if(isliving(target)) + var/mob/living/living = target + living.fire_stacks += 2 + living.IgniteMob() diff --git a/monkestation/code/modules/microfusion/icons/guns_lefthand.dmi b/monkestation/code/modules/microfusion/icons/guns_lefthand.dmi new file mode 100644 index 0000000000000000000000000000000000000000..6690df96ac0be99c93cc597cec6d6085e63ccdb6 GIT binary patch literal 840 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 SBS<{}0000{uupYV;iVv;m~?~ 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 KMNUMnLSTXiORv!Y literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/microfusion/sound/burn.ogg b/monkestation/code/modules/microfusion/sound/burn.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ea37d14ccc12f91b1aad4196d3ad615cd389d16d GIT binary patch literal 34599 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 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/microfusion/sound/incinerate.ogg b/monkestation/code/modules/microfusion/sound/incinerate.ogg new file mode 100644 index 0000000000000000000000000000000000000000..38f7846d7abcb25429ba1d55a2d0aa9b6bc59c62 GIT binary patch literal 29379 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¬L_loTD`l1pu7t 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 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/microfusion/sound/mag_insert.ogg b/monkestation/code/modules/microfusion/sound/mag_insert.ogg new file mode 100644 index 0000000000000000000000000000000000000000..53460ebf14dde47201a3de1ab552e724875a8cef GIT binary patch literal 9407 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%0AqxB!|}Sdvp8jUH{R=7hbgN6 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 Wv?i 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 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/microfusion/sound/overheat.ogg b/monkestation/code/modules/microfusion/sound/overheat.ogg new file mode 100644 index 0000000000000000000000000000000000000000..3585471bf9b958af2025d35d4c02fbf657890706 GIT binary patch literal 64084 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 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/microfusion/sound/vaporize.ogg b/monkestation/code/modules/microfusion/sound/vaporize.ogg new file mode 100644 index 0000000000000000000000000000000000000000..0ba3085797337340b311d9b6cba538902b5fdc39 GIT binary patch literal 35624 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
act('change_gun_name')} /> + )}> + + + {gun_name} + + + {gun_desc} + + + {gun_heat_dissipation + ' C/s'} + + +
+ + +
act('eject_cell')} /> + )}> + {has_cell ? ( + + + {cell_data.type} + + + {cell_data.status ? 'ERROR' : 'Nominal'} + + + + {cell_data.charge + '/' + cell_data.max_charge + 'MF'} + + + {!!cell_data.charge <= 0 && ( + +
+ + Charge depleted! + +
+
+ )} +
+ ) : ( + + No cell installed! + + )} +
+
+ +
act('eject_emitter')} /> + )}> + {has_emitter ? ( + phase_emitter_data.damaged ? ( + + Phase emitter is damaged! + + ) : ( + + + {phase_emitter_data.type} + + + + {toFixed(phase_emitter_data.current_heat) + ' C' + ' (' + phase_emitter_data.heat_percent + '%)'} + + + + {phase_emitter_data.max_heat + ' C'} + + + {phase_emitter_data.throttle_percentage + '% '} +
+
+ +
+ {has_attachments ? ( + attachments.map((attachment, index) => ( +
act('remove_attachment', { + attachment_ref: attachment.ref, + })} /> + )}> + + + {attachment.desc} + + + {attachment.slot} + + {attachment.information && ( + + {attachment.information} + + )} + {!!attachment.has_modifications && ( + attachment.modify.map((mod, index) => ( + act('modify_attachment', { + attachment_ref: attachment.ref, + modify_ref: mod.reference, + })} /> + )} /> + )) + )} + +
+ )) + ) : ( + + No attachments installed! + + )} +
+
+ + + + ); +}; From ad64e214fbd0e4a71f6366001da429a43b31aa41 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 7 Dec 2021 00:12:21 +0000 Subject: [PATCH 02/49] Microfusion bugfixes (#9911) --- .../modules/microfusion/code/microfusion_designs.dm | 10 ++++++++++ .../microfusion/code/microfusion_gun_attachments.dm | 12 +++++++----- .../modules/microfusion/code/microfusion_techweb.dm | 2 ++ .../code/modules/microfusion/code/phase_emitter.dm | 6 +++--- .../code/modules/microfusion/code/projectiles.dm | 3 +++ 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_designs.dm b/monkestation/code/modules/microfusion/code/microfusion_designs.dm index 773777199434..b9716985c2b0 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_designs.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_designs.dm @@ -216,3 +216,13 @@ build_path = /obj/item/microfusion_gun_attachment/xray category = list("Weapons") departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion_gun_attachment_rgb + name = "Phase Emitter Spectrograph" + desc = "An attachment hooked up to the phase emitter, allowing the user to adjust the color of the beam outputted. This has seen widespread use by various factions capable of getting their hands on microfusion weapons, whether as a calling card or simply for entertainment." + id = "microfusion_gun_attachment_rgb" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/bronze = 500) + build_path = /obj/item/microfusion_gun_attachment/rgb + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE diff --git a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm index b7f3e85967ca..78107529c14a 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm @@ -28,6 +28,7 @@ microfusion_gun.heat_per_shot += heat_addition microfusion_gun.update_appearance() microfusion_gun.extra_power_usage += power_usage + microfusion_gun.chambered?.refresh_shot() return /obj/item/microfusion_gun_attachment/proc/process_attachment(obj/item/gun/microfusion/microfusion_gun) @@ -42,6 +43,7 @@ microfusion_gun.heat_per_shot -= heat_addition microfusion_gun.update_appearance() microfusion_gun.extra_power_usage -= power_usage + microfusion_gun.chambered?.refresh_shot() return /* @@ -275,14 +277,14 @@ Converts shots to STAMNINA damage. /obj/item/microfusion_gun_attachment/undercharger/proc/toggle(obj/item/gun/microfusion/microfusion_gun, mob/user) if(toggle) toggle = FALSE - microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase - microfusion_gun.recoil -= recoil_to_remove - microfusion_gun.spread -= spread_to_remove - else - toggle = TRUE microfusion_gun.heat_dissipation_bonus += cooling_rate_increase microfusion_gun.recoil += recoil_to_remove microfusion_gun.spread += spread_to_remove + else + toggle = TRUE + microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase + microfusion_gun.recoil -= recoil_to_remove + microfusion_gun.spread -= spread_to_remove if(user) to_chat(user, span_notice("You toggle [src] [toggle ? "ON" : "OFF"].")) diff --git a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm index a673f7fce652..8ca0068aa05c 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm @@ -24,6 +24,8 @@ "microfusion_cell_attachment_rechargeable", "enhanced_microfusion_phase_emitter", "microfusion_gun_attachment_black_camo", + "microfusion_gun_attachment_heatsink", + "microfusion_gun_attachment_rgb", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) diff --git a/monkestation/code/modules/microfusion/code/phase_emitter.dm b/monkestation/code/modules/microfusion/code/phase_emitter.dm index 99a72ec27f05..d9cdaeee15b4 100644 --- a/monkestation/code/modules/microfusion/code/phase_emitter.dm +++ b/monkestation/code/modules/microfusion/code/phase_emitter.dm @@ -173,7 +173,7 @@ Basically the heart of the gun, can be upgraded. /obj/item/microfusion_phase_emitter/enhanced name = "enhanced microfusion phase emitter" desc = "A second-generation phase emitter, this one is made of more robust materials which allow for a higher capacity for heat, a faster dissipation and cooling of it, and more capacity for thermal throttling." - max_heat = 3000 + max_heat = 2500 throttle_percentage = 85 heat_dissipation_per_tick = 40 cooling_system_rate = 40 @@ -183,7 +183,7 @@ Basically the heart of the gun, can be upgraded. /obj/item/microfusion_phase_emitter/advanced name = "advanced microfusion phase emitter" desc = "A third-generation phase emitter, boasting a high capacity for heat, greater dissipation and cooling, and is built using higher-grade materials for more durability." - max_heat = 4000 + max_heat = 3000 throttle_percentage = 90 heat_dissipation_per_tick = 50 cooling_system_rate = 50 @@ -193,7 +193,7 @@ Basically the heart of the gun, can be upgraded. /obj/item/microfusion_phase_emitter/bluespace name = "bluespace microfusion phase emitter" desc = "A fourth-generation phase emitter, utilizing a bluespace medium to store and manage heat, allowing for much cooler temperatures than realspace would allow. This is made of nothing but the latest materials, leading to the highest durability of any phase emitter on the market." - max_heat = 5000 + max_heat = 3500 throttle_percentage = 95 heat_dissipation_per_tick = 60 cooling_system_rate = 60 diff --git a/monkestation/code/modules/microfusion/code/projectiles.dm b/monkestation/code/modules/microfusion/code/projectiles.dm index b11e1446f25c..0f57162a6c9f 100644 --- a/monkestation/code/modules/microfusion/code/projectiles.dm +++ b/monkestation/code/modules/microfusion/code/projectiles.dm @@ -10,6 +10,9 @@ fire_sound = 'modular_skyrat/modules/microfusion/sound/laser_1.ogg' fire_sound_volume = 100 +/obj/item/ammo_casing/proc/refresh_shot() + loaded_projectile = new projectile_type(src, src) + /obj/projectile/beam/laser/microfusion name = "microfusion laser" icon = 'modular_skyrat/modules/microfusion/icons/projectiles.dmi' From dc6228503bf9274db9968247c3aaff57562de2e0 Mon Sep 17 00:00:00 2001 From: Nerevar <12636964+Snakebittenn@users.noreply.github.com> Date: Tue, 7 Dec 2021 13:59:54 -0700 Subject: [PATCH 03/49] Small Microfusion Hotfix (#9936) --- .../code/modules/microfusion/code/microfusion_designs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_designs.dm b/monkestation/code/modules/microfusion/code/microfusion_designs.dm index b9716985c2b0..b1b3df82e101 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_designs.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_designs.dm @@ -172,7 +172,7 @@ desc = "A heatsink attachment for your microfusion weapon. Massively increases cooling potential." id = "microfusion_gun_attachment_heatsink" build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/bronze = 500) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/heatsink category = list("Weapons") departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE @@ -222,7 +222,7 @@ desc = "An attachment hooked up to the phase emitter, allowing the user to adjust the color of the beam outputted. This has seen widespread use by various factions capable of getting their hands on microfusion weapons, whether as a calling card or simply for entertainment." id = "microfusion_gun_attachment_rgb" build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/bronze = 500) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/rgb category = list("Weapons") departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE From eaeef0111c0424fab499e1567db29a599bbd10b1 Mon Sep 17 00:00:00 2001 From: Tom <8881105+tf-4@users.noreply.github.com> Date: Wed, 8 Dec 2021 16:50:50 +0000 Subject: [PATCH 04/49] fixes microfusion charging runtime (#9953) --- .../code/modules/microfusion/code/microfusion_energy_master.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm index 836459c4cc47..747527fd354f 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm @@ -84,6 +84,9 @@ recharge_newshot() //and try to charge a new shot update_appearance() +/obj/item/gun/microfusion/get_cell() + return cell + /obj/item/gun/microfusion/Initialize(mapload) . = ..() if(cell_type) From 454d0101933f2dd45d9bd352c9f1654e4fd0aea0 Mon Sep 17 00:00:00 2001 From: Tom <8881105+tf-4@users.noreply.github.com> Date: Sat, 15 Jan 2022 16:28:22 +0000 Subject: [PATCH 05/49] MCR patch (#10714) --- .../modules/microfusion/code/microfusion_gun_attachments.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm index 78107529c14a..e118ae1a13b7 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm @@ -99,8 +99,8 @@ The cell is stable and will not emit sparks when firing. . = ..() microfusion_gun.recoil -= recoil_to_add microfusion_gun.spread -= spread_to_add - microfusion_gun.microfusion_lens.pellets -= microfusion_gun.microfusion_lens.pellets - microfusion_gun.microfusion_lens.variance -= microfusion_gun.microfusion_lens.variance + microfusion_gun.microfusion_lens.pellets -= pellets_to_add + microfusion_gun.microfusion_lens.variance -= variance_to_add /* REPEATER ATTACHMENT From 398fed6c87d237a56b2f8f03fc1ba353398be4f4 Mon Sep 17 00:00:00 2001 From: Tom <8881105+tf-4@users.noreply.github.com> Date: Sat, 15 Jan 2022 21:42:39 +0000 Subject: [PATCH 06/49] MCR fix 2 (#10720) --- .../microfusion/code/microfusion_gun_attachments.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm index e118ae1a13b7..15f393ac8cc8 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm @@ -301,9 +301,10 @@ Converts shots to STAMNINA damage. /obj/item/microfusion_gun_attachment/undercharger/remove_attachment(obj/item/gun/microfusion/microfusion_gun) . = ..() if(toggle) - microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase - microfusion_gun.recoil -= recoil_to_remove - microfusion_gun.spread -= spread_to_remove + toggle = FALSE + microfusion_gun.heat_dissipation_bonus += cooling_rate_increase + microfusion_gun.recoil += recoil_to_remove + microfusion_gun.spread += spread_to_remove microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound /* From b452ab239a70334584ffef94e66c321b358351aa Mon Sep 17 00:00:00 2001 From: Tom <8881105+tf-4@users.noreply.github.com> Date: Fri, 28 Jan 2022 22:02:24 +0000 Subject: [PATCH 07/49] fixes microfusion cell emp_act (#11077) --- monkestation/code/modules/microfusion/code/microfusion_cell.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_cell.dm b/monkestation/code/modules/microfusion/code/microfusion_cell.dm index f0953d7d9590..999c19ffb48f 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_cell.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_cell.dm @@ -56,7 +56,7 @@ These are basically advanced cells. /obj/item/stock_parts/cell/microfusion/emp_act(severity) var/prob_percent = charge / 100 * severity - if(prob(prob_percent) && !meltdown && !stabilised && parent_gun) + if(prob(prob_percent) && !meltdown && !stabilised) process_instability() /obj/item/stock_parts/cell/microfusion/use(amount) From 0a88d5f77bbc54abf6ad1a433a43f76d7b1539d0 Mon Sep 17 00:00:00 2001 From: Zenitheevee Date: Wed, 2 Feb 2022 13:38:13 -0800 Subject: [PATCH 08/49] why cant you be righthanded like all the other guns!? (#11220) --- .../code/microfusion_energy_master.dm | 809 ++++++++++++++++++ 1 file changed, 809 insertions(+) create mode 100644 modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm diff --git a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm new file mode 100644 index 000000000000..60cfefc56da6 --- /dev/null +++ b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm @@ -0,0 +1,809 @@ +#define DUALWIELD_PENALTY_EXTRA_MULTIPLIER 1.4 + +// Master file for cell loadable energy guns. PROCS ONLY YOU MONKEYS! +// This file is a copy/paste of _energy.dm with extensive modification. + +/obj/item/gun/microfusion + name = "prototype detatchable cell energy projection aparatus" + desc = "The coders have obviously failed to realise this is broken." + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun40x32.dmi' + icon_state = "mcr01" + bayonet_icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun40x32.dmi' + gunlight_icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun40x32.dmi' + lefthand_file = 'modular_skyrat/modules/microfusion/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/microfusion/icons/guns_righthand.dmi' + has_gun_safety = TRUE + can_flashlight = FALSE + can_bayonet = FALSE + w_class = WEIGHT_CLASS_BULKY + + /// What type of power cell this uses + var/obj/item/stock_parts/cell/microfusion/cell + /// The cell we will spawn with + var/cell_type = /obj/item/stock_parts/cell/microfusion + /// The cell type we check when inserting a cell + var/base_cell_type = /obj/item/stock_parts/cell/microfusion + /// If the weapon has custom icons for individual ammo types it can switch between. ie disabler beams, taser, laser/lethals, ect. + var/modifystate = FALSE + /// Can it be charged in a recharger? + var/can_charge = TRUE + /// How many charge sections do we have? + var/charge_sections = 4 + ammo_x_offset = 2 + /// if this gun uses a stateful charge bar for more detail + var/shaded_charge = FALSE + /// If this gun has a "this is loaded with X" overlay alongside chargebars and such + var/single_shot_type_overlay = TRUE + /// Should we give an overlay to empty guns? + var/display_empty = TRUE + /// whether the gun's cell drains the cyborg user's cell to recharge + var/dead_cell = FALSE + + // MICROFUSION SPECIFIC VARS + + /// The microfusion lens used for generating the beams. + var/obj/item/ammo_casing/energy/laser/microfusion/microfusion_lens + /// The time it takes for someone to (tactically) reload this gun. In deciseconds. + var/reload_time = 2 SECONDS + /// The sound played when you insert a cell. + var/sound_cell_insert = 'modular_skyrat/modules/microfusion/sound/mag_insert.ogg' + /// Should the insertion sound played vary? + var/sound_cell_insert_vary = TRUE + /// The volume at which we will play the insertion sound. + var/sound_cell_insert_volume = 50 + /// The sound played when you remove a cell. + var/sound_cell_remove = 'modular_skyrat/modules/microfusion/sound/mag_insert.ogg' + /// Should the removal sound played vary? + var/sound_cell_remove_vary = TRUE + /// The volume at which we will play the removal sound. + var/sound_cell_remove_volume = 50 + /// A list of attached upgrades + var/list/attachments = list() + /// The starting phase emitter in this weapon. + var/phase_emitter_type = /obj/item/microfusion_phase_emitter + /// The base emitter type that we check when putting a new emitter in. + var/base_phase_emitter_type = /obj/item/microfusion_phase_emitter + /// The phase emitter that this gun currently has. + var/obj/item/microfusion_phase_emitter/phase_emitter + /// The amount of heat produced per shot + var/heat_per_shot = 100 + /// The heat dissipation bonus granted by the weapon. + var/heat_dissipation_bonus = 0 + /// What slots does this gun have? + var/attachment_slots = list(GUN_SLOT_BARREL, GUN_SLOT_UNDERBARREL, GUN_SLOT_RAIL, GUN_SLOT_UNIQUE) + /// Our base firedelay. + var/base_fire_delay = 0 + /// Do we use more power because of attachments? + var/extra_power_usage = 0 + +/obj/item/gun/microfusion/emp_act(severity) + . = ..() + if(!(. & EMP_PROTECT_CONTENTS)) + cell.use(round(cell.charge / severity)) + chambered = null //we empty the chamber + recharge_newshot() //and try to charge a new shot + update_appearance() + +/obj/item/gun/microfusion/get_cell() + return cell + +/obj/item/gun/microfusion/Initialize(mapload) + . = ..() + if(cell_type) + cell = new cell_type(src) + else + cell = new(src) + cell.parent_gun = src + if(!dead_cell) + cell.give(cell.maxcharge) + if(phase_emitter_type) + phase_emitter = new phase_emitter_type(src) + else + phase_emitter = new(src) + phase_emitter.parent_gun = src + update_microfusion_lens() + recharge_newshot(TRUE) + update_appearance() + AddComponent(/datum/component/ammo_hud) + RegisterSignal(src, COMSIG_ITEM_RECHARGED, .proc/instant_recharge) + base_fire_delay = fire_delay + +/obj/item/gun/microfusion/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/gun/microfusion/add_weapon_description() + AddElement(/datum/element/weapon_description, attached_proc = .proc/add_notes_energy) + +/obj/item/gun/microfusion/Destroy() + if(microfusion_lens) + QDEL_NULL(microfusion_lens) + if(cell) + cell.parent_gun = null + QDEL_NULL(cell) + if(attachments.len) + for(var/obj/item/iterating_item in attachments) + qdel(iterating_item) + attachments = null + if(phase_emitter) + QDEL_NULL(phase_emitter) + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/gun/microfusion/handle_atom_del(atom/to_handle) + if(to_handle == cell) + cell = null + update_appearance() + if(to_handle == phase_emitter) + phase_emitter = null + update_appearance() + return ..() + +/obj/item/gun/microfusion/can_shoot() + return !QDELETED(cell) ? (cell.charge >= microfusion_lens.e_cost) : FALSE + +/obj/item/gun/microfusion/recharge_newshot() + if (!microfusion_lens || !cell || !phase_emitter) + return + chambered = microfusion_lens + if(!chambered.loaded_projectile) + chambered.newshot() + +/obj/item/gun/microfusion/handle_chamber() + if(chambered && !chambered.loaded_projectile && cell) //if loaded_projectile is null, i.e the shot has been fired... + var/obj/item/ammo_casing/energy/shot = chambered + cell.use(shot.e_cost + extra_power_usage)//... drain the cell + chambered = null //either way, released the prepared shot + recharge_newshot() //try to charge a new shot + +/obj/item/gun/microfusion/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) + if(!chambered && can_shoot()) + process_chamber() // If the gun was drained and then recharged, load a new shot. + return ..() + +/obj/item/gun/microfusion/update_icon_state() + var/skip_inhand = initial(inhand_icon_state) //only build if we aren't using a preset inhand icon + var/skip_worn_icon = initial(worn_icon_state) //only build if we aren't using a preset worn icon + + if(skip_inhand && skip_worn_icon) //if we don't have either, don't do the math. + return ..() + + var/ratio = get_charge_ratio() + var/temp_icon_to_use = initial(icon_state) + if(modifystate) + temp_icon_to_use += "[microfusion_lens.select_name]" + + temp_icon_to_use += "[ratio]" + if(!skip_inhand) + inhand_icon_state = temp_icon_to_use + if(!skip_worn_icon) + worn_icon_state = temp_icon_to_use + return ..() + +/obj/item/gun/microfusion/update_overlays() + . = ..() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) //update the ammo hud since it's heavily dependent on the gun's state + if(!phase_emitter) + . += "[icon_state]_phase_emitter_missing" + else if(phase_emitter.damaged) + . += "[icon_state]_phase_emitter_damaged" + else if(cell) + var/ratio = get_charge_ratio() + if(ratio == 0 && display_empty) + . += "[icon_state]_empty" + else if(shaded_charge) + . += "[icon_state]_charge[ratio]_[phase_emitter.icon_state]" + else + . += "[icon_state]_phase_emitter_missing" + + + for(var/obj/item/microfusion_gun_attachment/microfusion_gun_attachment in attachments) + . += "[icon_state]_[microfusion_gun_attachment.attachment_overlay_icon_state]" + + +/obj/item/gun/microfusion/ignition_effect(atom/to_ignite, mob/living/user) + if(!can_shoot() || !microfusion_lens) + shoot_with_empty_chamber() + . = "" + else + var/obj/projectile/energy/loaded_projectile = microfusion_lens.loaded_projectile + if(!loaded_projectile) + . = "" + else if(loaded_projectile.nodamage || !loaded_projectile.damage || loaded_projectile.damage_type == STAMINA) + user.visible_message(span_danger("[user] tries to light [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src], but it doesn't do anything. Dumbass.")) + playsound(user, microfusion_lens.fire_sound, 50, TRUE) + playsound(user, loaded_projectile.hitsound, 50, TRUE) + cell.use(microfusion_lens.e_cost) + . = "" + else if(loaded_projectile.damage_type != BURN) + user.visible_message(span_danger("[user] tries to light [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src], but only succeeds in utterly destroying it. Dumbass.")) + playsound(user, microfusion_lens.fire_sound, 50, TRUE) + playsound(user, loaded_projectile.hitsound, 50, TRUE) + cell.use(microfusion_lens.e_cost) + qdel(to_ignite) + . = "" + else + playsound(user, microfusion_lens.fire_sound, 50, TRUE) + playsound(user, loaded_projectile.hitsound, 50, TRUE) + cell.use(microfusion_lens.e_cost) + . = span_danger("[user] casually lights [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src]. Damn.") + +/obj/item/gun/microfusion/attackby(obj/item/attacking_item, mob/user, params) + . = ..() + if (.) + return + if(istype(attacking_item, base_cell_type)) + insert_cell(user, attacking_item) + if(istype(attacking_item, /obj/item/microfusion_gun_attachment)) + add_attachment(attacking_item, user) + if(istype(attacking_item, base_phase_emitter_type)) + insert_emitter(attacking_item, user) + +/obj/item/gun/microfusion/process_chamber(empty_chamber, from_firing, chamber_next_round) + . = ..() + if(!cell?.stabilised && prob(40)) + do_sparks(2, FALSE, src) //Microfusion guns create sparks! + +/obj/item/gun/microfusion/attack_hand(mob/user, list/modifiers) + if(loc == user && user.is_holding(src) && cell) + eject_cell(user) + return + return ..() + +/obj/item/gun/microfusion/crowbar_act(mob/living/user, obj/item/tool) + if(!phase_emitter) + to_chat(user, span_danger("There is no phase emitter for you to remove!")) + return + playsound(src, 'sound/items/crowbar.ogg', 70, TRUE) + remove_emitter() + +/obj/item/gun/microfusion/AltClick(mob/user) + . = ..() + if(can_interact(user)) + var/obj/item/microfusion_gun_attachment/to_remove = input(user, "Please select what part you'd like to remove.", "Remove attachment") as null|obj in sort_names(attachments) + if(!to_remove) + return + remove_attachment(to_remove, user) + +/obj/item/gun/microfusion/proc/remove_all_attachments() + if(attachments.len) + for(var/obj/item/microfusion_gun_attachment/attachment in attachments) + attachment.remove_attachment(src) + attachment.forceMove(get_turf(src)) + attachments -= attachment + update_appearance() + +/obj/item/gun/microfusion/examine(mob/user) + . = ..() + if(attachments.len) + for(var/obj/item/microfusion_gun_attachment/microfusion_gun_attachment in attachments) + . += span_notice("It has a [microfusion_gun_attachment.name] installed.") + . += span_notice("Alt+click it to remove an upgrade.") + if(phase_emitter) + . += span_notice("It has a [phase_emitter.name] installed, at [phase_emitter.get_heat_percent()]% heat capacity.") + . += span_notice("The [phase_emitter.name] is at [phase_emitter.integrity]% integrity.") + . += span_notice("The [phase_emitter.name] will thermal throttle at [phase_emitter.throttle_percentage]% heat capacity.") + . += span_notice("Use a crowbar to remove the phase emitter.") + else + . += span_danger("It does not have a phase emitter installed!") + + if(cell) + . += span_notice("It has a [cell.name] installed, with a capacity of [cell.charge]/[cell.maxcharge] MF.") + +/obj/item/gun/microfusion/suicide_act(mob/living/user) + if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD)) + user.visible_message(span_suicide("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!")) + sleep(25) + if(user.is_holding(src)) + user.visible_message(span_suicide("[user] melts [user.p_their()] face off with [src]!")) + playsound(loc, fire_sound, 50, TRUE, -1) + cell.use(microfusion_lens.e_cost) + update_appearance() + return(FIRELOSS) + else + user.visible_message(span_suicide("[user] panics and starts choking to death!")) + return(OXYLOSS) + else + user.visible_message(span_suicide("[user] is pretending to melt [user.p_their()] face off with [src]! It looks like [user.p_theyre()] trying to commit suicide!

q8HWLMNk7spxay=@dF!Z?#JW;He$Ja!c&}T4mWN$MAz1##phG>219> z-Y8v6_pR0cI5$EEOY8FZa;YCE0ANNWJM_nBVUg`|;p3GW-ZJB1W{o>dVo`&!Um)C-!+tALnNY0WR(?_E+4`{8r=bjxY|O_(^B zT~51TPS+sNv8AYK0`%>4K&k)$e>(wC1psIVFlT8qyz={3Q$@O(<*puOM(Kx~JJlmN zgfqq=-Q?l*ik0a)y$*o@fC=w8M2P5l;GuqiZH+axxoXM*lNfiAy$6Qs-Ck4O1Fy`p z2Sg>Pf=bO%eVmsb4I)Ul%waqqhu?etcK%!atF(@YrX0W#R%HZq04(mZNM{2~K;bUw zm>2+nJ{Ys|^x{l8dN6ALZTE*il>h4M%_9~!<)iI~xA|7o4Eycpb(KLZKIxIOOL&$J zN`!aW0B}W}f57aI?V`Gs8@`5PoX%i2wki$iS@BWl)$F|E6WO{Wws!2dH6E5N_1*CB z#mHEAt*B~)hso2VytOfOg+;2J^VFpd4Hi=D^}SR|0p!&#cT5)AMw#R$p-14eG)sah2-2pdMK!^Ysv#Jg0mo9pG+V)qcInj5$l9qi1 zPW*QiJoUUV>gib2#eOF*AzOpkTdVoa6S)f=s-Zyy45AN?BSa|H0DM9#V)c-G#73(4 z`J6=^P)9&pfW3S@<*na2d+A|_$gTY<7ukMI)h;k`PDzc(X;^Ys34j0ql_NkU!{clv z+5X~{oEDJ3_mO`7oURxxf%uZ}DV*dCE{SzZe9&aDD+y)h@98cn3_o=@nYf%nZ@}r{ z>3#yz*{4FEP%j4l1nk=Z+@Z`8?_4%8HV%u<6+Nd|;_FIkxX-$eMrbk0K>&b?48ZdW zTD^D*SbkuOq~;G$WsM2!b5gE%wEnidmMC6V&nnvGhfw&bJlxxoe$&&V*qrn!eE@tu zAC!I!QRgJxTXgT=>H2o4|_jDDlIiD7Vn=H3G==af`pl1!LD+E6|&=kM!mfGh% zo}85DU=@Y%y?$q1Fw= z^sH2Lq85jgod5v<+D9V7#}ebS{q}vmR5?N~@AXrP_)hT^arx>Rk9m(FPS#MdC10CD z#iiphALp`aV*A}R=jSGOrWm6FWI88N&P^z(3~VwdM4oPB*EE9K0e11!H5~o2FK>~a z`Lv7bfa%`O>oTXQU@6a%BPs?40I0@6I9!3h0Qb|_GhVM_Oy$xW?{wV5ww#-I!zZln z3fjx#c(KRh!{&RuB(J3$RQJ34A1P^0oo_Z5B+Id?z<72YOU*Fc=KptK4Njh zsCj}bcpH;#d(^972nGPCi6nzg?(JzAN>)AI5n@n(q*iz%MdvrY=hOMu{xp`zu-keV*Z#HX)yGU@)h&nI^fPAs5A4;h2hp?w;GvcO94J8M~=(s_aIhOemV) z8|s(@ZUdUhye|MNE;fcFqz@&OE}5@|$C}Gg6Y;44?f?MzVKEJ#U4P~2EMFV`zMbnz zBHOT#Zj|lM|6(((Iy`+#r!&|WdA0Wp&t_Qt%=5E+@}fg94e?0H@dq9Ctxtc%*tM+l z$F#MFal)&3`SG6Uwa#@ofBw)#>hfdz^HFXr66>wU_&QdD@Gx7YwpOLJu`#u2JNMwD z#2@Eq7W4H0PEIO?3};1ZdqKnl2WLrFPLXAJn+AbYQBi%(K~ZKv>5*1eE#;ncY0gTP zw#zx|7zH=gFNygsU%6QPGprkM9@m zffDIhM5X^zo$)ObJ+*qRj992-C?x;@0000K$`hK!NQjJ#Sj;i3ED2hj=hJ1qc6|aT zVl5>aWltYZby*a)ZSbtlJ3lV(bht^zx!4*owtkhuW=h(i)|<8>ikdOMhNAf2GhY+! z<{uf3uOzoIP5auoJn8dKAL^MBI?T#lOW>Vt&FEDZN?o8*H;t_DbnTJ&&A2A5&nEc| z^u{F&lG$4Z+f1LRpGSGV|LW+he7vfj*(LE{+g0BlN8T*9gde;jYbJHJSFvyS{p;oD zb<777ymQ*xOkfOz0~-prv#Wo4_&fL}e-5kg5z=vwo5_mbW)VDk8GhBf6hvv97?lMc z!Pm8QT`Rt8Yy}z9o?J=3`H&5atMzFVv%*N`VP}lB2(tO%IR>vSr7T~ zH=`rr7V>V9v+U1^Tk_F-g~*eSLN!hh4gI4be}b$sT_*S zYJ2IUReXty&2OEjPj|__(Z4vQ|Dt{!ZF1N8$!(en=afH+Z{^q-Nk90(VQ}~nd@vZ1 z@@C1#h&ka9Zu8uh1SN5_peN`jc2EEyT)+hYo{D_01gb-B3%Ecy75T9f2ssX>fJ+h* z*C;BhlmdWAOQQL7kKDVWM?mn<(AFZKzQ6r_^N9HP8cSU)@2!~gCB*RNSGQ!v>9qN= zlpZJ#&g+(h zX|=2xZjqITDwb#-EUUJY(x$QdR3UOn3HPrEo#+2b@+ExN%f#_NR}Y8~t`KdR%8K>P z`ci5zT#5lx1(CKs*Nj<;sbeoRzJ^Q2_Gz3zrmIn)E8u1lBB5t@+d)lhwY|RuHpEWJ zd;mZ)0A(m8DG2}o0BFh`ZA3M~8YC!zEyjVdXrdGY9uXo!xvONX@MG}YGJMHzNs-*# zK0qeVu9qk|ynp*AEi3hB&t7~TZX_SGYJ+vAwjhS<(NkkM%v24aNn)c;Jm|Hq>~EmI zI_pD3-Dz$AAOBk-P3q!aNN=9MuU3LG^Vn0ib&2=V@gll{{ju@LrV^jPpo?=`wT1Xa z=treG`X=Gvb`w+uKF@LcwUseeId6|+pPrDt-#Zjrw>|&{yScyq#3=)`H-3*_A^y2* zYIo|XU+EuW22tOYe*@8_7tapG^eTzOAMeuV>TP+)caS;BI!e#g z&cBtIvfgy1^PMs`ChfHp97Z`5Ib^|qktT4WeNO?Fg@g$t8M%@wo*c(qNmi3nYGY>u6TP6d-Yd8YxIzTa>%ms!ss9fw&bfhexHVs^?$pr6H1M zu2n-I7%$CKb6M}}=jriV!}&Y;-nLrISG|hLE~z!5L4eea+1uN2vNTT3TDSKKWdgxg z;9PnU%crq&C}olDU3&nS%aChZcI2egx@K)6l*vrePz*ha^|6@>Ky$W7V9WV|V_=o^fD`8K&fjz03-* z`t;YGz8=fG6viI2r$Rskne7(4X8KQ3fl5&;*!O+^E~c7;A|s-QF+V^116gWjxAt|MlfB*mh0JzlqnwB5N+CcEi7b+t)cX>2q{q|TvW-Q&0w%!)kYr`pskFp81 z7&$nU>~{CB@Nk)0Is;P0vf-}i7|#C7%0deM_TfZg@P}Diic;k3aP{|%J$H@tAg5^F z8M-ytO*4MOS4(xu{MP16tN)Em=XBYb6%H>mu2Ij1v&Q=2y*}5#JQAynz5YhCCE_+% zy#10#etlt#elO z-8yvhIgi>cZ2S4s_^ls*O7GT>Vk{_)FgrG*WGRseff$}7V3qe2A$ zzInWN0Bth@2pO1FZO3#{(oZQ!wru6O-=gJJkl1652@1WDBJ ziB>U%H&lqk(KYw(<|-Llj|K|QA$ADVnG_YXFg=bAX6#rHUDlpoAUD2@r#?MCpr0K1dwMB zCDf)10031}M;&vNi3(t%Dln>{{VK1EPMs`$e5boZN+^hg9dMjdk^lez000m(CIW!r zld~<%9#;l_V}d^LzW3+w7r4VoaSC>K;^j}xt(OGud%Zqz#c-d7&xBuPeAB6?f#p@J zPFHiWHl?ep)7zs^$As*{{_%C<$AbU*{_B2ly;qo$IGb<8Urob%JsS79{IHonN%Oo` zeCKLwMl;^LoXNdefmxDW@9U1E;rDxn@ugYky>);rK8q50*j{dXCWlR|L|;lDXp^06 zPKnJLhmLt!uc{5cEFis1Mn;iZRo5vt(}-ZKxdbCNw?F3iVgB9lyp$6>M483EsTCJ~ zl;w$KWu8{4{POPl!^zs6IXR*9dQ@v;w6#*{utcRh@xp!PO%j1UU-|f|tljGTTP>iqh*c^Mi`iFLZqfCmDulH1sJwvSTlTyS}8P2cY4ly&3TjTsRl)u7chE*0s-L;?sp*L3gex+RPbiN-S) zK3m#p&fNRsXE3Dc3Pg~Y*pO3C0sv2EXHx(GK$8Ff00000qe%b&2mk;8JAvpr761Qt z|NoBv|9b!by8r)+|NmqE|Ed0YTpLDrk=qFAvWCy&xj@`y?wC5OJ_zAE007x7HBv;{ zt4kO^14+Oe8h2`b-^`%~z5d!jr zP(6GQQA8EP8B`#NnE$=JtXGwJQ~Xy-UaVvu4kTGDRWqB@zZS#OWa)ewX(Xb`sv%>= zRJ&;!7Bwc1ddNtcmZs7OIgaR;uQRxZr7E#3vY=#&Vfa+9slqs~Tajfge`+vN z7ectifsJ0Y2?YQ$#?e9rDFpxk0000=r33&&Z#=S*_`_&^y-WARY$B-oxK3#%4t)!F zZ)F=^JoXt6=vlwhKa5uS2{F6ekMmkblb?U15 z#(C#eR%B;cW-w>}qY?+PWFxlG{TYeT>h#-Y7KmbEH(*=HCuuvISLxO{UfY4WtafF7 zbv{bdPGCxWQr9X;QfO1`ySJA%_dQRm*=@3}UPcr_0J^Te`|4o>!tnse${hY?tlc%N zMIH?xqsEwZHeEOL$FzQ+4BkEs0|5ZOi9996p55ogz8O91ubu)z1W`@ZELB^(t7q0KJ+C7o&cDTCny&je|6#qx$J!f)5Rd>T zQ~KG*e_FObygghK9E-&$b4Fm*w0aTCa$*@%^{nMgsFIII#p$MY(L)$pUVYbzWjs`5 z*r7$LLdm6Qtqm-5iKkUmSJ1br>(&V&4f(`v<36bN`uX#PABC4kNE`JrGeU!!x6|JRidgygm!tE{bwvHK}cu{F-$;$eL_-_Bmn>b z003Q98zoO2hk-LXnmVuabT(`4#&kGreA1@jSaq5nqZw7<>Z0!F_v1~-n8S8Ik?w=t-mateuz|m)E|-MqXhf3#pVsC+xrAR1zKQ%m|2=kkzCT^& zJds7&J%j?{Q`i~yc$ZEyzw!s6Op8>m+17d!+R5w&EK|ytcv9QtzI5#%i98GB5Uy`I z@pe9{xQaPdzuj15ORpeGd6o!E=xu_xKryMa%=f$-e$2k3sp2>VXrRKl78_<700rd zY%{L2!)^X5!!k2toMx~%gb6yybi$h-YAMgw=X;~P*=U_@C=%6MYI|_$>_*I?T@Oa>b+QQS8M#uI1er09LDBaiu>hib*7{+7r?qC17q&gp< z!di7Yk^5Sj_PHjc+f8BM(=F?Zt>=^TQ$v!!Dy>%Ypz=_FJC&Y9Tlsre59(>{GxSr8 zMZW7Lg|WMPpUyVVcK?0n_bc{izt2GL!Q>pdLIH?}ixD}w4TVQ5nV1FiaBJHTKuC=y z5K##LOh5x3YP@s|haB)w7>Q5g<$!2Px!cyeTpl5GtsF5TVkCgZxYWJt)@0x1QKr6z zqY+7HE@>dYrW93O!xRL_BO$d^$!g^0-PiW{nxd|A>Y)fdnXi_wr+w9}^#7og0%$5V zT{FZgR*SZ|men|a^?oT?G=$>x_sH&ga$SFZJ$n!6(>VmvT434iJkl(;6~Sx)MR@>i z)eCCf8a5rN8JVgOt6NL=Fq9uyf923xx2iVHs?@9Xi@um|Kwn?%@3V2tE4r7++-jcw zIW)CvZART6bE+Uii^5MjlwY%$vfk_(i*uY72cV#=XBBMShU(#BUg91jO=V@|A= zHL1MTGWXA?uS67vUtQ(NYTZYXRzZLi<~T+NX!pnrb$bISLqSPO0ssI2$M0Ud1@GpE z2sAT6D2jAyb#OrXo9=U{e#*p1qXFg;WAwx1u_4}@pHq%E9%Wat_%wz}FIAU?XSI#u z;pU#w+Z;Yk;+E z@;I4px>BCEwe;9N--Ij1yMtLu)BlwN;V>|Yokiy#hUM`m+AeEl`wRk=RW?g(P`_td z?nC%7Vqq__O?9kGo9m)qcDh|>$UpYQW%g%KmLame62=|_O)1^L=wsuvyf-Z3ceSX- z0pA+(ccq1f`<02)IMbmkKq4ON|DBC77i=*#YoZbEC5|d2m``OOg;JZD;6OkOT#gq< z8iLHsBJ{fnnvHRrJ|B7=DfrhV04@L-*Z@SnS-drfuY54TqZ$&O#mmmXq`~kMJ**;e zEjla@3khJF=&rhldumJT2|y7+GmP|~mX)`G)7r3dG6Em3vM72gBdQp9&;7kBE#$hc zB1O)M@%Iw1h5lRCJXXZC^N{-Vqg0lN8M>_2Ul>g-%d@)ax!xKiNOZ-i0|V!&^~|@V zA{wTPDXwX!a4?Rk+O8f>5-O9UDRF57!{^7(*GLUjEiC=R-sa1h3U%yU6|1%)zR$n8 zre<;eH4WgClp~&-k!@V6DClS*PXz!VRm+zcX&hI5JFA=~9{^GJqbo8Vu>gTPHs`dQpwe@$WT=x|zPVEnTOvsWY z$2>n$xjOiB_^YvLoPICI-KsL=-qbq3dm)aX$B@zU2y5Xd;F^|RU6Su;(MpL| zR&XEpMGli^Zs6~a{QgVsM6u0gG&(&EzEi(bIRscvNvMlBox@9Fqp9}+pr?@m1Y7|C zUTJ(z7~F1{h5R9-bE#BmylojIxj~ZahqejDdjJ55(=+n4&Pa!f03lVZ)2vThx;89l z`C1&*)DG*Kj+L|K<9s82{MMK*-?J*Rq8-&u@>DR|NJEE_I`|t>Pmg#|nEIWbFC85a zueSZ|s!n($8L~vJo@~`Eox1DtEX#;Omse5!pBiuUQ1&+eZOeS;I7vdv6j4FKcP|<% zFD{28#W%&^Y=}ZB+;Zm-C)p+9oip-SA%StQ^Lw*7w~sYa5J3!~!mPL}?o6C<4h}gz zJ;GA|C+V+w8@f$KN=A~-7&wQ;SXu4J^-CkDsS%4}Keq7bo#OuQ_13|`=Q!#l6G7GV zSFvnttfnd{f}|t>00000fJ(&#fX$-r`HH#N^a4@exq{gH85FfyxdKxkdz)oJ-$vUm)&D}u zYT^4M-zB3JzAlGbyGFA9>r3BRC(-#-^|O?De9`+)Hx%$e)Hawi{ow0hr_aw$yP`{J zo7r_PF3qPk=kwk^yq$mGxn|OZ5Xfq0wpWj=>{9bU;3Rw$N@xB{Y^*s^f6?N*+UjJk z)W6Slb-}yb$9S4X%~RfUSr`0uLcjc$vh>*!MTOVo)f(b>Qy#IR4tAT%uz1Ub_}L$} zL49Ut&9AjX^XRtuc~5$CMaUORAN+6aAKYB(>B^fMS;_Z@%t7DzFKkJi(b#$$<6{>D zB^GNO01T`t$~fO?`>E|Q)X7f^FmvagIgl)}i1G$~r%(VN0M=N%R}$JdGJ++(93mmf z#p1RDsLe>D#t)}0Rk#NL*kxv!BYXLv8M*gR)0DA>WS!xkEhrhVZZi2 z?ES~yk}uZUBU>L_*R7!*PLxlv-zZlQH(m#;A1UQ%nx@s7)o>-y4KHyN=>A4d|E=D7 zov)91PpGF}qM?rIlZHK}@8jdOdREnn0Mvi8=Iz_)5v_9xIjl2Am$)bHnY+?hy<(~< z*N7IC0RRT5|NC$L1ruw3`~e69_x$lF-C5%9dOU=dwE4q+#`zHUl8e^$f2!RL4&?bc zeH+h}uiu{g&c`<6d0M~wRn60V@73c^sprwWKhnX`EM+_Yq04BY;ktdqTX9`dfG*(B z&;R{9J?w{cMO=TVicXa!I1S2D3IYHC002OBf{-BrPF-pyTi&V@*NLC~%nF%TY_TGB z9k(Q}JkFryoiVue?j>Q4Vp zb(_(ph2<7^r3}A!M?RI#i8saYS@m`Z4|iEZIDly zM-geuiCye-b+NR(;b^eY3h($0001^NdN!|0000G4`9gxd53%^PwcLSk7Covh}F zZVv0_Z3ms&r~Or=EJM(%`&u=NcaFK9X`6neF)UC7z|C_$J;|ja_@qz4FJXV~<%6rC zF5Q&3qpv#sa8O8+9Ys}!;!JmU&Lg@wcJ8ljX6F4QOQNRY`aJ*?;s&rfpa8=kZqw5~ z!V%69(_{2K+UB>Wb=umtSOsL$*CyTI$9?(h@4tSY6(<~v*LkZ@v0AK#8gk$7wcw!u zJpW7Bxi;K?kDj>R7GBhTYJ7uz$8$OKKV5da-DYdBkNnpz4|Q8Z*#I!);`f{A-No|x V{7oHlo2r`lxY$SpNnIOazy=g-wUYn< literal 0 HcmV?d00001 diff --git a/tgui/packages/tgui/interfaces/MicrofusionGunControl.js b/tgui/packages/tgui/interfaces/MicrofusionGunControl.js new file mode 100644 index 000000000000..106ab778a326 --- /dev/null +++ b/tgui/packages/tgui/interfaces/MicrofusionGunControl.js @@ -0,0 +1,269 @@ +import { toFixed } from 'common/math'; +import { useBackend } from '../backend'; +import { NoticeBox, Section, Stack, Button, LabeledList, ProgressBar } from '../components'; +import { Window } from '../layouts'; + +export const MicrofusionGunControl = (props, context) => { + const { act, data } = useBackend(context); + const { cell_data } = data; + const { phase_emitter_data } = data; + const { + gun_name, + gun_desc, + gun_heat_dissipation, + has_cell, + has_emitter, + has_attachments, + attachments = [], + } = data; + return ( + + + + +

")) + playsound(src, dry_fire_sound, 30, TRUE) + return (OXYLOSS) + +// To maintain modularity, I am moving this proc override here. +/obj/item/gun/microfusion/fire_gun(atom/target, mob/living/user, flag, params) + if(QDELETED(target)) + return + if(firing_burst) + return + if(flag) //It's adjacent, is the user, or is on the user's person + if(target in user.contents) //can't shoot stuff inside us. + return + if(!ismob(target) || user.combat_mode) //melee attack + return + if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) + return + if(iscarbon(target)) + var/mob/living/carbon/carbon = target + for(var/i in carbon.all_wounds) + var/datum/wound/W = i + if(W.try_treating(src, user)) + return // another coward cured! + + if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can. + var/mob/living/living = user + if(!can_trigger_gun(living)) + return + if(flag) + if(user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + handle_suicide(user, target, params) + return + + if(!can_shoot()) //Just because you can pull the trigger doesn't mean it can shoot. + shoot_with_empty_chamber(user) + return + + if(check_botched(user)) + return + + var/obj/item/bodypart/other_hand = user.has_hand_for_held_index(user.get_inactive_hand_index()) //returns non-disabled inactive hands + if(weapon_weight == WEAPON_HEAVY && (user.get_inactive_held_item() || !other_hand)) + to_chat(user, span_warning("You need two hands to fire [src]!")) + return + + var/attempted_shot = process_emitter() + if(attempted_shot != SHOT_SUCCESS) + if(attempted_shot) + to_chat(user, span_danger(attempted_shot)) + return + + //DUAL (or more!) WIELDING + var/bonus_spread = 0 + var/loop_counter = 0 + if(ishuman(user) && user.combat_mode) + var/mob/living/carbon/human/H = user + for(var/obj/item/gun/gun in H.held_items) + if(gun == src || gun.weapon_weight >= WEAPON_MEDIUM) + continue + else if(gun.can_trigger_gun(user)) + bonus_spread += dual_wield_spread + loop_counter++ + addtimer(CALLBACK(gun, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter) + + return process_fire(target, user, TRUE, params, null, bonus_spread) + +// To maintain modularity, I am moving this proc override here. +/obj/item/gun/microfusion/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) + if(user) + SEND_SIGNAL(user, COMSIG_MOB_FIRED_GUN, user, target, params, zone_override) + + SEND_SIGNAL(src, COMSIG_GUN_FIRED, user, target, params, zone_override) + + add_fingerprint(user) + + if(semicd) + return + + //Vary by at least this much + var/base_bonus_spread = 0 + var/calculated_spread = 0 + var/randomized_gun_spread = 0 + var/random_spread = rand() + if(user && HAS_TRAIT(user, TRAIT_POOR_AIM)) //Nice job hotshot + bonus_spread += 35 + base_bonus_spread += 10 + + if(spread) + randomized_gun_spread = rand(0,spread) + var/randomized_bonus_spread = rand(base_bonus_spread, bonus_spread) + + if(burst_size > 1) + firing_burst = TRUE + var/fire_delay_to_add = 0 + if(phase_emitter) + fire_delay_to_add = phase_emitter.fire_delay + for(var/i = 1 to burst_size) + addtimer(CALLBACK(src, .proc/process_burst, user, target, message, params, zone_override, calculated_spread, randomized_gun_spread, randomized_bonus_spread, random_spread, i), (fire_delay + fire_delay_to_add) * (i - 1)) + else + if(chambered) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal. + if(chambered.harmful) // Is the bullet chambered harmful? + to_chat(user, span_warning("[src] is lethally chambered! You don't want to risk harming anyone...")) + return + calculated_spread = round((rand(0, 1) - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + before_firing(target,user) + process_microfusion() + if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, calculated_spread, src)) + shoot_with_empty_chamber(user) + return + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + else + shoot_with_empty_chamber(user) + return + process_chamber() + update_appearance() + semicd = TRUE + var/fire_delay_to_add = 0 + if(phase_emitter) + fire_delay_to_add = phase_emitter.fire_delay + addtimer(CALLBACK(src, .proc/reset_semicd), fire_delay + fire_delay_to_add) + + if(user) + user.update_inv_hands() + SSblackbox.record_feedback("tally", "gun_fired", 1, type) + + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + + return TRUE + +// Same goes for this! +/obj/item/gun/microfusion/process_burst(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", calculated_spread = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, random_spread= 0, iteration = 0) + if(!user || !firing_burst) + firing_burst = FALSE + return FALSE + if(!can_shoot()) + firing_burst = FALSE + return FALSE + if(!chambered) + process_chamber() // Ditto. + if(!issilicon(user)) + if(iteration > 1 && !(user.is_holding(src))) //for burst firing + firing_burst = FALSE + return FALSE + if(chambered?.loaded_projectile) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal. + if(chambered.harmful) // Is the bullet chambered harmful? + to_chat(user, span_warning("[src] is lethally chambered! You don't want to risk harming anyone...")) + return + if(randomspread) + calculated_spread = round((rand(0, 1) - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + else //Smart spread + calculated_spread = round((((random_spread/burst_size) * iteration) - (0.5 + (random_spread * 0.25))) * (randomized_gun_spread + randomized_bonus_spread)) + before_firing(target,user) + process_microfusion() + if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, calculated_spread, src)) + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + if (iteration >= burst_size) + firing_burst = FALSE + else + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + process_chamber() + update_appearance() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) + return TRUE + +/obj/item/gun/microfusion/shoot_live_shot(mob/living/user, pointblank, atom/pbtarget, message) + if(recoil) + shake_camera(user, recoil + 1, recoil) + + var/sound_freq_to_add = 0 + + if(phase_emitter && phase_emitter.sound_freq > 1) + sound_freq_to_add = phase_emitter.sound_freq + + if(suppressed) + playsound(user, suppressed_sound, suppressed_volume, vary_fire_sound, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, frequency = sound_freq_to_add, falloff_distance = 0) + else + playsound(user, fire_sound, fire_sound_volume, vary_fire_sound, frequency = sound_freq_to_add) + if(message) + if(pointblank) + user.visible_message(span_danger("[user] fires [src] point blank at [pbtarget]!"), \ + span_danger("You fire [src] point blank at [pbtarget]!"), \ + span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE, pbtarget) + to_chat(pbtarget, span_userdanger("[user] fires [src] point blank at you!")) + if(pb_knockback > 0 && ismob(pbtarget)) + var/mob/PBT = pbtarget + var/atom/throw_target = get_edge_target_turf(PBT, user.dir) + PBT.throw_at(throw_target, pb_knockback, 2) + else + user.visible_message(span_danger("[user] fires [src]!"), \ + span_danger("You fire [src]!"), \ + span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE) + if(user.resting) + user.Immobilize(20, TRUE) + + phase_emitter.add_heat(heat_per_shot) + + if(phase_emitter.current_heat > phase_emitter.max_heat) + if(ishuman(user)) + var/mob/living/carbon/human/human = user + var/obj/item/bodypart/affecting = human.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") + if(affecting?.receive_damage( 0, 5 )) // 1 burn damage + to_chat(user, span_warning("[src] burns your hand, it's too hot!")) + +/obj/item/gun/microfusion/proc/process_microfusion() + if(attachments.len) + for(var/obj/item/microfusion_gun_attachment/attachment in attachments) + attachment.process_fire(src, chambered) + return TRUE + +/obj/item/gun/microfusion/proc/process_emitter() + if(!phase_emitter) + return SHOT_FAILURE_NO_EMITTER + var/phase_emitter_process = phase_emitter.check_emitter() + if(phase_emitter_process != SHOT_SUCCESS) + return phase_emitter_process + return SHOT_SUCCESS + +/obj/item/gun/microfusion/proc/instant_recharge() + SIGNAL_HANDLER + if(!cell) + return + cell.charge = cell.maxcharge + recharge_newshot() + update_appearance() + +///Used by update_icon_state() and update_overlays() +/obj/item/gun/microfusion/proc/get_charge_ratio() + return can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0 + // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if its power cell is removed. + +/** + * + * Outputs type-specific weapon stats for energy-based firearms based on its firing modes + * and the stats of those firing modes. Esoteric firing modes like ion are currently not supported + * but can be added easily + * + */ +/obj/item/gun/microfusion/proc/add_notes_energy() + var/list/readout = list() + // Make sure there is something to actually retrieve + if(!microfusion_lens) + return + var/obj/projectile/exam_proj + readout += "Our heroic interns have shown that one can theoretically stay standing after..." + exam_proj = initial(microfusion_lens?.projectile_type) + + if(!istype(exam_proj)) + return readout.Join("\n") + + if(exam_proj.damage > 0) // Don't divide by 0!!!!! + readout += "[span_warning("[HITS_TO_CRIT(exam_proj.damage * microfusion_lens.pellets)] shot\s")] on [span_warning("[microfusion_lens.select_name]")] mode before collapsing from [exam_proj.damage_type == STAMINA ? "immense pain" : "their wounds"]." + if(exam_proj.stamina > 0) // In case a projectile does damage AND stamina damage (Energy Crossbow) + readout += "[span_warning("[HITS_TO_CRIT(exam_proj.stamina * microfusion_lens.pellets)] shot\s")] on [span_warning("[microfusion_lens.select_name]")] mode before collapsing from immense pain." + else + readout += "a theoretically infinite number of shots on [span_warning("[microfusion_lens.select_name]")] mode." + + return readout.Join("\n") // Sending over the singular string, rather than the whole list + +/obj/item/gun/microfusion/proc/update_microfusion_lens() + if(!microfusion_lens) + microfusion_lens = new(src) + fire_sound = microfusion_lens.fire_sound + fire_sound_volume = microfusion_lens.fire_sound_volume + fire_delay = microfusion_lens.delay + +// Cell, emitter and upgrade interactions + +/obj/item/gun/microfusion/proc/remove_emitter(mob/user) + playsound(src, sound_cell_insert, 50, TRUE) + phase_emitter.forceMove(get_turf(src)) + if(user) + user.put_in_hands(phase_emitter) + to_chat(user, span_notice("You remove [phase_emitter] from [src]!")) + phase_emitter.parent_gun = null + phase_emitter = null + update_appearance() + +/obj/item/gun/microfusion/proc/insert_emitter(obj/item/microfusion_phase_emitter/inserting_phase_emitter, mob/living/user) + if(phase_emitter) + to_chat(user, span_danger("There is already a phase emitter installed!")) + return FALSE + to_chat(user, span_notice("You carefully insert [inserting_phase_emitter] into the slot.")) + playsound(src, sound_cell_remove, 50, TRUE) + inserting_phase_emitter.forceMove(src) + phase_emitter = inserting_phase_emitter + phase_emitter.parent_gun = src + update_appearance() + + +/// Try to insert the cell into the gun, if successful, return TRUE +/obj/item/gun/microfusion/proc/insert_cell(mob/user, obj/item/stock_parts/cell/microfusion/inserting_cell, display_message = TRUE) + var/tactical_reload = FALSE //We need to do this so that cells don't fall on the ground. + var/obj/item/stock_parts/cell/old_cell = cell + if(cell) + if(reload_time && !HAS_TRAIT(user, TRAIT_INSTANT_RELOAD)) //This only happens when you're attempting a tactical reload, e.g. there's a mag already inserted. + if(display_message) + to_chat(user, span_notice("You start to insert [inserting_cell] into [src]!")) + if(!do_after(user, reload_time, src)) + if(display_message) + to_chat(user, span_warning("You fail to insert [inserting_cell] into [src]!")) + return FALSE + if(display_message) + to_chat(user, span_notice("You tactically reload [src], replacing [cell] inside!")) + tactical_reload = TRUE + eject_cell(user, FALSE, FALSE) + else if(display_message) + to_chat(user, span_notice("You insert [inserting_cell] into [src]!")) + if(sound_cell_insert) + playsound(src, sound_cell_insert, sound_cell_insert_volume, sound_cell_insert_vary) + cell = inserting_cell + inserting_cell.forceMove(src) + cell.parent_gun = src + if(tactical_reload) + user.put_in_hands(old_cell) + recharge_newshot() + update_appearance() + return TRUE + +/// Ejecting a cell. +/obj/item/gun/microfusion/proc/eject_cell(mob/user, display_message = TRUE, put_in_hands = TRUE) + var/obj/item/stock_parts/cell/microfusion/old_cell = cell + old_cell.forceMove(get_turf(src)) + if(user) + if(put_in_hands) + user.put_in_hands(old_cell) + if(display_message) + to_chat(user, span_notice("You remove [old_cell] from [src]!")) + if(sound_cell_remove) + playsound(src, sound_cell_remove, sound_cell_remove_volume, sound_cell_remove_vary) + old_cell.update_appearance() + cell.parent_gun = null + cell = null + update_appearance() + +/// Attatching an upgrade. +/obj/item/gun/microfusion/proc/add_attachment(obj/item/microfusion_gun_attachment/microfusion_gun_attachment, mob/living/user) + if(is_type_in_list(microfusion_gun_attachment, attachments)) + to_chat(user, span_warning("[src] already has [microfusion_gun_attachment] installed!")) + return FALSE + if(!(microfusion_gun_attachment.slot in attachment_slots)) + to_chat(user, span_warning("[src] cannot install [microfusion_gun_attachment]!")) + return FALSE + for(var/obj/item/microfusion_gun_attachment/iterating_attachment in attachments) + if(is_type_in_list(microfusion_gun_attachment, iterating_attachment.incompatable_attachments)) + to_chat(user, span_warning("[microfusion_gun_attachment] is not compatible with [iterating_attachment]!")) + return FALSE + if(iterating_attachment.slot != GUN_SLOT_UNIQUE && iterating_attachment.slot == microfusion_gun_attachment.slot) + to_chat(user, span_warning("[microfusion_gun_attachment] cannot be installed in the same slot as [iterating_attachment]!")) + return FALSE + attachments += microfusion_gun_attachment + microfusion_gun_attachment.forceMove(src) + microfusion_gun_attachment.run_attachment(src) + to_chat(user, span_notice("You successfully install [microfusion_gun_attachment] onto [src]!")) + playsound(src, 'sound/effects/structure_stress/pop2.ogg', 70, TRUE) + return TRUE + +/obj/item/gun/microfusion/proc/remove_attachment(obj/item/microfusion_gun_attachment/microfusion_gun_attachment, mob/living/user) + to_chat(user, span_notice("You remove [microfusion_gun_attachment] from [src]!")) + playsound(src, 'sound/items/screwdriver.ogg', 70) + microfusion_gun_attachment.forceMove(get_turf(src)) + attachments -= microfusion_gun_attachment + microfusion_gun_attachment.remove_attachment(src) + user?.put_in_hands(microfusion_gun_attachment) + update_appearance() + +/obj/item/gun/microfusion/proc/change_name(mob/user) + var/new_name = input(user, "Enter new name:", "Change gun name") as null|text + if(!new_name) + return + var/name_length = length(new_name) + if(name_length > GUN_MAX_NAME_CHARS && name_length < GUN_MIN_NAME_CHARS) + to_chat(user, span_warning("New name cannot be longer than 20 or shorter than 5 characters!")) + return + + name = sanitize(new_name) + update_appearance() + +// UI CONTROL + +/obj/item/gun/microfusion/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "MicrofusionGunControl") + ui.open() + +/obj/item/gun/microfusion/ui_data(mob/user) + var/list/data = list() + + data["gun_name"] = name + data["gun_desc"] = desc + data["gun_heat_dissipation"] = heat_dissipation_bonus + + if(phase_emitter) + data["has_emitter"] = TRUE + data["phase_emitter_data"] = list( + "type" = capitalize(phase_emitter.name), + "integrity" = phase_emitter.integrity, + "current_heat" = phase_emitter.current_heat, + "throttle_percentage" = phase_emitter.throttle_percentage, + "heat_dissipation_per_tick" = phase_emitter.heat_dissipation_per_tick, + "max_heat" = phase_emitter.max_heat, + "damaged" = phase_emitter.damaged, + "hacked" = phase_emitter.hacked, + "heat_percent" = phase_emitter.get_heat_percent(), + "process_time" = phase_emitter.fire_delay, + "cooling_system" = phase_emitter.cooling_system, + "cooling_system_rate" = phase_emitter.cooling_system_rate, + ) + else + data["has_emitter"] = FALSE + + if(cell) + var/list/attachments = list() + for(var/obj/item/microfusion_cell_attachment/attachment in cell.attachments) + attachments += attachment.name + data["has_cell"] = TRUE + data["cell_data"] = list( + "type" = capitalize(cell.name), + "charge" = cell.charge, + "max_charge" = cell.maxcharge, + "status" = cell.meltdown, + "attachments" = attachments, + ) + else + data["has_cell"] = FALSE + + + + if(attachments.len) + data["has_attachments"] = TRUE + data["attachments"] = list() + for(var/obj/item/microfusion_gun_attachment/attachment in attachments) + var/list/attachment_functions = attachment.get_modify_data() + var/has_modifications = FALSE + if(attachment_functions?.len > 0) + has_modifications = TRUE + data["attachments"] += list(list( + "name" = uppertext(attachment.name), + "desc" = attachment.desc, + "slot" = capitalize(attachment.slot), + "information" = attachment.get_information_data(), + "has_modifications" = has_modifications, + "modify" = attachment_functions, + "ref" = REF(attachment), + )) + + else + data["has_attachments"] = FALSE + + return data + +/obj/item/gun/microfusion/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("eject_cell") + if(!cell) + return + eject_cell(usr) + if("change_gun_name") + change_name(usr) + if("overclock_emitter") + if(!phase_emitter) + return + if(!phase_emitter.hacked) + return + phase_emitter.set_overclock(usr) + if("eject_emitter") + if(!phase_emitter) + return + remove_emitter(usr) + if("remove_attachment") + var/obj/item/microfusion_gun_attachment/to_remove = locate(params["attachment_ref"]) in src + if(!to_remove) + return + remove_attachment(to_remove, usr) + if("modify_attachment") + var/obj/item/microfusion_gun_attachment/to_modify = locate(params["attachment_ref"]) in src + if(!to_modify) + return + to_modify.run_modify_data(params["modify_ref"], usr, src) + if("toggle_cooling_system") + if(!phase_emitter) + return + phase_emitter.toggle_cooling_system(usr) + From 9c257950e163bf10a952d03b391597fe51134bcb Mon Sep 17 00:00:00 2001 From: ErdinyoBarboza Date: Sun, 20 Feb 2022 15:49:33 +0300 Subject: [PATCH 09/49] [SEMI-MODULAR] MCR Expansion Vol 1 & Balance Passes (#11377) * LasersAreTameNow * HellfireAndSuperheat * Update readme.md * Modular Edit of Damage * moreupdates * Update modular_skyrat/modules/microfusion/code/microfusion_gun_attachments.dm Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com> * goerofsleepy * eep * morestuff * Update microfusion_gun40x32.dmi * Update microfusion_designs.dm * price * oops * whyisthiscodenotworking * help * aaaaaaaaaaa * how * YeahBabyWeMadeIt * wowcoolreloads * LetsGoBaby * coolbox * Update modular_skyrat/modules/microfusion/code/cargo_stuff.dm Co-authored-by: OrionTheFox <76465278+OrionTheFox@users.noreply.github.com> * reviews * missedone * cells * cargo * aaaaaa * lasernerf * refactor * hhnnngh Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com> Co-authored-by: OrionTheFox <76465278+OrionTheFox@users.noreply.github.com> --- .../code/microfusion_energy_master.dm | 24 +- .../modules/sec_haul/code/guns/gun_spawns.dm | 2 + .../modules/microfusion/code/cargo_stuff.dm | 50 +++- .../modules/microfusion/code/gun_types.dm | 23 +- .../microfusion/code/microfusion_cell.dm | 11 +- .../code/microfusion_cell_attachments.dm | 39 +++ .../microfusion/code/microfusion_designs.dm | 274 +++++++++-------- .../code/microfusion_gun_attachments.dm | 283 ++++++++++++++++-- .../microfusion/code/microfusion_techweb.dm | 41 ++- .../modules/microfusion/code/projectiles.dm | 38 ++- .../microfusion/icons/microfusion_cells.dmi | Bin 1724 -> 2060 bytes .../icons/microfusion_gun40x32.dmi | Bin 4051 -> 5942 bytes .../icons/microfusion_gun_attachments.dmi | Bin 3393 -> 5234 bytes 13 files changed, 623 insertions(+), 162 deletions(-) diff --git a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm index 60cfefc56da6..ec5df16c6134 100644 --- a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm +++ b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm @@ -44,7 +44,9 @@ /// The microfusion lens used for generating the beams. var/obj/item/ammo_casing/energy/laser/microfusion/microfusion_lens /// The time it takes for someone to (tactically) reload this gun. In deciseconds. - var/reload_time = 2 SECONDS + var/reload_time = 6 SECONDS + /// The time it takes for someone to normally reload this gun. In deciseconds. + var/reload_time_slow = 4 SECONDS /// The sound played when you insert a cell. var/sound_cell_insert = 'modular_skyrat/modules/microfusion/sound/mag_insert.ogg' /// Should the insertion sound played vary? @@ -612,6 +614,8 @@ /obj/item/gun/microfusion/proc/insert_cell(mob/user, obj/item/stock_parts/cell/microfusion/inserting_cell, display_message = TRUE) var/tactical_reload = FALSE //We need to do this so that cells don't fall on the ground. var/obj/item/stock_parts/cell/old_cell = cell + reload_time_slow = inserting_cell.reloading_time + reload_time = inserting_cell.reloading_time_tactical if(cell) if(reload_time && !HAS_TRAIT(user, TRAIT_INSTANT_RELOAD)) //This only happens when you're attempting a tactical reload, e.g. there's a mag already inserted. if(display_message) @@ -624,8 +628,15 @@ to_chat(user, span_notice("You tactically reload [src], replacing [cell] inside!")) tactical_reload = TRUE eject_cell(user, FALSE, FALSE) - else if(display_message) - to_chat(user, span_notice("You insert [inserting_cell] into [src]!")) + else + if(display_message) + to_chat(user, span_notice("You start to insert [inserting_cell] into [src]!")) + if(!do_after(user, reload_time_slow, src)) + if(display_message) + to_chat(user, span_warning("You fail to insert [inserting_cell] into [src]!")) + return FALSE + if(display_message) + to_chat(user, span_notice("You insert [inserting_cell] into [src]!")) if(sound_cell_insert) playsound(src, sound_cell_insert, sound_cell_insert_volume, sound_cell_insert_vary) cell = inserting_cell @@ -637,6 +648,10 @@ update_appearance() return TRUE + /// Update reload timers +// /obj/item/gun/microfusion/proc/reload_timer(mob/user, obj/item/stock_parts/cell/microfusion/inserting_cell) + + /// Ejecting a cell. /obj/item/gun/microfusion/proc/eject_cell(mob/user, display_message = TRUE, put_in_hands = TRUE) var/obj/item/stock_parts/cell/microfusion/old_cell = cell @@ -651,6 +666,9 @@ old_cell.update_appearance() cell.parent_gun = null cell = null + // RESET THE RELOAD TIMER WHEN CELL IS OUT + reload_time = 6 SECONDS + reload_time_slow = 4 SECONDS update_appearance() /// Attatching an upgrade. diff --git a/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm b/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm index 4af51d2c4fa3..a352603b38e7 100644 --- a/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm +++ b/modular_skyrat/modules/sec_haul/code/guns/gun_spawns.dm @@ -72,6 +72,8 @@ /obj/item/storage/box/ammo_box/microfusion name = "microfusion cell container" desc = "A box filled with microfusion cells." + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_cells.dmi' + icon_state = "microfusion_box" /obj/item/storage/box/ammo_box/microfusion/PopulateContents() new /obj/item/storage/bag/ammo(src) diff --git a/monkestation/code/modules/microfusion/code/cargo_stuff.dm b/monkestation/code/modules/microfusion/code/cargo_stuff.dm index b29213fa2325..c7b9658e7ec8 100644 --- a/monkestation/code/modules/microfusion/code/cargo_stuff.dm +++ b/monkestation/code/modules/microfusion/code/cargo_stuff.dm @@ -35,12 +35,14 @@ crate_name = "Microfusion Cell Crate" /datum/supply_pack/security/mcr01_attachments - name = "MCR-01 Military Attachments Crate" - desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments!" - cost = CARGO_CRATE_VALUE * 15 + name = "MCR-01 Military Attachments Crate Type A" + desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments! This crate comes with two utilitarian repeater loadout." + cost = CARGO_CRATE_VALUE * 14 contains = list( - /obj/item/microfusion_gun_attachment/scope, - /obj/item/microfusion_gun_attachment/scope, + /obj/item/microfusion_cell_attachment/tactical, + /obj/item/microfusion_cell_attachment/tactical, + /obj/item/microfusion_cell_attachment/tactical, + /obj/item/microfusion_cell_attachment/tactical, /obj/item/microfusion_gun_attachment/grip, /obj/item/microfusion_gun_attachment/grip, /obj/item/microfusion_gun_attachment/rail, @@ -48,4 +50,40 @@ /obj/item/microfusion_gun_attachment/repeater, /obj/item/microfusion_gun_attachment/repeater, ) - crate_name = "MCR-01 Military Attachments Crate" + crate_name = "MCR-01 Military Attachments Crate Type A" + +/datum/supply_pack/security/mcr01_attachments + name = "MCR-01 Military Attachments Crate Type B" + desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments! This crate comes in a mixed specialist loadout." + cost = CARGO_CRATE_VALUE * 16 + contains = list( + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/scatter, + /obj/item/microfusion_gun_attachment/scatter, + /obj/item/microfusion_gun_attachment/scatter, + /obj/item/microfusion_gun_attachment/scope, + /obj/item/microfusion_gun_attachment/lance, + ) + crate_name = "MCR-01 Military Attachments Crate Type B" + + +/datum/supply_pack/security/mcr01_attachments + name = "HCR-01 Military Attachments Crate Type H" + desc = "Honkicron Clownery Systems Inhonkorated supplied HCR-01 Clownery spec attachments! This crate oddly smells of bananas." + cost = CARGO_CRATE_VALUE * 20 + contraband = TRUE + contains = list( + /obj/item/microfusion_gun_attachment/honk, + /obj/item/microfusion_gun_attachment/honk, + /obj/item/microfusion_gun_attachment/honk, + /obj/item/microfusion_gun_attachment/honk_camo, + /obj/item/microfusion_gun_attachment/honk_camo, + /obj/item/microfusion_gun_attachment/honk_camo, + /obj/item/food/pie/cream, + /obj/item/food/pie/cream, + /obj/item/food/pie/cream, + ) + crate_name = "MCR-01 Military Attachments Crate Type H" + diff --git a/monkestation/code/modules/microfusion/code/gun_types.dm b/monkestation/code/modules/microfusion/code/gun_types.dm index 4745258a564a..bc59c449176b 100644 --- a/monkestation/code/modules/microfusion/code/gun_types.dm +++ b/monkestation/code/modules/microfusion/code/gun_types.dm @@ -10,14 +10,35 @@ name = "Advanced MCR-01" cell_type = /obj/item/stock_parts/cell/microfusion/advanced phase_emitter_type = /obj/item/microfusion_phase_emitter/advanced - +/* THESE ARE STILL UTTERLY BROKEN /obj/item/gun/microfusion/mcr01/nanocarbon name = "Nanocarbon Destroyer" desc = "The pinnacle of the Nanocarbon weapon line. This weapon is the ultimate in power and performance. It is capable of firing a wide variety of beams, including a wide range of energy types, and is capable of firing a wide variety of frequencies." icon_state = "mcr01" inhand_icon_state = "mcr01" shaded_charge = TRUE + phase_emitter_type = /obj/item/microfusion_phase_emitter/nanocarbon + cell_type = /obj/item/stock_parts/cell/microfusion/nanocarbon + attachments = list( + /obj/item/microfusion_gun_attachment/pulse, + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/rail, + /obj/item/microfusion_gun_attachment/black_camo, + ) +//For syndicate uplink. +/obj/item/gun/microfusion/mcr01/syndie + name = "SCR-01" + desc = "A Syndicate brand copy of the MCR-01. It comes with a proprietary suppressor and some tactical attachments." + cell_type = /obj/item/stock_parts/cell/microfusion/advanced + phase_emitter_type = /obj/item/microfusion_phase_emitter/advanced + attachments = list( + /obj/item/microfusion_gun_attachment/suppressor, + /obj/item/microfusion_gun_attachment/grip, + /obj/item/microfusion_gun_attachment/rail, + /obj/item/microfusion_gun_attachment/syndi_camo, + ) +*/ /obj/item/storage/box/ammo_box/microfusion/advanced name = "advanced microfusion cell container" desc = "A box filled with microfusion cells." diff --git a/monkestation/code/modules/microfusion/code/microfusion_cell.dm b/monkestation/code/modules/microfusion/code/microfusion_cell.dm index 999c19ffb48f..6039a27b8533 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_cell.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_cell.dm @@ -33,6 +33,10 @@ These are basically advanced cells. var/empty_alarm_sound = 'sound/weapons/gun/general/empty_alarm.ogg' /// Do we have the self charging upgrade? var/self_charging = FALSE + /// We use this to edit the reload time of the gun + var/reloading_time = 4 SECONDS + /// We use this to edit the tactical reload time of the gun + var/reloading_time_tactical = 6 SECONDS /obj/item/stock_parts/cell /// Is this cell stabilised? (used in microfusion guns) @@ -114,7 +118,7 @@ These are basically advanced cells. . += span_notice("It has a [microfusion_cell_attachment.name] installed.") . += span_notice("Use a screwdriver to remove the attachments.") -/obj/item/stock_parts/cell/microfusion/proc/add_attachment(obj/item/microfusion_cell_attachment/microfusion_cell_attachment, mob/living/user) +/obj/item/stock_parts/cell/microfusion/proc/add_attachment(obj/item/microfusion_cell_attachment/microfusion_cell_attachment, mob/living/user, obj/item/gun/microfusion/microfusion_gun) if(attachments.len >= max_attachments) to_chat(user, span_warning("[src] cannot fit any more attachments!")) return FALSE @@ -172,14 +176,14 @@ These are basically advanced cells. desc = "A third generation microfusion cell, boasting a much higher shot count. Additionally, these come with support for up to three modifications to the cell itself." icon_state = "microfusion_advanced" maxcharge = 1700 - max_attachments = 3 + max_attachments = 2 /obj/item/stock_parts/cell/microfusion/bluespace name = "bluespace microfusion cell" desc = "A fourth generation microfusion cell, employing bluespace technology to store power in a medium that's bigger on the inside. This has the highest capacity of any man-portable cell, and has flexibility for four different attachments to the cell itself." icon_state = "microfusion_bluespace" maxcharge = 2000 - max_attachments = 4 + max_attachments = 3 /obj/item/stock_parts/cell/microfusion/nanocarbon name = "nanocarbon fusion cell" @@ -187,3 +191,4 @@ These are basically advanced cells. icon_state = "microfusion_nanocarbon" maxcharge = 30000 max_attachments = 420 + diff --git a/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm index 711d1db57aa3..a0dcce866558 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm @@ -130,3 +130,42 @@ If the cell isn't stabilised by a stabiliser, it may emit a radiation pulse. if(!microfusion_cell.stabilised && DT_PROB(1, delta_time)) radiation_pulse(src, 1, RAD_MEDIUM_INSULATION) + + +/* +RELOAD GRIP ATTACHMENT + +Makes normal reloads easier +*/ +/obj/item/microfusion_cell_attachment/reloader + name = "reloading handle microfusion cell attachment" + desc = "An aftermarket modification that makes the process of loading a MF cell far easier." + icon_state = "attachment_reloader" + attachment_overlay_icon_state = "microfusion_reloader" + +/obj/item/microfusion_cell_attachment/reloader/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.reloading_time = 2 SECONDS + +/obj/item/microfusion_cell_attachment/reloader/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.reloading_time = microfusion_cell?.reloading_time + +/* +TACTICAL GRIP ATTACHMENT + +Makes tactical reloads easier +*/ +/obj/item/microfusion_cell_attachment/tactical + name = "tac-reload handle microfusion cell attachment" + desc = "An aftermarket modification that makes the process of tactically loading a MF cell far easier and cooler." + icon_state = "attachment_tactical" + attachment_overlay_icon_state = "microfusion_tactical" + +/obj/item/microfusion_cell_attachment/tactical/add_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.reloading_time_tactical = 3 SECONDS + +/obj/item/microfusion_cell_attachment/tactical/remove_attachment(obj/item/stock_parts/cell/microfusion/microfusion_cell) + . = ..() + microfusion_cell.reloading_time_tactical = microfusion_cell?.reloading_time_tactical diff --git a/monkestation/code/modules/microfusion/code/microfusion_designs.dm b/monkestation/code/modules/microfusion/code/microfusion_designs.dm index b1b3df82e101..21287174c577 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_designs.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_designs.dm @@ -1,228 +1,250 @@ -// CELLS AND EMITTERS -/datum/design/basic_microfusion_cell +// BASE FOR MCR DESIGNS +/datum/design/microfusion + name = "Microfusion Part" + build_type = PROTOLATHE | AWAY_LATHE + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + construction_time = 10 SECONDS //dunno if this is for mechfabs or what but I'll keep this anyway + category = list("Weapons") + +// EMITTERS +/datum/design/microfusion/enhanced_phase_emitter + name = "Enhanced Microfusion Phase Emitter" + desc = "The core of a microfusion projection weapon, produces the laser." + id = "enhanced_microfusion_phase_emitter" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) + build_path = /obj/item/microfusion_phase_emitter/enhanced + +/datum/design/microfusion/advanced_phase_emitter + name = "Advanced Microfusion Phase Emitter" + desc = "The core of a microfusion projection weapon, produces the laser." + id = "advanced_microfusion_phase_emitter" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) + build_path = /obj/item/microfusion_phase_emitter/advanced + +/datum/design/microfusion/bluespace_phase_emitter + name = "Bluespace Microfusion Phase Emitter" + desc = "The core of a microfusion projection weapon, produces the laser." + id = "bluespace_microfusion_phase_emitter" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500, /datum/material/diamond = 500) + build_path = /obj/item/microfusion_phase_emitter/bluespace + +// CELLS +/datum/design/microfusion/cell + name = "Microfusion Cell" + desc = "A microfusion cell." + category = list("Ammo") + +/datum/design/microfusion/cell/basic name = "Basic Microfusion Cell" desc = "A basic microfusion cell with a capacity of 1200 MF and and 1 attachment points." id = "basic_microfusion_cell" build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE materials = list(/datum/material/iron = 1000, /datum/material/glass = 200) - construction_time = 10 SECONDS build_path = /obj/item/stock_parts/cell/microfusion - category = list("Misc", "Power Designs", "Machinery", "initial") - -/datum/design/microfusion_phase_emitter_undercharger - name = "Microfusion Phase Emitter Undercharger" - desc = "Inverts the output beam of the phase emitter, popular amongst law enforcement as a non-lethal upgrade." - id = "microfusion_phase_emitter_undercharger" - build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE - materials = list(/datum/material/iron = 1000, /datum/material/glass = 200) - construction_time = 10 SECONDS - build_path = /obj/item/microfusion_gun_attachment/undercharger - category = list("Misc", "Power Designs", "Machinery", "initial") + category = list("Ammo", "Security", "initial") -/datum/design/enhanced_microfusion_cell +/datum/design/microfusion/cell/enhanced name = "Enhanced Microfusion Cell" - desc = "An enhanced microfusion cell with a capacity of 1500 MF and 2 attachment points." + desc = "An enhanced microfusion cell with a capacity of 1500 MF and 1 attachment points." id = "enhanced_microfusion_cell" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 200, /datum/material/uranium = 200) - construction_time = 10 SECONDS build_path = /obj/item/stock_parts/cell/microfusion/enhanced - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE - -/datum/design/enhanced_microfusion_phase_emitter - name = "Enhanced Microfusion Phase Emitter" - desc = "The core of a microfusion projection weapon, produces the laser." - id = "enhanced_microfusion_phase_emitter" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) - construction_time = 10 SECONDS - build_path = /obj/item/microfusion_phase_emitter/enhanced - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/advanced_microfusion_cell +/datum/design/microfusion/cell/advanced name = "Advanced Microfusion Cell" - desc = "An advanced microfusion cell with a capacity of 1700 MF and 3 attachment points." + desc = "An advanced microfusion cell with a capacity of 1700 MF and 2 attachment points." id = "advanced_microfusion_cell" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/gold = 300, /datum/material/silver = 300, /datum/material/glass = 300, /datum/material/uranium = 300) - construction_time = 10 SECONDS build_path = /obj/item/stock_parts/cell/microfusion/advanced - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/advanced_microfusion_phase_emitter - name = "Advanced Microfusion Phase Emitter" - desc = "The core of a microfusion projection weapon, produces the laser." - id = "advanced_microfusion_phase_emitter" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) - construction_time = 10 SECONDS - build_path = /obj/item/microfusion_phase_emitter/advanced - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE - -/datum/design/bluespace_microfusion_cell +/datum/design/microfusion/cell/bluespace name = "Bluespace Microfusion Cell" - desc = "A bluespace microfusion cell with a capacity of 2000 MF and 4 attachment points." + desc = "A bluespace microfusion cell with a capacity of 2000 MF and 3 attachment points." id = "bluespace_microfusion_cell" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/gold = 300, /datum/material/glass = 300, /datum/material/diamond = 300, /datum/material/uranium = 300, /datum/material/titanium = 300, /datum/material/bluespace = 300) - construction_time = 10 SECONDS build_path = /obj/item/stock_parts/cell/microfusion/bluespace - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE - -/datum/design/bluespace_microfusion_phase_emitter - name = "Bluespace Microfusion Phase Emitter" - desc = "The core of a microfusion projection weapon, produces the laser." - id = "bluespace_microfusion_phase_emitter" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500, /datum/material/diamond = 500) - construction_time = 10 SECONDS - build_path = /obj/item/microfusion_phase_emitter/bluespace - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE // CELL UPGRADES -/datum/design/microfusion_cell_attachment_rechargeable +/datum/design/microfusion/cell_attachment_rechargeable name = "Rechargeable Microfusion Cell Attachment" desc = "An attachment for microfusion cells that allows conversion of KJ to MF in standard chargers." id = "microfusion_cell_attachment_rechargeable" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/gold = 1000) build_path = /obj/item/microfusion_cell_attachment/rechargeable - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_cell_attachment_stabiliser +/datum/design/microfusion/cell_attachment_stabiliser name = "Stabilising Microfusion Cell Attachment" desc = "Stabilises the internal fusion reaction of microfusion cells." id = "microfusion_cell_attachment_stabiliser" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000, /datum/material/silver = 1000) build_path = /obj/item/microfusion_cell_attachment/stabiliser - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_cell_attachment_overcapacity +/datum/design/microfusion/cell_attachment_overcapacity name = "Overcapacity Microfusion Cell Attachment" desc = "An attachment for microfusion cells that increases MF capacity." id = "microfusion_cell_attachment_overcapacity" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 500, /datum/material/gold = 500) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000, /datum/material/gold = 2000) build_path = /obj/item/microfusion_cell_attachment/overcapacity - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_cell_attachment_selfcharging +/datum/design/microfusion/cell_attachment_selfcharging name = "Self-Charging Microfusion Cell Attachment" desc = "Contains a small amount of infinitely decaying nuclear material, causing the fusion reaction to be self sustaining. WARNING: May cause radiation burns if not stabilised." id = "microfusion_cell_attachment_selfcharging" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/uranium = 1000) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/uranium = 5000, /datum/material/titanium = 5000, /datum/material/bluespace = 2500) // Makes it almost in-line with Advanced Egun pricing build_path = /obj/item/microfusion_cell_attachment/selfcharging - category = list("Misc", "Power Designs") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/microfusion/cell_attachment_tactical + name = "Tac-Reload Handle Microfusion Cell Attachment" + desc = "An aftermarket modification that makes the process of tactical reloading a MF cell far easier." + id = "microfusion_cell_attachment_tactical" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000, /datum/material/silver = 1000) + build_path = /obj/item/microfusion_cell_attachment/tactical + +/datum/design/microfusion/cell_attachment_reloader + name = "Reloading Handle Microfusion Cell Attachment" + desc = "An aftermarket modification that makes the process of loading a MF cell far easier." + id = "microfusion_cell_attachment_reloader" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000, /datum/material/silver = 1000) + build_path = /obj/item/microfusion_cell_attachment/reloader // GUN UPGRADES -/datum/design/microfusion_gun_attachment_grip +/datum/design/microfusion/phase_emitter_undercharger + name = "Microfusion Phase Emitter Undercharger" + desc = "Inverts the output beam of the phase emitter, popular amongst law enforcement as a non-lethal upgrade." + id = "microfusion_phase_emitter_undercharger" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 200) + build_path = /obj/item/microfusion_gun_attachment/undercharger + category = list("Weapons", "initial") + +/datum/design/microfusion/gun_attachment_grip name = "Microfusion Weapon Grip" desc = "A grip... for microfusion weapon platforms." id = "microfusion_gun_attachment_grip" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) build_path = /obj/item/microfusion_gun_attachment/grip - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_scope +/datum/design/microfusion/gun_attachment_scope name = "Microfusion Weapon Scope" desc = "A scope... for microfusion weapon platforms." id = "microfusion_gun_attachment_scope" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) build_path = /obj/item/microfusion_gun_attachment/scope - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_black_camo +/datum/design/microfusion/gun_attachment_black_camo name = "Black Camo Microfusion Frame" desc = "A frame modification for the MCR-10, changing the color of the gun to black." id = "microfusion_gun_attachment_black_camo" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/black_camo - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_rail +/datum/design/microfusion/gun_attachment_nt_camo + name = "Nanotrasen Camo Microfusion Frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to blue." + id = "microfusion_gun_attachment_nt_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma. = 500) + build_path = /obj/item/microfusion_gun_attachment/nt_camo + +/datum/design/microfusion/gun_attachment_syndi_camo + name = "Blood Red Camo Microfusion Frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to a slick blood red." + id = "microfusion_gun_attachment_syndi_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/titanium = 500) + build_path = /obj/item/microfusion_gun_attachment/syndi_camo + +/datum/design/microfusion/gun_attachment_honk_camo + name = "Bananium Microfusion Frame" + desc = "A frame modification for the MCR-01, plating the gun in bananium." + id = "microfusion_gun_attachment_honk_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/bananium = 500) + build_path = /obj/item/microfusion_gun_attachment/honk_camo + +/datum/design/microfusion/gun_attachment_rail name = "Microfusion Weapon Rail" desc = "A rail system for any additional attachments, such as a torch." id = "microfusion_gun_attachment_rail" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/rail - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_heatsink +/datum/design/microfusion/gun_attachment_heatsink name = "Phase Emitter Heatsink" desc = "A heatsink attachment for your microfusion weapon. Massively increases cooling potential." id = "microfusion_gun_attachment_heatsink" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/heatsink - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_scatter +/datum/design/microfusion/gun_attachment_scatter name = "Diffuser Microfusion Lens Attachment" desc = "Splits the microfusion laser beam entering the lens!" id = "microfusion_gun_attachment_scatter" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/silver = 500) build_path = /obj/item/microfusion_gun_attachment/scatter - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_superheat +/datum/design/microfusion/gun_attachment_superheat name = "Superheating Phase Emitter Upgrade" desc = "Superheats the beam, causing targets to ignite!" id = "microfusion_gun_attachment_superheat" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 500) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 1000) build_path = /obj/item/microfusion_gun_attachment/superheat - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_repeater +/datum/design/microfusion/gun_attachment_hellfire + name = "Hellfire Phase Emitter Upgrade" + desc = "Overheats the beam, causing nastier wounds and higher damage!" + id = "microfusion_gun_attachment_hellfire" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 500) + build_path = /obj/item/microfusion_gun_attachment/hellfire + +/datum/design/microfusion/gun_attachment_penetrator + name = "Focused Repeating Phase Emitter Upgrade" + desc = "Upgrades the central phase emitter to repeat twice and penetrate armor." + id = "microfusion_gun_attachment_penetrator" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/bluespace = 1000) + build_path = /obj/item/microfusion_gun_attachment/penetrator + +/datum/design/microfusion/gun_attachment_scattermax + name = "Crystalline Diffuser Microfusion Lens Attachment" + desc = "Splits the microfusion laser beam entering the lens even more!" + id = "microfusion_gun_attachment_scattermax" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/silver = 1000) + build_path = /obj/item/microfusion_gun_attachment/scattermax + +/datum/design/microfusion/gun_attachment_lance + name = "Lance Induction Carriage" + desc = "Turns the gun into a designated marksman rifle." + id = "microfusion_gun_attachment_lance" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 500, /datum/material/bluespace = 500) + build_path = /obj/item/microfusion_gun_attachment/lance + +/datum/design/microfusion/gun_attachment_suppressor + name = "Suppressor Lens Attachment" + desc = "An experimental barrel attachment that dampens the soundwave of the emitter, making the laser shots far more stealthy!" + id = "microfusion_gun_attachment_suppressor" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 1000) + build_path = /obj/item/microfusion_gun_attachment/suppressor + +/datum/design/microfusion/gun_attachment_honk + name = "Bananium Phase Emitter Upgrade" + desc = "Makes your lasers into the greatest clowning tool ever made. HONK!" + id = "microfusion_gun_attachment_honk" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/bananium = 1000) + build_path = /obj/item/microfusion_gun_attachment/honk + +/datum/design/microfusion/gun_attachment_repeater name = "Repeating Phase Emitter Upgrade" desc = "Upgrades the central phase emitter to repeat twice." id = "microfusion_gun_attachment_repeater" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/bluespace = 500) + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/bluespace = 1000) build_path = /obj/item/microfusion_gun_attachment/repeater - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_xray +/datum/design/microfusion/gun_attachment_xray name = "Phase Inverter Emitter Array" desc = "Experimental technology that inverts the central phase emitter causing the wave frequency to shift into X-ray. CAUTION: Phase emitter heats up very quickly." id = "microfusion_gun_attachment_xray" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 1000, /datum/material/uranium = 500, /datum/material/bluespace = 500) build_path = /obj/item/microfusion_gun_attachment/xray - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE -/datum/design/microfusion_gun_attachment_rgb +/datum/design/microfusion/gun_attachment_rgb name = "Phase Emitter Spectrograph" desc = "An attachment hooked up to the phase emitter, allowing the user to adjust the color of the beam outputted. This has seen widespread use by various factions capable of getting their hands on microfusion weapons, whether as a calling card or simply for entertainment." id = "microfusion_gun_attachment_rgb" - build_type = PROTOLATHE | AWAY_LATHE | MECHFAB materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/rgb - category = list("Weapons") - departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE diff --git a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm index 15f393ac8cc8..13c8c1f95e3a 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_gun_attachments.dm @@ -5,7 +5,7 @@ /obj/item/microfusion_gun_attachment name = "microfusion gun attachment" - desc = "broken" + desc = "If you see this yell at a coder" icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun_attachments.dmi' w_class = WEIGHT_CLASS_NORMAL /// The attachment overlay icon state. @@ -67,7 +67,7 @@ reference - The reference of the modification button, this is used to call the p /* SCATTER ATTACHMENT -The cell is stable and will not emit sparks when firing. +Turns the gun into a shotgun. */ /obj/item/microfusion_gun_attachment/scatter name = "diffuser microfusion lens upgrade" @@ -83,6 +83,7 @@ The cell is stable and will not emit sparks when firing. var/recoil_to_add = 1 /// The spread to add. var/spread_to_add = 10 + var/projectile_override = /obj/projectile/beam/laser/microfusion/scatter /obj/item/microfusion_gun_attachment/scatter/run_attachment(obj/item/gun/microfusion/microfusion_gun) . = ..() @@ -93,6 +94,7 @@ The cell is stable and will not emit sparks when firing. /obj/item/microfusion_gun_attachment/scatter/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) . = ..() + chambered.loaded_projectile = new projectile_override chambered.loaded_projectile?.damage = chambered.loaded_projectile.damage / chambered.pellets /obj/item/microfusion_gun_attachment/scatter/remove_attachment(obj/item/gun/microfusion/microfusion_gun) @@ -103,19 +105,60 @@ The cell is stable and will not emit sparks when firing. microfusion_gun.microfusion_lens.variance -= variance_to_add /* -REPEATER ATTACHMENT +CRYSTALLINE SCATTER ATTACHMENT -The gun can fire volleys of shots. +An overclocked shotgun. +*/ +/obj/item/microfusion_gun_attachment/scattermax + name = "crystalline diffuser microfusion lens upgrade" + desc = "An experimental diffusing lens system capable of splitting one beam into 7. However, it requires higher power usage as well as results in higher recoil." + icon_state = "attachment_scattermax" + attachment_overlay_icon_state = "attachment_scattermax" + slot = GUN_SLOT_BARREL + /// How many pellets are we going to add to the existing amount on the gun? + var/pellets_to_add = 6 + /// The variation in pellet scatter. + var/variance_to_add = 25 + /// How much recoil are we adding? + var/recoil_to_add = 1 + /// The spread to add. + var/spread_to_add = 15 + var/projectile_override =/obj/projectile/beam/laser/microfusion/scattermax + power_usage = 20 + +/obj/item/microfusion_gun_attachment/scattermax/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.spread += spread_to_add + microfusion_gun.microfusion_lens.pellets += pellets_to_add + microfusion_gun.microfusion_lens.variance += variance_to_add + +/obj/item/microfusion_gun_attachment/scattermax/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + chambered.loaded_projectile?.damage = chambered.loaded_projectile.damage / chambered.pellets + +/obj/item/microfusion_gun_attachment/scattermax/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.spread -= spread_to_add + microfusion_gun.microfusion_lens.pellets -= pellets_to_add + microfusion_gun.microfusion_lens.variance -= variance_to_add + +/* +SUPERHEAT ATTACHMENT + +Lasers set the target on fire. */ /obj/item/microfusion_gun_attachment/superheat name = "superheating phase emitter upgrade" desc = "A barrel attachment hooked to the phase emitter, this adjusts the beam's wavelength to carry an intense wave of heat; causing targets to ignite." icon_state = "attachment_superheat" attachment_overlay_icon_state = "attachment_superheat" - incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter) - heat_addition = 70 + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/hellfire) + heat_addition = 90 slot = GUN_SLOT_BARREL - var/projectile_override =/obj/projectile/beam/laser/microfusion/superheated + var/projectile_override =/obj/projectile/beam/laser/microfusion/scatter /obj/item/microfusion_gun_attachment/superheat/run_attachment(obj/item/gun/microfusion/microfusion_gun) . = ..() @@ -130,6 +173,35 @@ The gun can fire volleys of shots. . = ..() chambered.loaded_projectile = new projectile_override +/* +HELLFIRE ATTACHMENT + +Makes the gun shoot hellfire lasers. +*/ +/obj/item/microfusion_gun_attachment/hellfire + name = "hellfire emitter upgrade" + desc = "A barrel attachment hooked to the phase emitter, this adjusts the beam's wavelength to carry an extra wave of heat; causing nastier wounds and more damage." + icon_state = "attachment_hellfire" + attachment_overlay_icon_state = "attachment_hellfire" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/superheat) + heat_addition = 50 + power_usage = 20 + slot = GUN_SLOT_BARREL + var/projectile_override =/obj/projectile/beam/laser/microfusion/hellfire + +/obj/item/microfusion_gun_attachment/hellfire/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/melt.ogg' + +/obj/item/microfusion_gun_attachment/hellfire/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + + +/obj/item/microfusion_gun_attachment/hellfire/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + /* REPEATER ATTACHMENT @@ -149,7 +221,8 @@ The gun can fire volleys of shots. /// The burst to add to the gun. var/burst_to_add = 1 /// The delay to add to the firing. - var/delay_to_add = 2 + var/delay_to_add = 5 + var/projectile_override =/obj/projectile/beam/laser/microfusion/repeater /obj/item/microfusion_gun_attachment/repeater/run_attachment(obj/item/gun/microfusion/microfusion_gun) . = ..() @@ -165,6 +238,52 @@ The gun can fire volleys of shots. microfusion_gun.fire_delay -= delay_to_add microfusion_gun.spread -= spread_to_add +/obj/item/microfusion_gun_attachment/repeater/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override +/* +FOCUSED REPEATER ATTACHMENT + +The gun can fire volleys of shots that penetrate armor. +*/ +/obj/item/microfusion_gun_attachment/penetrator + name = "focused repeating phase emitter upgrade" + desc = "A focused variant of the repeating phase controller. It allows the lasers to penetrate armor however this results in higher power usage." + icon_state = "attachment_penetrator" + attachment_overlay_icon_state = "attachment_penetrator" + heat_addition = 40 + power_usage = 20 + slot = GUN_SLOT_BARREL + /// The spread to add to the gun. + var/spread_to_add = 15 + /// The recoil to add to the gun. + var/recoil_to_add = 1 + /// The burst to add to the gun. + var/burst_to_add = 1 + /// The delay to add to the firing. + var/delay_to_add = 5 + var/projectile_override =/obj/projectile/beam/laser/microfusion/penetrator + power_usage = 80 // A price to pay to penetrate through armor + +/obj/item/microfusion_gun_attachment/penetrator/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.burst_size += burst_to_add + microfusion_gun.fire_delay += delay_to_add + microfusion_gun.spread += spread_to_add + +/obj/item/microfusion_gun_attachment/penetrator/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.burst_size -= burst_to_add + microfusion_gun.fire_delay -= delay_to_add + microfusion_gun.spread -= spread_to_add + +/obj/item/microfusion_gun_attachment/penetrator/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + + /* X-RAY ATTACHMENT @@ -250,22 +369,19 @@ HEATSINK ATTACHMENT UNDERCHARGER ATTACHMENT Massively decreases the output beam of the phase emitter. -Converts shots to STAMNINA damage. +Converts shots to STAMINA damage. */ /obj/item/microfusion_gun_attachment/undercharger name = "phase emitter undercharger" desc = "An underbarrel system hooked to the phase emitter, this allows the weapon to also fire an electron bolt, producing a short-lived underpowered electric charge capable of stunning targets. These shots are less demanding on the weapon, leading to an increase in cooling rate." icon_state = "attachment_undercharger" attachment_overlay_icon_state = "attachment_undercharger" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/scattermax, /obj/item/microfusion_gun_attachment/honk) slot = GUN_SLOT_UNDERBARREL var/toggle = FALSE var/cooling_rate_increase = 10 /// The projectile we override var/projectile_override = /obj/projectile/beam/microfusion_disabler - /// How much recoil are we removing? - var/recoil_to_remove = 1 - /// How much spread are we removing? - var/spread_to_remove = 10 /obj/item/microfusion_gun_attachment/undercharger/get_modify_data() return list(list("title" = "Turn [toggle ? "OFF" : "ON"]", "icon" = "power-off", "color" = "[toggle ? "red" : "green"]", "reference" = "toggle_on_off")) @@ -278,13 +394,9 @@ Converts shots to STAMNINA damage. if(toggle) toggle = FALSE microfusion_gun.heat_dissipation_bonus += cooling_rate_increase - microfusion_gun.recoil += recoil_to_remove - microfusion_gun.spread += spread_to_remove else toggle = TRUE microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase - microfusion_gun.recoil -= recoil_to_remove - microfusion_gun.spread -= spread_to_remove if(user) to_chat(user, span_notice("You toggle [src] [toggle ? "ON" : "OFF"].")) @@ -303,8 +415,6 @@ Converts shots to STAMNINA damage. if(toggle) toggle = FALSE microfusion_gun.heat_dissipation_bonus += cooling_rate_increase - microfusion_gun.recoil += recoil_to_remove - microfusion_gun.spread += spread_to_remove microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound /* @@ -411,10 +521,46 @@ All tactical, all the time. */ /obj/item/microfusion_gun_attachment/black_camo name = "black camo microfusion frame" - desc = "A frame modification for the MCR-10, changing the color of the gun to black." + desc = "A frame modification for the MCR-01, changing the color of the gun to black." icon_state = "attachment_black" attachment_overlay_icon_state = "attachment_black" +/* +HONK CAMO ATTACHMENT + +Allows for a clown camo to be applied to the gun. +HONK!! +*/ +/obj/item/microfusion_gun_attachment/honk_camo + name = "bananium microfusion frame" + desc = "A frame modification for the MCR-01, plating the gun in bananium." + icon_state = "attachment_honk_camo" + attachment_overlay_icon_state = "attachment_honk_camo" + +/* +SYNDIE CAMO ATTACHMENT + +Allows for a blood red camo to be applied to the gun. +Totally not property of a hostile corporation. +*/ +/obj/item/microfusion_gun_attachment/syndi_camo + name = "blood red camo microfusion frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to a slick blood red." + icon_state = "attachment_syndi_camo" + attachment_overlay_icon_state = "attachment_syndi_camo" + +/* +NANOTRASEN CAMO ATTACHMENT + +Allows for an official blue camo to be applied to the gun. +Hail NanoTrasen. +*/ +/obj/item/microfusion_gun_attachment/nt_camo + name = "\improper NanoTrasen brand microfusion frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to blue." + icon_state = "attachment_nt_camo" + attachment_overlay_icon_state = "attachment_nt_camo" + /* PULSE ATTACHMENT @@ -448,3 +594,100 @@ The gun can fire PULSE shots. /obj/item/microfusion_gun_attachment/pulse/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) . = ..() chambered.loaded_projectile = new /obj/projectile/beam/pulse + +/* +SUPPRESSOR ATTACHMENT + +Makes operators operate operatingly. +*/ + +/obj/item/microfusion_gun_attachment/suppressor + name = "laser suppressor" // sure it makes no sense but its cool + desc = "An experimental barrel attachment that dampens the soundwave of the emitter, making the laser shots far more stealthy. Best paired with black camo." + icon_state = "attachment_suppressor" + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_suppressor" + +/obj/item/microfusion_gun_attachment/suppressor/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.suppressed = TRUE + +/obj/item/microfusion_gun_attachment/suppressor/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.suppressed = null + +/* +BIKEHORN ATTACHMENT + +HONK!! Does subpar stamina damage but slips people. +*/ + +/obj/item/microfusion_gun_attachment/honk + name = "bananium phase emitter upgrade" + desc = "An honksperimental barrel attachment that makes your lasers funnier." + icon_state = "attachment_honk" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/scattermax, /obj/item/microfusion_gun_attachment/undercharger) + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_honk" + var/added_fire_delay = 20 + +/obj/item/microfusion_gun_attachment/honk/examine(mob/user) + . = ..() + . += span_warning("CAUTION: The gun you are about to handle is extremely funny!") + +/obj/item/microfusion_gun_attachment/honk/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'sound/items/bikehorn.ogg' + microfusion_gun.fire_delay += added_fire_delay + +/obj/item/microfusion_gun_attachment/honk/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + microfusion_gun.fire_delay += added_fire_delay + +/obj/item/microfusion_gun_attachment/honk/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile.icon_state = "laser_greyscale" + chambered.loaded_projectile.color = COLOR_VIVID_YELLOW + chambered.loaded_projectile.light_color = COLOR_VIVID_YELLOW + chambered.loaded_projectile.damage_type = STAMINA + chambered.loaded_projectile.damage = 20 + chambered.loaded_projectile.flag = ENERGY + chambered.loaded_projectile.AddComponent(/datum/component/slippery, 20) + chambered.loaded_projectile.hitsound = 'sound/misc/slip.ogg' + chambered.loaded_projectile.impact_type = /obj/effect/projectile/impact/disabler + +/* +LANCE ATTACHMENT + +The gun fires fast heavy lasers but takes a long time to fire. +*/ +/obj/item/microfusion_gun_attachment/lance + name = "lance induction carriage" + desc = "A modification kit that turns the MCR into a designated marksman rifle. Fired beams boast greater firepower and speed however it is very draining on battery as well as generates an extreme amount of heat." + icon = 'icons/obj/improvised.dmi' + icon_state = "kitsuitcase" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/black_camo, /obj/item/microfusion_gun_attachment/nt_camo, /obj/item/microfusion_gun_attachment/honk_camo) + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_lance" + heat_addition = 150 + power_usage = 100 + var/added_fire_delay = 25 + +/obj/item/microfusion_gun_attachment/lance/examine(mob/user) + . = ..() + . += span_warning("CAUTION: Phase emitter heats up extremely quickly!") + +/obj/item/microfusion_gun_attachment/lance/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_delay += added_fire_delay + microfusion_gun.fire_sound = 'sound/weapons/lasercannonfire.ogg' + +/obj/item/microfusion_gun_attachment/lance/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_delay -= added_fire_delay + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + +/obj/item/microfusion_gun_attachment/lance/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new /obj/projectile/beam/laser/microfusion/lance diff --git a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm index 8ca0068aa05c..f7c304814770 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm @@ -24,8 +24,11 @@ "microfusion_cell_attachment_rechargeable", "enhanced_microfusion_phase_emitter", "microfusion_gun_attachment_black_camo", + "microfusion_gun_attachment_nt_camo", "microfusion_gun_attachment_heatsink", "microfusion_gun_attachment_rgb", + "microfusion_cell_attachment_tactical", + "microfusion_cell_attachment_reloader", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) @@ -46,8 +49,9 @@ "microfusion_cell_attachment_overcapacity", "microfusion_cell_attachment_stabiliser", "microfusion_gun_attachment_scatter", - "microfusion_gun_attachment_superheat", + "microfusion_gun_attachment_hellfire", "advanced_microfusion_phase_emitter", + "microfusion_gun_attachment_lance", "microfusion_gun_attachment_grip", "microfusion_gun_attachment_rail", "microfusion_gun_attachment_scope", @@ -74,7 +78,7 @@ ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) -// Bluespace microfusion +// Quantum microfusion /datum/techweb_node/quantum_microfusion id = "quantum_microfusion" display_name = "Quantum Microfusion Technology" @@ -87,3 +91,36 @@ "microfusion_gun_attachment_xray", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 15000) + +// Warcrime microfusion +/datum/techweb_node/illegal_microfusion + id = "illegal_microfusion" + display_name = "Illegal Microfusion Technology" + description = "Microfusion tech that has previously been banned by SolFed. I love the smell of plasma in the mornings." + prereq_ids = list( + "advanced_microfusion", + "syndicate_basic", + ) + design_ids = list( + "microfusion_gun_attachment_superheat", + "microfusion_gun_attachment_scattermax", + "microfusion_gun_attachment_penetrator", + "microfusion_gun_attachment_syndi_camo", + "microfusion_gun_attachment_suppressor", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +// clown microfusion. | This exists to not make this non modular +/datum/techweb_node/clown_microfusion + id = "clown_microfusion" + display_name = "Honkicron Clownery Systems Technology" + description = "Microfusion tech that is proprietary tech of Honkicron Clownery Systems. HONK!!" + prereq_ids = list( + "basic_microfusion", + "clown", + ) + design_ids = list( + "microfusion_gun_attachment_honk", + "microfusion_gun_attachment_honk_camo", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) //Its normally supposed to be in clown tech so diff --git a/monkestation/code/modules/microfusion/code/projectiles.dm b/monkestation/code/modules/microfusion/code/projectiles.dm index 0f57162a6c9f..988751c3287f 100644 --- a/monkestation/code/modules/microfusion/code/projectiles.dm +++ b/monkestation/code/modules/microfusion/code/projectiles.dm @@ -5,7 +5,7 @@ /obj/item/ammo_casing/energy/laser/microfusion name = "microfusion energy lens" projectile_type = /obj/projectile/beam/laser/microfusion - e_cost = 100 // 10 shots with a normal cell. + e_cost = 100 // 12 shots with a normal cell. select_name = "laser" fire_sound = 'modular_skyrat/modules/microfusion/sound/laser_1.ogg' fire_sound_volume = 100 @@ -16,6 +16,7 @@ /obj/projectile/beam/laser/microfusion name = "microfusion laser" icon = 'modular_skyrat/modules/microfusion/icons/projectiles.dmi' + damage = 20 /obj/projectile/beam/microfusion_disabler name = "microfusion disabler laser" @@ -35,6 +36,7 @@ /obj/projectile/beam/laser/microfusion/superheated name = "superheated microfusion laser" icon_state = "laser_greyscale" + damage = 15 //Trading damage for fire stacks color = LIGHT_COLOR_FIRE light_color = LIGHT_COLOR_FIRE @@ -45,3 +47,37 @@ var/mob/living/living = target living.fire_stacks += 2 living.IgniteMob() + +/obj/projectile/beam/laser/microfusion/hellfire + name = "hellfire microfusion laser" + icon_state = "laser_greyscale" + wound_bonus = 0 + damage = 25 // Basically a hellfire beam + speed = 0.6 + color = LIGHT_COLOR_FLARE + light_color = LIGHT_COLOR_FLARE + +/obj/projectile/beam/laser/microfusion/scatter + name = "scatter microfusion laser" + damage = 30 // This damage is split into pellet amount + +/obj/projectile/beam/laser/microfusion/scattermax + name = "scatter microfusion laser" + damage = 45 // This damage is split into pellet amount + +/obj/projectile/beam/laser/microfusion/repeater + name = "scatter microfusion laser" + damage = 15 // No more a x2 damage buff + +/obj/projectile/beam/laser/microfusion/penetrator + name = "scatter microfusion laser" + damage = 15 + armour_penetration = 50 + +/obj/projectile/beam/laser/microfusion/lance + name = "lance microfusion laser" + damage = 40 // Were turning the gun into a heavylaser + tracer_type = /obj/effect/projectile/tracer/heavy_laser + muzzle_type = /obj/effect/projectile/muzzle/heavy_laser + impact_type = /obj/effect/projectile/impact/heavy_laser + speed = 0.4 diff --git a/monkestation/code/modules/microfusion/icons/microfusion_cells.dmi b/monkestation/code/modules/microfusion/icons/microfusion_cells.dmi index 12afc1a7183d858763559b3c69bb76e2695d063e..10d19a08544dba9521dbaa867aa4b536ddd87f98 100644 GIT binary patch delta 1889 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 literal 4051 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 literal 3393 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 Date: Tue, 22 Feb 2022 16:03:02 +0000 Subject: [PATCH 10/49] [MODULAR] Refactors MCR designs (#11536) * refactors MCR design * forgot one designpath * more sorting im sorry @ErdinyoBarboza * linters hate him! * not again * I found a bug --- .../microfusion/code/microfusion_designs.dm | 131 +++++++++--------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_designs.dm b/monkestation/code/modules/microfusion/code/microfusion_designs.dm index 21287174c577..0cc3a41514af 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_designs.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_designs.dm @@ -107,7 +107,22 @@ materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 1000, /datum/material/silver = 1000) build_path = /obj/item/microfusion_cell_attachment/reloader -// GUN UPGRADES +// RAIL MODS +/datum/design/microfusion/gun_attachment_scope + name = "Microfusion Weapon Scope" + desc = "A scope... for microfusion weapon platforms." + id = "microfusion_gun_attachment_scope" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) + build_path = /obj/item/microfusion_gun_attachment/scope + +/datum/design/microfusion/gun_attachment_rail + name = "Microfusion Weapon Rail" + desc = "A rail system for any additional attachments, such as a torch." + id = "microfusion_gun_attachment_rail" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) + build_path = /obj/item/microfusion_gun_attachment/rail + +// BARREL MODS /datum/design/microfusion/phase_emitter_undercharger name = "Microfusion Phase Emitter Undercharger" desc = "Inverts the output beam of the phase emitter, popular amongst law enforcement as a non-lethal upgrade." @@ -123,48 +138,6 @@ materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) build_path = /obj/item/microfusion_gun_attachment/grip -/datum/design/microfusion/gun_attachment_scope - name = "Microfusion Weapon Scope" - desc = "A scope... for microfusion weapon platforms." - id = "microfusion_gun_attachment_scope" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500) - build_path = /obj/item/microfusion_gun_attachment/scope - -/datum/design/microfusion/gun_attachment_black_camo - name = "Black Camo Microfusion Frame" - desc = "A frame modification for the MCR-10, changing the color of the gun to black." - id = "microfusion_gun_attachment_black_camo" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/gold = 500) - build_path = /obj/item/microfusion_gun_attachment/black_camo - -/datum/design/microfusion/gun_attachment_nt_camo - name = "Nanotrasen Camo Microfusion Frame" - desc = "A frame modification for the MCR-01, changing the color of the gun to blue." - id = "microfusion_gun_attachment_nt_camo" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma. = 500) - build_path = /obj/item/microfusion_gun_attachment/nt_camo - -/datum/design/microfusion/gun_attachment_syndi_camo - name = "Blood Red Camo Microfusion Frame" - desc = "A frame modification for the MCR-01, changing the color of the gun to a slick blood red." - id = "microfusion_gun_attachment_syndi_camo" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/titanium = 500) - build_path = /obj/item/microfusion_gun_attachment/syndi_camo - -/datum/design/microfusion/gun_attachment_honk_camo - name = "Bananium Microfusion Frame" - desc = "A frame modification for the MCR-01, plating the gun in bananium." - id = "microfusion_gun_attachment_honk_camo" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/bananium = 500) - build_path = /obj/item/microfusion_gun_attachment/honk_camo - -/datum/design/microfusion/gun_attachment_rail - name = "Microfusion Weapon Rail" - desc = "A rail system for any additional attachments, such as a torch." - id = "microfusion_gun_attachment_rail" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) - build_path = /obj/item/microfusion_gun_attachment/rail - /datum/design/microfusion/gun_attachment_heatsink name = "Phase Emitter Heatsink" desc = "A heatsink attachment for your microfusion weapon. Massively increases cooling potential." @@ -172,6 +145,28 @@ materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/heatsink +/datum/design/microfusion/gun_attachment_suppressor + name = "Suppressor Lens Attachment" + desc = "An experimental barrel attachment that dampens the soundwave of the emitter, making the laser shots far more stealthy!" + id = "microfusion_gun_attachment_suppressor" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 1000) + build_path = /obj/item/microfusion_gun_attachment/suppressor + +/datum/design/microfusion/gun_attachment_honk + name = "Bananium Phase Emitter Upgrade" + desc = "Makes your lasers into the greatest clowning tool ever made. HONK!" + id = "microfusion_gun_attachment_honk" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/bananium = 1000) + build_path = /obj/item/microfusion_gun_attachment/honk + +/datum/design/microfusion/gun_attachment_lance + name = "Lance Induction Carriage" + desc = "Turns the gun into a designated marksman rifle." + id = "microfusion_gun_attachment_lance" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 500, /datum/material/bluespace = 500) + build_path = /obj/item/microfusion_gun_attachment/lance + +// EMITTER UPGRADES /datum/design/microfusion/gun_attachment_scatter name = "Diffuser Microfusion Lens Attachment" desc = "Splits the microfusion laser beam entering the lens!" @@ -207,27 +202,6 @@ materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/silver = 1000) build_path = /obj/item/microfusion_gun_attachment/scattermax -/datum/design/microfusion/gun_attachment_lance - name = "Lance Induction Carriage" - desc = "Turns the gun into a designated marksman rifle." - id = "microfusion_gun_attachment_lance" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 500, /datum/material/plasma = 500, /datum/material/bluespace = 500) - build_path = /obj/item/microfusion_gun_attachment/lance - -/datum/design/microfusion/gun_attachment_suppressor - name = "Suppressor Lens Attachment" - desc = "An experimental barrel attachment that dampens the soundwave of the emitter, making the laser shots far more stealthy!" - id = "microfusion_gun_attachment_suppressor" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 1000) - build_path = /obj/item/microfusion_gun_attachment/suppressor - -/datum/design/microfusion/gun_attachment_honk - name = "Bananium Phase Emitter Upgrade" - desc = "Makes your lasers into the greatest clowning tool ever made. HONK!" - id = "microfusion_gun_attachment_honk" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/bananium = 1000) - build_path = /obj/item/microfusion_gun_attachment/honk - /datum/design/microfusion/gun_attachment_repeater name = "Repeating Phase Emitter Upgrade" desc = "Upgrades the central phase emitter to repeat twice." @@ -242,9 +216,38 @@ materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/diamond = 1000, /datum/material/uranium = 500, /datum/material/bluespace = 500) build_path = /obj/item/microfusion_gun_attachment/xray +// COSMETICS /datum/design/microfusion/gun_attachment_rgb name = "Phase Emitter Spectrograph" desc = "An attachment hooked up to the phase emitter, allowing the user to adjust the color of the beam outputted. This has seen widespread use by various factions capable of getting their hands on microfusion weapons, whether as a calling card or simply for entertainment." id = "microfusion_gun_attachment_rgb" materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/silver = 500, /datum/material/gold = 500) build_path = /obj/item/microfusion_gun_attachment/rgb + +/datum/design/microfusion/gun_attachment_black_camo + name = "Black Camo Microfusion Frame" + desc = "A frame modification for the MCR-10, changing the color of the gun to black." + id = "microfusion_gun_attachment_black_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/gold = 500) + build_path = /obj/item/microfusion_gun_attachment/black_camo + +/datum/design/microfusion/gun_attachment_nt_camo + name = "Nanotrasen Camo Microfusion Frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to blue." + id = "microfusion_gun_attachment_nt_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/plasma = 500) + build_path = /obj/item/microfusion_gun_attachment/nt_camo + +/datum/design/microfusion/gun_attachment_syndi_camo + name = "Blood Red Camo Microfusion Frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to a slick blood red." + id = "microfusion_gun_attachment_syndi_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/titanium = 500) + build_path = /obj/item/microfusion_gun_attachment/syndi_camo + +/datum/design/microfusion/gun_attachment_honk_camo + name = "Bananium Microfusion Frame" + desc = "A frame modification for the MCR-01, plating the gun in bananium." + id = "microfusion_gun_attachment_honk_camo" + materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000, /datum/material/bananium = 500) + build_path = /obj/item/microfusion_gun_attachment/honk_camo From 44fd5c1e8c399a1945850f29265a94a11a025bf8 Mon Sep 17 00:00:00 2001 From: OrionTheFox <76465278+OrionTheFox@users.noreply.github.com> Date: Wed, 13 Apr 2022 07:57:12 -0600 Subject: [PATCH 11/49] cells fix!! (#12724) --- code/game/machinery/cell_charger.dm | 2 + .../modules/aesthetics/cells/cell.dm | 58 +++++++++++++++++- .../modules/aesthetics/cells/cell.dmi | Bin 0 -> 6163 bytes .../modules/new_cells/code/power_cell.dm | 55 +++++++++++++++++ .../modules/new_cells/icons/power.dmi | Bin 0 -> 492 bytes .../microfusion/code/microfusion_cell.dm | 2 +- 6 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 modular_skyrat/modules/aesthetics/cells/cell.dmi create mode 100644 modular_skyrat/modules/new_cells/code/power_cell.dm create mode 100644 modular_skyrat/modules/new_cells/icons/power.dmi diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index c9b41d58cf06..5f355ec36374 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -9,6 +9,7 @@ var/obj/item/stock_parts/cell/charging = null var/charge_rate = 250 +/* OVERWRITTEN IN modular_skyrat\modules\aesthetics\cells\cell.dm /obj/machinery/cell_charger/update_overlays() . = ..() @@ -24,6 +25,7 @@ . += "ccharger-[charging.connector_type]-on" if((charging.charge > 0.01) && charging.charge_light_type) . += mutable_appearance('icons/obj/power.dmi', "cell-[charging.charge_light_type]-o[(charging.percent() >= 99.5) ? 2 : 1]") +*/ /obj/machinery/cell_charger/examine(mob/user) . = ..() diff --git a/modular_skyrat/modules/aesthetics/cells/cell.dm b/modular_skyrat/modules/aesthetics/cells/cell.dm index bdc9214d8109..753412d15d73 100644 --- a/modular_skyrat/modules/aesthetics/cells/cell.dm +++ b/modular_skyrat/modules/aesthetics/cells/cell.dm @@ -1,7 +1,63 @@ /obj/item/stock_parts/cell icon = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' /// The charge overlay icon file for the cell charge lights - var/charge_overlay_icon = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' + var/charging_icon = "cell_in" + connector_type = null + +/obj/item/stock_parts/cell/high + charging_icon = "hcell_in" + +/obj/item/stock_parts/cell/super + charging_icon = "scell_in" + +/obj/item/stock_parts/cell/hyper + charging_icon = "hpcell_in" + +/obj/item/stock_parts/cell/bluespace + charging_icon = "bscell_in" + +/obj/item/stock_parts/cell/infinite + charging_icon = "icell_in" + +/obj/item/stock_parts/cell/potato + charging_icon = "potato_in" + charge_light_type = "old" + +/obj/item/stock_parts/cell/emproof/slime + charging_icon = "slime_in" + +/obj/item/stock_parts/cell/high/slime_hypercharged + charging_icon = "slime_in" + +/obj/item/stock_parts/cell/lead + charging_icon = "lead_in" + +/obj/item/stock_parts/cell/update_overlays() + . = ..() + if(grown_battery) + . += mutable_appearance('icons/obj/power.dmi', "grown_wires") + if((charge < 0.01) || !charge_light_type) + return + var/icon_link + if(!grown_battery) + icon_link = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' + else + icon_link = 'icons/obj/power.dmi' + . += mutable_appearance(icon_link, "cell-[charge_light_type]-o[(percent() >= 99.5) ? 2 : 1]") /obj/machinery/cell_charger icon = 'modular_skyrat/modules/aesthetics/cells/cell.dmi' + +/obj/machinery/cell_charger/update_overlays() + . = ..() + + if(!charging) + return + + if(!(machine_stat & (BROKEN|NOPOWER))) + var/newlevel = round(charging.percent() * 4 / 100) + . += "ccharger-o[newlevel]" + if(!charging.charging_icon) + . += image(charging.icon, charging.icon_state) + else + .+= image('modular_skyrat/modules/aesthetics/cells/cell.dmi', charging.charging_icon)\ diff --git a/modular_skyrat/modules/aesthetics/cells/cell.dmi b/modular_skyrat/modules/aesthetics/cells/cell.dmi new file mode 100644 index 0000000000000000000000000000000000000000..706f5b4b3b506ebd152dcd7ae39393fccd55dc29 GIT binary patch literal 6163 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 Date: Wed, 13 Apr 2022 17:00:13 -0400 Subject: [PATCH 12/49] [MODULAR] Removes the undercharger MCR attachment. (#12688) * rere * Update microfusion_designs.dm * Update microfusion_techweb.dm * Update microfusion_gun_attachments.dm Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com> --- .../code/microfusion_gun_attachments.dm | 642 ++++++++++++++++++ .../microfusion/code/microfusion_designs.dm | 8 - .../microfusion/code/microfusion_techweb.dm | 1 - 3 files changed, 642 insertions(+), 9 deletions(-) create mode 100644 modular_skyrat/modules/microfusion/code/microfusion_gun_attachments.dm diff --git a/modular_skyrat/modules/microfusion/code/microfusion_gun_attachments.dm b/modular_skyrat/modules/microfusion/code/microfusion_gun_attachments.dm new file mode 100644 index 000000000000..7f4f6b0d2f9c --- /dev/null +++ b/modular_skyrat/modules/microfusion/code/microfusion_gun_attachments.dm @@ -0,0 +1,642 @@ +/** +*MICROFUSION GUN UPGRADE ATTACHMENTS +*For adding unique abilities to microfusion guns, these can directly interact with the gun! +*/ + +/obj/item/microfusion_gun_attachment + name = "microfusion gun attachment" + desc = "If you see this yell at a coder" + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_gun_attachments.dmi' + w_class = WEIGHT_CLASS_NORMAL + /// The attachment overlay icon state. + var/attachment_overlay_icon_state + /// Any incompatable upgrade types. + var/list/incompatable_attachments = list() + /// The added heat produced by having this module installed. + var/heat_addition = 0 + /// The slot this attachment is installed in. + var/slot = GUN_SLOT_UNIQUE + /// How much extra power do we use? + var/power_usage = 0 + +/obj/item/microfusion_gun_attachment/examine(mob/user) + . = ..() + . += "Compatible slot: [slot]." + +/obj/item/microfusion_gun_attachment/proc/run_attachment(obj/item/gun/microfusion/microfusion_gun) + SHOULD_CALL_PARENT(TRUE) + microfusion_gun.heat_per_shot += heat_addition + microfusion_gun.update_appearance() + microfusion_gun.extra_power_usage += power_usage + microfusion_gun.chambered?.refresh_shot() + return + +/obj/item/microfusion_gun_attachment/proc/process_attachment(obj/item/gun/microfusion/microfusion_gun) + return + +//Firing the gun right before we let go of it, tis is called. +/obj/item/microfusion_gun_attachment/proc/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + return + +/obj/item/microfusion_gun_attachment/proc/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + SHOULD_CALL_PARENT(TRUE) + microfusion_gun.heat_per_shot -= heat_addition + microfusion_gun.update_appearance() + microfusion_gun.extra_power_usage -= power_usage + microfusion_gun.chambered?.refresh_shot() + return + +/* +Returns a list of modifications of this attachment, it must return a list within a list list(list()). +All of the following must be returned. +list(list("title" = "Toggle [toggle ? "OFF" : "ON"]", "icon" = "power-off", "color" = "blue" "reference" = "toggle_on_off")) +title - The title of the modification button +icon - The icon of the modification button +color - The color of the modification button +reference - The reference of the modification button, this is used to call the proc when the run modify data proc is called. +*/ +/obj/item/microfusion_gun_attachment/proc/get_modify_data() + return + +/obj/item/microfusion_gun_attachment/proc/run_modify_data(params, mob/living/user, obj/item/gun/microfusion/microfusion_gun) + return + +/obj/item/microfusion_gun_attachment/proc/get_information_data() + return + +/* +SCATTER ATTACHMENT + +Turns the gun into a shotgun. +*/ +/obj/item/microfusion_gun_attachment/scatter + name = "diffuser microfusion lens upgrade" + desc = "A diffusing lens system capable of splitting one beam into three. However, the additional ionizing of the air will cause higher recoil." + icon_state = "attachment_scatter" + attachment_overlay_icon_state = "attachment_scatter" + slot = GUN_SLOT_BARREL + /// How many pellets are we going to add to the existing amount on the gun? + var/pellets_to_add = 2 + /// The variation in pellet scatter. + var/variance_to_add = 20 + /// How much recoil are we adding? + var/recoil_to_add = 1 + /// The spread to add. + var/spread_to_add = 10 + var/projectile_override = /obj/projectile/beam/laser/microfusion/scatter + +/obj/item/microfusion_gun_attachment/scatter/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.spread += spread_to_add + microfusion_gun.microfusion_lens.pellets += pellets_to_add + microfusion_gun.microfusion_lens.variance += variance_to_add + +/obj/item/microfusion_gun_attachment/scatter/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + chambered.loaded_projectile?.damage = chambered.loaded_projectile.damage / chambered.pellets + +/obj/item/microfusion_gun_attachment/scatter/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.spread -= spread_to_add + microfusion_gun.microfusion_lens.pellets -= pellets_to_add + microfusion_gun.microfusion_lens.variance -= variance_to_add + +/* +CRYSTALLINE SCATTER ATTACHMENT + +An overclocked shotgun. +*/ +/obj/item/microfusion_gun_attachment/scattermax + name = "crystalline diffuser microfusion lens upgrade" + desc = "An experimental diffusing lens system capable of splitting one beam into 7. However, it requires higher power usage as well as results in higher recoil." + icon_state = "attachment_scattermax" + attachment_overlay_icon_state = "attachment_scattermax" + slot = GUN_SLOT_BARREL + /// How many pellets are we going to add to the existing amount on the gun? + var/pellets_to_add = 6 + /// The variation in pellet scatter. + var/variance_to_add = 25 + /// How much recoil are we adding? + var/recoil_to_add = 1 + /// The spread to add. + var/spread_to_add = 15 + var/projectile_override =/obj/projectile/beam/laser/microfusion/scattermax + power_usage = 20 + +/obj/item/microfusion_gun_attachment/scattermax/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.spread += spread_to_add + microfusion_gun.microfusion_lens.pellets += pellets_to_add + microfusion_gun.microfusion_lens.variance += variance_to_add + +/obj/item/microfusion_gun_attachment/scattermax/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + chambered.loaded_projectile?.damage = chambered.loaded_projectile.damage / chambered.pellets + +/obj/item/microfusion_gun_attachment/scattermax/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.spread -= spread_to_add + microfusion_gun.microfusion_lens.pellets -= pellets_to_add + microfusion_gun.microfusion_lens.variance -= variance_to_add + +/* +SUPERHEAT ATTACHMENT + +Lasers set the target on fire. +*/ +/obj/item/microfusion_gun_attachment/superheat + name = "superheating phase emitter upgrade" + desc = "A barrel attachment hooked to the phase emitter, this adjusts the beam's wavelength to carry an intense wave of heat; causing targets to ignite." + icon_state = "attachment_superheat" + attachment_overlay_icon_state = "attachment_superheat" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/hellfire) + heat_addition = 90 + slot = GUN_SLOT_BARREL + var/projectile_override =/obj/projectile/beam/laser/microfusion/scatter + +/obj/item/microfusion_gun_attachment/superheat/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/vaporize.ogg' + +/obj/item/microfusion_gun_attachment/superheat/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + + +/obj/item/microfusion_gun_attachment/superheat/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + +/* +HELLFIRE ATTACHMENT + +Makes the gun shoot hellfire lasers. +*/ +/obj/item/microfusion_gun_attachment/hellfire + name = "hellfire emitter upgrade" + desc = "A barrel attachment hooked to the phase emitter, this adjusts the beam's wavelength to carry an extra wave of heat; causing nastier wounds and more damage." + icon_state = "attachment_hellfire" + attachment_overlay_icon_state = "attachment_hellfire" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/superheat) + heat_addition = 50 + power_usage = 20 + slot = GUN_SLOT_BARREL + var/projectile_override =/obj/projectile/beam/laser/microfusion/hellfire + +/obj/item/microfusion_gun_attachment/hellfire/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/melt.ogg' + +/obj/item/microfusion_gun_attachment/hellfire/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + + +/obj/item/microfusion_gun_attachment/hellfire/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + +/* +REPEATER ATTACHMENT + +The gun can fire volleys of shots. +*/ +/obj/item/microfusion_gun_attachment/repeater + name = "repeating phase emitter upgrade" + desc = "This barrel attachment upgrades the central phase emitter to fire off two beams in quick succession. While offering an increased rate of fire, the heat output and recoil rises too." + icon_state = "attachment_repeater" + attachment_overlay_icon_state = "attachment_repeater" + heat_addition = 40 + slot = GUN_SLOT_BARREL + /// The spread to add to the gun. + var/spread_to_add = 15 + /// The recoil to add to the gun. + var/recoil_to_add = 1 + /// The burst to add to the gun. + var/burst_to_add = 1 + /// The delay to add to the firing. + var/delay_to_add = 5 + var/projectile_override =/obj/projectile/beam/laser/microfusion/repeater + +/obj/item/microfusion_gun_attachment/repeater/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.burst_size += burst_to_add + microfusion_gun.fire_delay += delay_to_add + microfusion_gun.spread += spread_to_add + +/obj/item/microfusion_gun_attachment/repeater/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.burst_size -= burst_to_add + microfusion_gun.fire_delay -= delay_to_add + microfusion_gun.spread -= spread_to_add + +/obj/item/microfusion_gun_attachment/repeater/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override +/* +FOCUSED REPEATER ATTACHMENT + +The gun can fire volleys of shots that penetrate armor. +*/ +/obj/item/microfusion_gun_attachment/penetrator + name = "focused repeating phase emitter upgrade" + desc = "A focused variant of the repeating phase controller. It allows the lasers to penetrate armor however this results in higher power usage." + icon_state = "attachment_penetrator" + attachment_overlay_icon_state = "attachment_penetrator" + heat_addition = 40 + power_usage = 20 + slot = GUN_SLOT_BARREL + /// The spread to add to the gun. + var/spread_to_add = 15 + /// The recoil to add to the gun. + var/recoil_to_add = 1 + /// The burst to add to the gun. + var/burst_to_add = 1 + /// The delay to add to the firing. + var/delay_to_add = 5 + var/projectile_override =/obj/projectile/beam/laser/microfusion/penetrator + power_usage = 80 // A price to pay to penetrate through armor + +/obj/item/microfusion_gun_attachment/penetrator/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_add + microfusion_gun.burst_size += burst_to_add + microfusion_gun.fire_delay += delay_to_add + microfusion_gun.spread += spread_to_add + +/obj/item/microfusion_gun_attachment/penetrator/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_add + microfusion_gun.burst_size -= burst_to_add + microfusion_gun.fire_delay -= delay_to_add + microfusion_gun.spread -= spread_to_add + +/obj/item/microfusion_gun_attachment/penetrator/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new projectile_override + + +/* +X-RAY ATTACHMENT + +The gun can fire X-RAY shots. +*/ +/obj/item/microfusion_gun_attachment/xray + name = "quantum phase inverter array" //Yes quantum makes things sound cooler. + desc = "An experimental barrel attachment that modifies the central phase emitter, causing the wave frequency to shift into X-ray. Capable of penetrating both glass and solid matter with ease, though the bolts don't carry a greater effect against armor, due to going through the target and doing more minimal internal damage. These attachments are power-hungry and overheat easily, though engineers have deemed the costs necessary drawbacks." + icon_state = "attachment_xray" + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_xray" + heat_addition = 90 + power_usage = 50 + +/obj/item/microfusion_gun_attachment/xray/examine(mob/user) + . = ..() + . += span_warning("CAUTION: Phase emitter heats up extremely quickly, sustained fire not recommended!") + +/obj/item/microfusion_gun_attachment/xray/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'modular_skyrat/modules/microfusion/sound/incinerate.ogg' + +/obj/item/microfusion_gun_attachment/xray/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + +/obj/item/microfusion_gun_attachment/xray/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile.icon_state = "laser_greyscale" + chambered.loaded_projectile.color = COLOR_GREEN + chambered.loaded_projectile.light_color = COLOR_GREEN + chambered.loaded_projectile.projectile_piercing = PASSCLOSEDTURF|PASSGRILLE|PASSGLASS + +/* +GRIP ATTACHMENT + +Greatly reduces recoil and spread. +*/ +/obj/item/microfusion_gun_attachment/grip + name = "grip attachment" + desc = "A simple grip that increases accuracy." + icon_state = "attachment_grip" + attachment_overlay_icon_state = "attachment_grip" + slot = GUN_SLOT_UNDERBARREL + /// How much recoil are we removing? + var/recoil_to_remove = 1 + /// How much spread are we removing? + var/spread_to_remove = 10 + +/obj/item/microfusion_gun_attachment/grip/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil -= recoil_to_remove + microfusion_gun.spread -= spread_to_remove + +/obj/item/microfusion_gun_attachment/grip/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.recoil += recoil_to_remove + microfusion_gun.spread += spread_to_remove + +/* +HEATSINK ATTACHMENT + +"Greatly increases the phase emitter cooling rate." +*/ +/obj/item/microfusion_gun_attachment/heatsink + name = "phase emitter heatsink" + desc = "Greatly increases the phase emitter cooling rate." + icon_state = "attachment_heatsink" + attachment_overlay_icon_state = "attachment_heatsink" + slot = GUN_SLOT_UNDERBARREL + /// Coolant bonus + var/cooling_rate_increase = 50 + +/obj/item/microfusion_gun_attachment/heatsink/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.heat_dissipation_bonus += cooling_rate_increase + +/obj/item/microfusion_gun_attachment/heatsink/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.heat_dissipation_bonus -= cooling_rate_increase + + +/* +RGB ATTACHMENT + +Enables you to change the light color of the laser. +*/ +/obj/item/microfusion_gun_attachment/rgb + name = "phase emitter spectrograph" + desc = "An attachment hooked up to the phase emitter, allowing the user to adjust the color of the beam outputted. This has seen widespread use by various factions capable of getting their hands on microfusion weapons, whether as a calling card or simply for entertainment." + icon_state = "attachment_rgb" + attachment_overlay_icon_state = "attachment_rgb" + /// What color are we changing the sprite to? + var/color_to_apply = COLOR_MOSTLY_PURE_RED + +/obj/item/microfusion_gun_attachment/rgb/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered?.loaded_projectile.icon_state = "laser_greyscale" + chambered?.loaded_projectile.color = color_to_apply + chambered?.loaded_projectile.light_color = color_to_apply + +/obj/item/microfusion_gun_attachment/rgb/proc/select_color(mob/living/user) + var/new_color = input(user, "Please select your new projectile color", "Laser color", color_to_apply) as null|color + + if(!new_color) + return + + color_to_apply = new_color + +/obj/item/microfusion_gun_attachment/rgb/attack_self(mob/user, modifiers) + . = ..() + select_color(user) + +/obj/item/microfusion_gun_attachment/rgb/get_modify_data() + return list(list("title" = "Change Color", "icon" = "wrench", "reference" = "color", "color" = "blue")) + +/obj/item/microfusion_gun_attachment/rgb/run_modify_data(params, mob/living/user) + if(params == "color") + select_color(user) + +/* +RAIL ATTACHMENT + +Allows for flashlights bayonets and adds 1 slot to equipment. +*/ +/obj/item/microfusion_gun_attachment/rail + name = "gun rail attachment" + desc = "A simple set of rails that attaches to weapon hardpoints. Allows for 3 more attachment slots and the instillation of a flashlight or bayonet." + icon_state = "attachment_rail" + attachment_overlay_icon_state = "attachment_rail" + slot = GUN_SLOT_RAIL + +/obj/item/microfusion_gun_attachment/rail/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.can_flashlight = TRUE + microfusion_gun.can_bayonet = TRUE + +/obj/item/microfusion_gun_attachment/rail/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.gun_light = initial(microfusion_gun.can_flashlight) + if(microfusion_gun.gun_light) + microfusion_gun.gun_light.forceMove(get_turf(microfusion_gun)) + microfusion_gun.clear_gunlight() + microfusion_gun.can_bayonet = initial(microfusion_gun.can_bayonet) + if(microfusion_gun.bayonet) + microfusion_gun.bayonet.forceMove(get_turf(microfusion_gun)) + microfusion_gun.clear_bayonet() + microfusion_gun.remove_all_attachments() + +/* +SCOPE ATTACHMENT + +Allows for a scope to be attached to the gun. +DANGER: SNOWFLAKE ZONE +*/ +/obj/item/microfusion_gun_attachment/scope + name = "scope attachment" + desc = "A simple telescopic scope, allowing for long-ranged use of the weapon. However, these do not provide any night vision." + icon_state = "attachment_scope" + attachment_overlay_icon_state = "attachment_scope" + slot = GUN_SLOT_RAIL + +/obj/item/microfusion_gun_attachment/scope/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + if(microfusion_gun.azoom) + return + + microfusion_gun.azoom = new() + microfusion_gun.azoom.gun = microfusion_gun + microfusion_gun.update_action_buttons() + +/obj/item/microfusion_gun_attachment/scope/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + if(microfusion_gun.azoom) + microfusion_gun.azoom.Remove(microfusion_gun.azoom.owner) + QDEL_NULL(microfusion_gun.azoom) + microfusion_gun.update_action_buttons() + +/* +BLACK CAMO ATTACHMENT + +Allows for a black camo to be applied to the gun. +All tactical, all the time. +*/ +/obj/item/microfusion_gun_attachment/black_camo + name = "black camo microfusion frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to black." + icon_state = "attachment_black" + attachment_overlay_icon_state = "attachment_black" + +/* +HONK CAMO ATTACHMENT + +Allows for a clown camo to be applied to the gun. +HONK!! +*/ +/obj/item/microfusion_gun_attachment/honk_camo + name = "bananium microfusion frame" + desc = "A frame modification for the MCR-01, plating the gun in bananium." + icon_state = "attachment_honk_camo" + attachment_overlay_icon_state = "attachment_honk_camo" + +/* +SYNDIE CAMO ATTACHMENT + +Allows for a blood red camo to be applied to the gun. +Totally not property of a hostile corporation. +*/ +/obj/item/microfusion_gun_attachment/syndi_camo + name = "blood red camo microfusion frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to a slick blood red." + icon_state = "attachment_syndi_camo" + attachment_overlay_icon_state = "attachment_syndi_camo" + +/* +NANOTRASEN CAMO ATTACHMENT + +Allows for an official blue camo to be applied to the gun. +Hail NanoTrasen. +*/ +/obj/item/microfusion_gun_attachment/nt_camo + name = "\improper NanoTrasen brand microfusion frame" + desc = "A frame modification for the MCR-01, changing the color of the gun to blue." + icon_state = "attachment_nt_camo" + attachment_overlay_icon_state = "attachment_nt_camo" + +/* +PULSE ATTACHMENT + +The gun can fire PULSE shots. +*/ +/obj/item/microfusion_gun_attachment/pulse + name = "pulse induction carriage" + desc = "A cutting-edge bluespace capacitor array and distributing lens overhaul produced in laboratories by Nanotrasen scientists that allow microfusion rifles to fire military-grade pulse rounds. Comes equipped with cyclic cooling to ensure maximum combat efficiency, a munitions counter, and an extra-secure drop cage for the power source. May shorten trigger lifetime." + icon_state = "attachment_pulse" + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_pulse" + heat_addition = 150 + power_usage = 50 + var/added_burst_size = 2 + var/added_fire_delay = 2 + +/obj/item/microfusion_gun_attachment/pulse/examine(mob/user) + . = ..() + . += span_warning("CAUTION: Phase emitter heats up extremely quickly, sustained fire not recommended!") + +/obj/item/microfusion_gun_attachment/pulse/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.burst_size += added_burst_size + microfusion_gun.fire_delay += added_fire_delay + +/obj/item/microfusion_gun_attachment/pulse/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.burst_size -= added_burst_size + microfusion_gun.fire_delay -= added_fire_delay + +/obj/item/microfusion_gun_attachment/pulse/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new /obj/projectile/beam/pulse + +/* +SUPPRESSOR ATTACHMENT + +Makes operators operate operatingly. +*/ + +/obj/item/microfusion_gun_attachment/suppressor + name = "laser suppressor" // sure it makes no sense but its cool + desc = "An experimental barrel attachment that dampens the soundwave of the emitter, making the laser shots far more stealthy. Best paired with black camo." + icon_state = "attachment_suppressor" + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_suppressor" + +/obj/item/microfusion_gun_attachment/suppressor/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.suppressed = TRUE + +/obj/item/microfusion_gun_attachment/suppressor/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.suppressed = null + +/* +BIKEHORN ATTACHMENT + +HONK!! Does subpar stamina damage but slips people. +*/ + +/obj/item/microfusion_gun_attachment/honk + name = "bananium phase emitter upgrade" + desc = "An honksperimental barrel attachment that makes your lasers funnier." + icon_state = "attachment_honk" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/scatter, /obj/item/microfusion_gun_attachment/scattermax) + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_honk" + var/added_fire_delay = 20 + +/obj/item/microfusion_gun_attachment/honk/examine(mob/user) + . = ..() + . += span_warning("CAUTION: The gun you are about to handle is extremely funny!") + +/obj/item/microfusion_gun_attachment/honk/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = 'sound/items/bikehorn.ogg' + microfusion_gun.fire_delay += added_fire_delay + +/obj/item/microfusion_gun_attachment/honk/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + microfusion_gun.fire_delay += added_fire_delay + +/obj/item/microfusion_gun_attachment/honk/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile.icon_state = "laser_greyscale" + chambered.loaded_projectile.color = COLOR_VIVID_YELLOW + chambered.loaded_projectile.light_color = COLOR_VIVID_YELLOW + chambered.loaded_projectile.damage_type = STAMINA + chambered.loaded_projectile.damage = 20 + chambered.loaded_projectile.armor_flag = ENERGY + chambered.loaded_projectile.AddComponent(/datum/component/slippery, 20) + chambered.loaded_projectile.hitsound = 'sound/misc/slip.ogg' + chambered.loaded_projectile.impact_type = /obj/effect/projectile/impact/disabler + +/* +LANCE ATTACHMENT + +The gun fires fast heavy lasers but takes a long time to fire. +*/ +/obj/item/microfusion_gun_attachment/lance + name = "lance induction carriage" + desc = "A modification kit that turns the MCR into a designated marksman rifle. Fired beams boast greater firepower and speed however it is very draining on battery as well as generates an extreme amount of heat." + icon = 'icons/obj/improvised.dmi' + icon_state = "kitsuitcase" + incompatable_attachments = list(/obj/item/microfusion_gun_attachment/black_camo, /obj/item/microfusion_gun_attachment/nt_camo, /obj/item/microfusion_gun_attachment/honk_camo) + slot = GUN_SLOT_BARREL + attachment_overlay_icon_state = "attachment_lance" + heat_addition = 150 + power_usage = 100 + var/added_fire_delay = 25 + +/obj/item/microfusion_gun_attachment/lance/examine(mob/user) + . = ..() + . += span_warning("CAUTION: Phase emitter heats up extremely quickly!") + +/obj/item/microfusion_gun_attachment/lance/run_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_delay += added_fire_delay + microfusion_gun.fire_sound = 'sound/weapons/lasercannonfire.ogg' + +/obj/item/microfusion_gun_attachment/lance/remove_attachment(obj/item/gun/microfusion/microfusion_gun) + . = ..() + microfusion_gun.fire_delay -= added_fire_delay + microfusion_gun.fire_sound = microfusion_gun.chambered?.fire_sound + +/obj/item/microfusion_gun_attachment/lance/process_fire(obj/item/gun/microfusion/microfusion_gun, obj/item/ammo_casing/chambered) + . = ..() + chambered.loaded_projectile = new /obj/projectile/beam/laser/microfusion/lance diff --git a/monkestation/code/modules/microfusion/code/microfusion_designs.dm b/monkestation/code/modules/microfusion/code/microfusion_designs.dm index 0cc3a41514af..273e6db0482a 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_designs.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_designs.dm @@ -123,14 +123,6 @@ build_path = /obj/item/microfusion_gun_attachment/rail // BARREL MODS -/datum/design/microfusion/phase_emitter_undercharger - name = "Microfusion Phase Emitter Undercharger" - desc = "Inverts the output beam of the phase emitter, popular amongst law enforcement as a non-lethal upgrade." - id = "microfusion_phase_emitter_undercharger" - materials = list(/datum/material/iron = 1000, /datum/material/glass = 200) - build_path = /obj/item/microfusion_gun_attachment/undercharger - category = list("Weapons", "initial") - /datum/design/microfusion/gun_attachment_grip name = "Microfusion Weapon Grip" desc = "A grip... for microfusion weapon platforms." diff --git a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm index f7c304814770..c60ac0588ca2 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_techweb.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_techweb.dm @@ -5,7 +5,6 @@ description = "Basic microfusion technology allowing for basic microfusion designs." design_ids = list( "basic_microfusion_cell", - "microfusion_phase_emitter_undercharger", ) //Enhanced microfusion From 34e3c5ac3938f78fd8d520fa6f4ccf0d1e8062c7 Mon Sep 17 00:00:00 2001 From: ErdinyoBarboza Date: Wed, 20 Apr 2022 18:58:02 +0300 Subject: [PATCH 13/49] Update cargo_stuff.dm (#12931) --- monkestation/code/modules/microfusion/code/cargo_stuff.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/cargo_stuff.dm b/monkestation/code/modules/microfusion/code/cargo_stuff.dm index c7b9658e7ec8..f4d49054a98b 100644 --- a/monkestation/code/modules/microfusion/code/cargo_stuff.dm +++ b/monkestation/code/modules/microfusion/code/cargo_stuff.dm @@ -34,7 +34,7 @@ ) crate_name = "Microfusion Cell Crate" -/datum/supply_pack/security/mcr01_attachments +/datum/supply_pack/security/mcr01_attachments_A name = "MCR-01 Military Attachments Crate Type A" desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments! This crate comes with two utilitarian repeater loadout." cost = CARGO_CRATE_VALUE * 14 @@ -52,7 +52,7 @@ ) crate_name = "MCR-01 Military Attachments Crate Type A" -/datum/supply_pack/security/mcr01_attachments +/datum/supply_pack/security/mcr01_attachments_type_B name = "MCR-01 Military Attachments Crate Type B" desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments! This crate comes in a mixed specialist loadout." cost = CARGO_CRATE_VALUE * 16 @@ -69,7 +69,7 @@ crate_name = "MCR-01 Military Attachments Crate Type B" -/datum/supply_pack/security/mcr01_attachments +/datum/supply_pack/security/mcr01_attachments_H name = "HCR-01 Military Attachments Crate Type H" desc = "Honkicron Clownery Systems Inhonkorated supplied HCR-01 Clownery spec attachments! This crate oddly smells of bananas." cost = CARGO_CRATE_VALUE * 20 From 1ea94423338ec0669f5a58d81c7780ac5db9dc4e Mon Sep 17 00:00:00 2001 From: Tom <8881105+tf-4@users.noreply.github.com> Date: Thu, 21 Apr 2022 15:07:49 +0100 Subject: [PATCH 14/49] MCR renaming adjustment (#12961) --- .../code/microfusion_energy_master.dm | 17 ++--------------- .../tgui/interfaces/MicrofusionGunControl.js | 8 +------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm index ec5df16c6134..7276f56910bd 100644 --- a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm +++ b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm @@ -16,6 +16,8 @@ can_flashlight = FALSE can_bayonet = FALSE w_class = WEIGHT_CLASS_BULKY + obj_flags = UNIQUE_RENAME + ammo_x_offset = 2 /// What type of power cell this uses var/obj/item/stock_parts/cell/microfusion/cell @@ -29,7 +31,6 @@ var/can_charge = TRUE /// How many charge sections do we have? var/charge_sections = 4 - ammo_x_offset = 2 /// if this gun uses a stateful charge bar for more detail var/shaded_charge = FALSE /// If this gun has a "this is loaded with X" overlay alongside chargebars and such @@ -702,18 +703,6 @@ user?.put_in_hands(microfusion_gun_attachment) update_appearance() -/obj/item/gun/microfusion/proc/change_name(mob/user) - var/new_name = input(user, "Enter new name:", "Change gun name") as null|text - if(!new_name) - return - var/name_length = length(new_name) - if(name_length > GUN_MAX_NAME_CHARS && name_length < GUN_MIN_NAME_CHARS) - to_chat(user, span_warning("New name cannot be longer than 20 or shorter than 5 characters!")) - return - - name = sanitize(new_name) - update_appearance() - // UI CONTROL /obj/item/gun/microfusion/ui_interact(mob/user, datum/tgui/ui) @@ -798,8 +787,6 @@ if(!cell) return eject_cell(usr) - if("change_gun_name") - change_name(usr) if("overclock_emitter") if(!phase_emitter) return diff --git a/tgui/packages/tgui/interfaces/MicrofusionGunControl.js b/tgui/packages/tgui/interfaces/MicrofusionGunControl.js index 106ab778a326..0786995848b9 100644 --- a/tgui/packages/tgui/interfaces/MicrofusionGunControl.js +++ b/tgui/packages/tgui/interfaces/MicrofusionGunControl.js @@ -25,13 +25,7 @@ export const MicrofusionGunControl = (props, context) => { - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/KeycardAuth.js b/tgui/packages/tgui/interfaces/KeycardAuth.js index 3c2c0c1c3028..f38e8b3b6800 100644 --- a/tgui/packages/tgui/interfaces/KeycardAuth.js +++ b/tgui/packages/tgui/interfaces/KeycardAuth.js @@ -5,8 +5,7 @@ import { Window } from '../layouts'; export const KeycardAuth = (props, context) => { const { act, data } = useBackend(context); return ( - // SKYRAT EDIT: height 125 -> 150, addition of permit-locked firing pin - +
@@ -56,12 +55,6 @@ export const KeycardAuth = (props, context) => { onClick={() => act('give_janitor_access')} content="Grant Janitor Access" /> -
-
+
{has_attachments ? ( attachments.map((attachment, index) => (
act('remove_attachment', { - attachment_ref: attachment.ref, - })} /> - )}> + onClick={() => + act('remove_attachment', { + attachment_ref: attachment.ref, + }) + } + /> + }> {attachment.desc} @@ -229,30 +250,31 @@ export const MicrofusionGunControl = (props, context) => { {attachment.information} )} - {!!attachment.has_modifications && ( + {!!attachment.has_modifications && attachment.modify.map((mod, index) => ( act('modify_attachment', { - attachment_ref: attachment.ref, - modify_ref: mod.reference, - })} /> - )} /> - )) - )} + onClick={() => + act('modify_attachment', { + attachment_ref: attachment.ref, + modify_ref: mod.reference, + }) + } + /> + } + /> + ))}
)) ) : ( - - No attachments installed! - + No attachments installed! )}
From 9562c223cc996a78e2b67cf1b05ed2b7668ab587 Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Wed, 17 Jan 2024 19:44:10 -0800 Subject: [PATCH 43/49] no goon styles --- .../tgui-panel/styles/goon/chat-dark.scss | 1043 ----------------- .../tgui-panel/styles/goon/chat-light.scss | 994 ---------------- 2 files changed, 2037 deletions(-) delete mode 100644 tgui/packages/tgui-panel/styles/goon/chat-dark.scss delete mode 100644 tgui/packages/tgui-panel/styles/goon/chat-light.scss diff --git a/tgui/packages/tgui-panel/styles/goon/chat-dark.scss b/tgui/packages/tgui-panel/styles/goon/chat-dark.scss deleted file mode 100644 index 9fbd3db9877a..000000000000 --- a/tgui/packages/tgui-panel/styles/goon/chat-dark.scss +++ /dev/null @@ -1,1043 +0,0 @@ -/** - * Copyright (c) 2020 Aleksej Komarov - * SPDX-License-Identifier: MIT - */ - -em { - font-style: normal; - font-weight: bold; -} - -img { - margin: 0; - padding: 0; - line-height: 1; - -ms-interpolation-mode: nearest-neighbor; - image-rendering: pixelated; -} - -img.icon { - height: 1em; - min-height: 16px; - width: auto; - vertical-align: bottom; -} - -a { - color: #397ea5; -} - -a.visited { - color: #7c00e6; -} - -a:visited { - color: #7c00e6; -} - -a.popt { - text-decoration: none; -} - -/* POPUPS */ - -.popup { - position: fixed; - top: 50%; - left: 50%; - background: #ddd; -} - -.popup .close { - position: absolute; - background: #aaa; - top: 0; - right: 0; - color: #333; - text-decoration: none; - z-index: 2; - padding: 0 10px; - height: 30px; - line-height: 30px; -} - -.popup .close:hover { - background: #999; -} - -.popup .head { - background: #999; - color: #ddd; - padding: 0 10px; - height: 30px; - line-height: 30px; - text-transform: uppercase; - font-size: 0.9em; - font-weight: bold; - border-bottom: 2px solid green; -} - -.popup input { - border: 1px solid #999; - background: #fff; - margin: 0; - padding: 5px; - outline: none; - color: #333; -} - -.popup input[type=text]:hover, -.popup input[type=text]:active, -.popup input[type=text]:focus { - border-color: green; -} - -.popup input[type=submit] { - padding: 5px 10px; - background: #999; - color: #ddd; - text-transform: uppercase; - font-size: 0.9em; - font-weight: bold; -} - -.popup input[type=submit]:hover, -.popup input[type=submit]:focus, -.popup input[type=submit]:active { - background: #aaa; - cursor: pointer; -} - -.changeFont { - padding: 10px; -} - -.changeFont a { - display: block; - text-decoration: none; - padding: 3px; - color: #333; -} - -.changeFont a:hover { - background: #ccc; -} - -.highlightPopup { - padding: 10px; - text-align: center; -} - -.highlightPopup input[type=text] { - display: block; - width: 215px; - text-align: left; - margin-top: 5px; -} - -.highlightPopup input.highlightColor { - background-color: #FFFF00; -} - -.highlightPopup input.highlightTermSubmit { - margin-top: 5px; -} - - - -/* ADMIN CONTEXT MENU */ - - -.contextMenu { - background-color: #ddd; - position: fixed; - margin: 2px; - width: 150px; -} - -.contextMenu a { - display: block; - padding: 2px 5px; - text-decoration: none; - color: #333; -} - -.contextMenu a:hover { - background-color: #ccc; -} - - - -/* ADMIN FILTER MESSAGES MENU */ - - -.filterMessages { - padding: 5px; -} - -.filterMessages div { - padding: 2px 0; -} - -.filterMessages input { -} - -.filterMessages label { -} - -.icon-stack { - height: 1em; - line-height: 1em; - width: 1em; - vertical-align: middle; - margin-top: -2px; -} - - - - -/***************************************** -* -* OUTPUT ACTUALLY RELATED TO MESSAGES -* -******************************************/ - - - - - -/* MOTD */ - - -.motd { - color: #a4bad6; - font-family: Verdana, sans-serif; - white-space: normal; -} - -.motd h1, -.motd h2, -.motd h3, -.motd h4, -.motd h5, -.motd h6 { - color: #a4bad6; - text-decoration: underline; -} - -.motd a, -.motd a:link, -.motd a:visited, -.motd a:active, -.motd a:hover { - color: #a4bad6; -} - - - -/* ADD HERE FOR BOLD */ - - -.bold, -.name, -.prefix, -.ooc, -.looc, -.adminooc, -.admin, -.medal, -.yell { - font-weight: bold; -} - - - -/* ADD HERE FOR ITALIC */ - - -.italic, .italics { - font-style: italic; -} - - - -/* OUTPUT COLORS */ - - -.highlight { - background: yellow; -} - -h1, h2, h3, h4, h5, h6 { - color: #a4bad6; - font-family: Georgia, Verdana, sans-serif; -} - -h1.alert, h2.alert { - color: #a4bad6; -} - -em { - font-style: normal; - font-weight: bold; -} - -.ooc { - color: #cca300; - font-weight: bold; -} - -.adminobserverooc { - color: #0099cc; - font-weight: bold; -} - -.adminooc { - color: #3d5bc3; - font-weight: bold; -} - -.adminsay { - color: #ff4500; - font-weight: bold; -} - -.admin { - color: #5975da; - font-weight: bold; -} - -.name { - font-weight: bold; -} - -.say, .emote, .infoplain, .oocplain, .warningplain, .mentor { -} - -.deadsay { - color: #e2c1ff; -} - -.binarysay { - color: #1e90ff; -} - -.binarysay a { - color: #00ff00; -} - -.binarysay a:active, .binarysay a:visited { - color: #88ff88; -} - -/* RADIO COLORS */ -/* IF YOU CHANGE THIS KEEP IT IN SYNC WITH TGUI CONSTANTS */ - -.radio { - color: #1ecc43; -} - -.sciradio { - color: #c68cfa; -} - -.comradio { - color: #fcdf03; -} - -.secradio { - color: #dd3535; -} - -.medradio { - color: #57b8f0; -} - -.engradio { - color: #f37746; -} - -.suppradio { - color: #b88646; -} - -.servradio { - color: #6ca729; -} - -.syndradio { - color: #8f4a4b; -} - -.gangradio { - color: #ac2ea1; -} - -.centcomradio { - color: #2681a5; -} - -.aiprivradio { - color: #d65d95; -} - -.redteamradio { - color: #ff4444; -} - -.blueteamradio { - color: #3434fd; -} - -.greenteamradio { - color: #34fd34; -} - -.yellowteamradio { - color: #fdfd34; -} - -.yell { - font-weight: bold; -} - -.alert { - color: #d82020; -} - -.userdanger { - color: #c51e1e; - font-weight: bold; - font-size: 185%; -} - -.bolddanger { - color: #c51e1e; - font-weight: bold; -} - -.danger { - color: #c51e1e; -} - -.warning { - color: #c51e1e; - font-style: italic; -} - -.alertwarning { - color: #FF0000; - font-weight: bold; -} - -.boldwarning { - color: #c51e1e; - font-style: italic; - font-weight: bold; -} - -.announce { - color: #c51e1e; - font-weight: bold; -} - -.boldannounce { - color: #c51e1e; - font-weight: bold; -} - -.minorannounce { - font-weight: bold; - font-size: 185%; -} - -.greenannounce { - color: #059223; - font-weight: bold; -} - -.rose { - color: #ff5050; -} - -.info { - color: #9ab0ff; -} - -.notice { - color: #6685f5; -} - -.tinynotice { - color: #6685f5; - font-size: 85%; -} - -.tinynoticeital { - color: #6685f5; - font-style: italic; - font-size: 85%; -} - -.smallnotice { - color: #6685f5; - font-size: 90%; -} - -.smallnoticeital { - color: #6685f5; - font-style: italic; - font-size: 90%; -} - -.boldnotice { - color: #6685f5; - font-weight: bold; -} - -.hear { - color: #6685f5; - font-style: italic; -} - -.adminnotice { - color: #6685f5; -} - -.adminhelp { - color: #ff0000; - font-weight: bold; -} - -.unconscious { - color: #a4bad6; - font-weight: bold; -} - -.suicide { - color: #ff5050; - font-style: italic; -} - -.green { - color: #059223; -} - -.grey { - color: #838383; -} - -.red { - color: #FF0000; -} - -.blue { - color: #215cff; -} - -.nicegreen { - color: #059223; -} - -.boldnicegreen { - color: #059223; - font-weight: bold; -} - -.cult { - color: #973e3b; -} - -.cultitalic { - color: #973e3b; - font-style: italic; -} - -.cultbold { - color: #973e3b; - font-style: italic; - font-weight: bold; -} - -.cultboldtalic { - color: #973e3b; - font-weight: bold; - font-size: 185%; -} - -.cultlarge { - color: #973e3b; - font-weight: bold; - font-size: 185%; -} - -.narsie { - color: #973e3b; - font-weight: bold; - font-size: 925%; -} - -.narsiesmall { - color: #973e3b; - font-weight: bold; - font-size: 370%; -} - -.colossus { - color: #7F282A; - font-size: 310%; -} - -.hierophant { - color: #b441ee; - font-weight: bold; - font-style: italic; -} - -.hierophant_warning { - color: #c56bf1; - font-style: italic; -} - -.purple { - color: #9956d3; -} - -.holoparasite { - color: #88809c; -} - -.revennotice { - color: #c099e2; -} - -.revenboldnotice { - color: #c099e2; - font-weight: bold; -} - -.revenbignotice { - color: #c099e2; - font-weight: bold; - font-size: 185%; -} - -.revenminor { - color: #823abb; -} - -.revenwarning { - color: #760fbb; - font-style: italic; -} - -.revendanger { - color: #760fbb; - font-weight: bold; - font-size: 185%; -} - -.deconversion_message { - color: #a947ff; - font-size: 185%; - font-style: italic; -} - -.ghostalert { - color: #6600ff; - font-style: italic; - font-weight: bold; -} - -.alien { - color: #855d85; -} - -.noticealien { - color: #059223; -} - -.alertalien { - color: #059223; - font-weight: bold; -} - -.changeling { - color: #059223; - font-style: italic; -} - -.alertsyndie { - color: #FF0000; - font-size: 185%; - font-weight: bold; -} - -.spider { - color: #8800ff; - font-weight: bold; - font-size: 185%; -} - -.interface { - color: #750e75; -} - -.sans { - font-family: "Comic Sans MS", cursive, sans-serif; -} - -.papyrus { - font-family: "Papyrus", cursive, sans-serif; -} - -.robot { - font-family: "Courier New", cursive, sans-serif; -} - -.tape_recorder { - color: #FF0000; - font-family: "Courier New", cursive, sans-serif; -} - -.command_headset { - font-weight: bold; - font-size: 160%; -} - -.small { - font-size: 60%; -} - -.big { - font-size: 185%; -} - -.reallybig { - font-size: 245%; -} - -.extremelybig { - font-size: 310%; -} - -.greentext { - color: #059223; - font-size: 185%; -} - -.redtext { - color: #c51e1e; - font-size: 185%; -} - -.clown { - color: #ff70c1; - font-size: 160%; - font-family: "Comic Sans MS", cursive, sans-serif; - font-weight: bold; -} - -.singing { - font-family: "Trebuchet MS", cursive, sans-serif; - font-style: italic; -} - -.his_grace { - color: #15D512; - font-family: "Courier New", cursive, sans-serif; - font-style: italic; -} - -.hypnophrase { - color: #202020; - font-weight: bold; - animation: hypnocolor 1500ms infinite; - animation-direction: alternate; -} - -@keyframes hypnocolor { - 0% { - color: #202020; - } - - 25% { - color: #4b02ac; - } - - 50% { - color: #9f41f1; - } - - 75% { - color: #541c9c; - } - - 100% { - color: #7adbf3; - } -} - -// SKYRAT ADDITION BEGIN -.velvet { - color: #660015; - font-weight: bold; - animation: velvet 5000ms infinite; -} -@keyframes velvet { - 0% { - color: #400020; - } - 40% { - color: #ff0000; - } - 50% { - color: #ff8888; - } - 60% { - color: #ff0000; - } - 100% { - color: #400020; - } -} - -.hexnut { - color: #0099ff; - font-weight: bold; - animation: hexnut 5000ms infinite; - animation-direction: alternate; -} - -@keyframes hexnut { - 0% { - color: #0099ff; - } - 35% { - color: #a64dff; - } - 50% { - color: #00997a; - } - 60% { - color: #ffb31a; - } - 100% { - color: #ff33cc; - } -} - -.doyourjobidiot { - color: #c51e1e; - text-shadow: 0 0 4px #e22525; - font-size: 125%; - font-weight: bold; - animation: flashingfuckingwarning 250ms infinite; -} - -@keyframes flashingfuckingwarning { - 0% { - color: #c51e1e; - text-shadow: 0 0 4px #c51e1e; - } - - 50% { - color: #e22525; - text-shadow: 0 0 8px #e22525; - } - - 100% { - color: #c51e1e; - text-shadow: 0 0 4px #c51e1e; - } -} -// SKYRAT ADDITION END - -.phobia { - color: #dd0000; - font-weight: bold; - animation: phobia 750ms infinite; -} - -@keyframes phobia { - 0% { - color: #f75a5a; - } - - 50% { - color: #dd0000; - } - - 100% { - color: #f75a5a; - } -} - -.icon { - height: 1em; - width: auto; -} - -.bigicon { - font-size: 2.5em; -} - -.memo { - color: #638500; - text-align: center; -} - -.memoedit { - text-align: center; - font-size: 125%; -} - -.abductor { - color: #c204c2; - font-style: italic; -} - -.mind_control { - color: #df3da9; - font-size: 100%; - font-weight: bold; - font-style: italic; -} - -.slime { - color: #00CED1; -} - -.drone { - color: #848482; -} - -.monkey { - color: #975032; -} - -.swarmer { - color: #2C75FF; -} - -.resonate { - color: #298F85; -} - -.monkeyhive { - color: #a56408; -} - -.monkeylead { - color: #af6805; - font-size: 80%; -} - -.connectionClosed, .fatalError { - background: red; - color: white; - padding: 5px; -} - -.connectionClosed.restored { - background: green; -} - -.internal.boldnshit { - color: #3d5bc3; - font-weight: bold; -} - - - -/* HELPER CLASSES */ - - -.text-normal { - font-weight: normal; - font-style: normal; -} - -.hidden { - display: none; - visibility: hidden; -} - -.ml-1 { - margin-left: 1em; -} - -.ml-2 { - margin-left: 2em; -} - -.ml-3 { - margin-left: 3em; -} - -.tooltip { - font-style: italic; - border-bottom: 1px dashed #fff; -} - -/* SKYRAT DARK MODE CLASSES */ -.mentor {color: #8a2be2;} -.looc {color: #d8b555;} -.rlooc {color: #b09448;} - -.examine_block { - background: rgba(0, 0, 0, 0.2); - border: 1px solid rgba(55, 55, 55, 0.33); - margin: 7px 4px; - padding: 8px 12px; - max-width: 550px; -} - -.examine_block hr { - border: none; - background: #222; - height: 1px; - margin: 8px 16px 8px 16px; -} - -.userlove { - color: #FF1493; - font-style: italic; - font-weight: bold; - text-shadow: 0 0 6px #ff6dbc; -} - -.crossooc { - color: #9f6efc; - font-weight: bold; -} - -.crossasay { - color: #ff0000; - font-weight: bold; -} - -.pink { - color: #ff00ff; - font-weight: bold; -} - -.brown { - color: #3d2009; - font-weight: bold; -} - -.orange { - color: #b8761a; - font-weight: bold; -} - -.yellow { - color: #c7b72c; - font-weight: bold; -} - -.cyan { - color: #0ea1e6; - font-weight: bold; -} diff --git a/tgui/packages/tgui-panel/styles/goon/chat-light.scss b/tgui/packages/tgui-panel/styles/goon/chat-light.scss deleted file mode 100644 index 20ed07138ce8..000000000000 --- a/tgui/packages/tgui-panel/styles/goon/chat-light.scss +++ /dev/null @@ -1,994 +0,0 @@ -/** - * Copyright (c) 2020 Aleksej Komarov - * SPDX-License-Identifier: MIT - */ - -html, body { - padding: 0; - margin: 0; - height: 100%; - color: #000000; -} - -body { - background: #fff; - font-family: Verdana, sans-serif; - font-size: 13px; - line-height: 1.2; - overflow-x: hidden; - overflow-y: scroll; - word-wrap: break-word; -} - -em { - font-style: normal; - font-weight: bold; -} - -img { - margin: 0; - padding: 0; - line-height: 1; - -ms-interpolation-mode: nearest-neighbor; - image-rendering: pixelated; -} - -img.icon { - height: 1em; - min-height: 16px; - width: auto; - vertical-align: bottom; -} - -a { - color: #0000ff; -} - -a.visited { - color: #ff00ff; -} - -a:visited { - color: #ff00ff; -} - -a.popt { - text-decoration: none; -} - -/* POPUPS */ - -.popup { - position: fixed; - top: 50%; - left: 50%; - background: #ddd; -} - -.popup .close { - position: absolute; - background: #aaa; - top: 0; - right: 0; - color: #333; - text-decoration: none; - z-index: 2; - padding: 0 10px; - height: 30px; - line-height: 30px; -} - -.popup .close:hover { - background: #999; -} - -.popup .head { - background: #999; - color: #ddd; - padding: 0 10px; - height: 30px; - line-height: 30px; - text-transform: uppercase; - font-size: 0.9em; - font-weight: bold; - border-bottom: 2px solid green; -} - -.popup input { - border: 1px solid #999; - background: #fff; - margin: 0; - padding: 5px; - outline: none; - color: #333; -} - -.popup input[type=text]:hover, -.popup input[type=text]:active, -.popup input[type=text]:focus { - border-color: green; -} - -.popup input[type=submit] { - padding: 5px 10px; - background: #999; - color: #ddd; - text-transform: uppercase; - font-size: 0.9em; - font-weight: bold; -} - -.popup input[type=submit]:hover, -.popup input[type=submit]:focus, -.popup input[type=submit]:active { - background: #aaa; - cursor: pointer; -} - -.changeFont { - padding: 10px; -} - -.changeFont a { - display: block; - text-decoration: none; - padding: 3px; - color: #333; -} - -.changeFont a:hover { - background: #ccc; -} - -.highlightPopup { - padding: 10px; - text-align: center; -} - -.highlightPopup input[type=text] { - display: block; - width: 215px; - text-align: left; - margin-top: 5px; -} - -.highlightPopup input.highlightColor { - background-color: #FFFF00; -} - -.highlightPopup input.highlightTermSubmit { - margin-top: 5px; -} - - - -/* ADMIN CONTEXT MENU */ - - -.contextMenu { - background-color: #ddd; - position: fixed; - margin: 2px; - width: 150px; -} - -.contextMenu a { - display: block; - padding: 2px 5px; - text-decoration: none; - color: #333; -} - -.contextMenu a:hover { - background-color: #ccc; -} - - - -/* ADMIN FILTER MESSAGES MENU */ - - -.filterMessages { - padding: 5px; -} - -.filterMessages div { - padding: 2px 0; -} - -.filterMessages input { -} - -.filterMessages label { -} - -.icon-stack { - height: 1em; - line-height: 1em; - width: 1em; - vertical-align: middle; - margin-top: -2px; -} - - - - -/***************************************** -* -* OUTPUT ACTUALLY RELATED TO MESSAGES -* -******************************************/ - - - - - -/* MOTD */ - - -.motd { - color: #638500; - font-family: Verdana, sans-serif; - white-space: normal; -} - -.motd h1, -.motd h2, -.motd h3, -.motd h4, -.motd h5, -.motd h6 { - color: #638500; - text-decoration: underline; -} - -.motd a, -.motd a:link, -.motd a:visited, -.motd a:active, -.motd a:hover { - color: #638500; -} - - - -/* ADD HERE FOR BOLD */ - - -.bold, -.name, -.prefix, -.ooc, -.looc, -.adminooc, -.admin, -.medal, -.yell { - font-weight: bold; -} - - - -/* ADD HERE FOR ITALIC */ - - -.italic, -.italics { - font-style: italic; -} - - - -/* OUTPUT COLORS */ - - -.highlight { - background: yellow; -} - -h1, h2, h3, h4, h5, h6 { - color: #0000ff; - font-family: Georgia, Verdana, sans-serif; -} - -h1.alert, h2.alert { - color: #000000; -} - -em { - font-style: normal; - font-weight: bold; -} - -.ooc { - color: #002eb8; - font-weight: bold; -} - -.adminobserverooc { - color: #0099cc; - font-weight: bold; -} - -.adminooc { - color: #700038; - font-weight: bold; -} - -.adminsay { - color: #ff4500; - font-weight: bold; -} - -.admin { - color: #4473ff; - font-weight: bold; -} - -.name { - font-weight: bold; -} - -.say, .emote, .infoplain, .oocplain, .warningplain, .mentor { -} - -.deadsay { - color: #5c00e6; -} - -.binarysay { - color: #20c20e; - background-color: #000000; - display: block; -} - -.binarysay a { - color: #00ff00; -} - -.binarysay a:active, -.binarysay a:visited { - color: #88ff88; -} - -.radio { - color: #008000; -} - -.sciradio { - color: #993399; -} - -.comradio { - color: #948f02; -} - -.secradio { - color: #a30000; -} - -.medradio { - color: #337296; -} - -.engradio { - color: #fb5613; -} - -.suppradio { - color: #a8732b; -} - -.servradio { - color: #6eaa2c; -} - -.syndradio { - color: #6d3f40; -} - -.gangradio { - color: #ac2ea1; -} - -.centcomradio { - color: #686868; -} - -.aiprivradio { - color: #ff00ff; -} - -.redteamradio { - color: #ff0000; -} - -.blueteamradio { - color: #0000ff; -} - -.greenteamradio { - color: #00ff00; -} - -.yellowteamradio { - color: #d1ba22; -} - -.yell { - font-weight: bold; -} - -.alert { - color: #ff0000; -} - -h1.alert, h2.alert { - color: #000000; -} - -.userdanger { - color: #ff0000; - font-weight: bold; - font-size: 185%; -} - -.bolddanger { - color: #ff0000; - font-weight: bold; -} - -.danger { - color: #ff0000; -} - -.tinydanger { - color: #ff0000; - font-size: 85%; -} - -.smalldanger { - color: #ff0000; - font-size: 90%; -} - -.warning { - color: #ff0000; - font-style: italic; -} - -.alertwarning { - color: #FF0000; - font-weight: bold; -} - -.boldwarning { - color: #ff0000; - font-style: italic; - font-weight: bold; -} - -.announce { - color: #228b22; - font-weight: bold; -} - -.boldannounce { - color: #ff0000; - font-weight: bold; -} - -.minorannounce { - font-weight: bold; - font-size: 185%; -} - -.greenannounce { - color: #00ff00; - font-weight: bold; -} - -.rose { - color: #ff5050; -} - -.info { - color: #0000CC; -} - -.notice { - color: #000099; -} - -.tinynotice { - color: #000099; - font-size: 85%; -} - -.tinynoticeital { - color: #000099; - font-style: italic; - font-size: 85%; -} - -.smallnotice { - color: #000099; - font-size: 90%; -} - -.smallnoticeital { - color: #000099; - font-style: italic; - font-size: 90%; -} - -.boldnotice { - color: #000099; - font-weight: bold; -} - -.hear { - color: #000099; - font-style: italic; -} - -.adminnotice { - color: #0000ff; -} - -.adminhelp { - color: #ff0000; - font-weight: bold; -} - -.unconscious { - color: #0000ff; - font-weight: bold; -} - -.suicide { - color: #ff5050; - font-style: italic; -} - -.green { - color: #03ff39; -} - -.grey { - color: #838383; -} - -.red { - color: #FF0000; -} - -.blue { - color: #0000FF; -} - -.nicegreen { - color: #14a833; -} - -.boldnicegreen { - color: #14a833; - font-weight: bold; -} - -.cult { - color: #973e3b; -} - -.cultitalic { - color: #973e3b; - font-style: italic; -} - -.cultbold { - color: #973e3b; - font-style: italic; - font-weight: bold; -} - -.cultboldtalic { - color: #973e3b; - font-weight: bold; - font-size: 185%; -} - -.cultlarge { - color: #973e3b; - font-weight: bold; - font-size: 185%; -} - -.narsie { - color: #973e3b; - font-weight: bold; - font-size: 925%; -} - -.narsiesmall { - color: #973e3b; - font-weight: bold; - font-size: 370%; -} - -.colossus { - color: #7F282A; - font-size: 310%; -} - -.hierophant { - color: #660099; - font-weight: bold; - font-style: italic; -} - -.hierophant_warning { - color: #660099; - font-style: italic; -} - -.purple { - color: #5e2d79; -} - -.holoparasite { - color: #35333a; -} - -.revennotice { - color: #1d2953; -} - -.revenboldnotice { - color: #1d2953; - font-weight: bold; -} - -.revenbignotice { - color: #1d2953; - font-weight: bold; - font-size: 185%; -} - -.revenminor { - color: #823abb; -} - -.revenwarning { - color: #760fbb; - font-style: italic; -} - -.revendanger { - color: #760fbb; - font-weight: bold; - font-size: 185%; -} - -.deconversion_message { - color: #5000A0; - font-size: 185%; - font-style: italic; -} - -.ghostalert { - color: #5c00e6; - font-style: italic; - font-weight: bold; -} - -.alien { - color: #543354; -} - -.noticealien { - color: #00c000; -} - -.alertalien { - color: #00c000; - font-weight: bold; -} - -.changeling { - color: #800080; - font-style: italic; -} - -.alertsyndie { - color: #FF0000; - font-size: 185%; - font-weight: bold; -} - -.spider { - color: #4d004d; - font-weight: bold; - font-size: 185%; -} - -.interface { - color: #330033; -} - -.sans { - font-family: "Comic Sans MS", cursive, sans-serif; -} - -.papyrus { - font-family: "Papyrus", cursive, sans-serif; -} - -.robot { - font-family: "Courier New", cursive, sans-serif; -} - -.tape_recorder { - color: #800000; - font-family: "Courier New", cursive, sans-serif; -} - -.command_headset { - font-weight: bold; - font-size: 160%; -} - -.small { - font-size: 60%; -} - -.big { - font-size: 185%; -} - -.reallybig { - font-size: 245%; -} - -.extremelybig { - font-size: 310%; -} - -.greentext { - color: #00FF00; - font-size: 185%; -} - -.redtext { - color: #FF0000; - font-size: 185%; -} - -.clown { - color: #FF69Bf; - font-size: 160%; - font-family: "Comic Sans MS", cursive, sans-serif; - font-weight: bold; -} - -.singing { - font-family: "Trebuchet MS", cursive, sans-serif; - font-style: italic; -} - -.his_grace { - color: #15D512; - font-family: "Courier New", cursive, sans-serif; - font-style: italic; -} - -.hypnophrase { - color: #0d0d0d; - font-weight: bold; - animation: hypnocolor 1500ms infinite; - animation-direction: alternate; -} - -@keyframes hypnocolor { - 0% { - color: #0d0d0d; - } - - 25% { - color: #410194; - } - - 50% { - color: #7f17d8; - } - - 75% { - color: #410194; - } - - 100% { - color: #3bb5d3; - } -} - -.phobia { - color: #dd0000; - font-weight: bold; - animation: phobia 750ms infinite; -} - -@keyframes phobia { - 0% { - color: #0d0d0d; - } - - 50% { - color: #dd0000; - } - - 100% { - color: #0d0d0d; - } -} - -.icon { - height: 1em; - width: auto; -} - -.bigicon { - font-size: 2.5em; -} - -.memo { - color: #638500; - text-align: center; -} - -.memoedit { - text-align: center; - font-size: 125%; -} - -.abductor { - color: #800080; - font-style: italic; -} - -.mind_control { - color: #A00D6F; - font-size: 100%; - font-weight: bold; - font-style: italic; -} - -.slime { - color: #00CED1; -} - -.drone { - color: #848482; -} - -.monkey { - color: #975032; -} - -.swarmer { - color: #2C75FF; -} - -.resonate { - color: #298F85; -} - -.monkeyhive { - color: #774704; -} - -.monkeylead { - color: #774704; - font-size: 80%; -} - -.connectionClosed, -.fatalError { - background: red; - color: white; - padding: 5px; -} - -.connectionClosed.restored { - background: green; -} - -.internal.boldnshit { - color: blue; - font-weight: bold; -} - - - -/* HELPER CLASSES */ - - -.text-normal { - font-weight: normal; - font-style: normal; -} - -.hidden { - display: none; - visibility: hidden; -} - -.ml-1 { - margin-left: 1em; -} - -.ml-2 { - margin-left: 2em; -} - -.ml-3 { - margin-left: 3em; -} - -.tooltip { - font-style: italic; - border-bottom: 1px dashed #000; -} - -/* SKYRAT LIGHT MODE CLASSES */ -.mentor {color: #8a2be2;} -.looc {color: #6699CC; font-weight: bold;} -.rlooc {color: #507294; font-weight: bold;} - -.examine_block { - background: rgba(0, 0, 0, 0.1); - border: 1px solid #111a27; - margin: 2px 8px; - padding: 8px 12px; - max-width: 550px; -} - -.examine_block hr { - border: none; - background: #333; - height: 1px; - margin: 8px 16px 8px 16px; -} - -.crossooc { - color: #9f6efc; - font-weight: bold; -} - -.crossasay { - color: #ff0000; - font-weight: bold; -} - -.pink { - color: #ff00ff; - font-weight: bold; -} - -.brown { - color: #3d2009; - font-weight: bold; -} - -.orange { - color: #b8761a; - font-weight: bold; -} - -.yellow { - color: #c7b72c; - font-weight: bold; -} - -.cyan { - color: #0ea1e6; - font-weight: bold; -} From d290595112fcc3969b7c078f8694929922a13ed4 Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:32:27 -0800 Subject: [PATCH 44/49] linebreaks --- .../microfusion/code/microfusion_cell_attachments.dm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm b/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm index 4bf806d95214..cb60e0ad12f0 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_cell_attachments.dm @@ -34,7 +34,8 @@ Increases the cell capacity by a set percentage. /obj/item/microfusion_cell_attachment/overcapacity name = "overcapacity microfusion cell attachment" - desc = "An attachment which increases the capacity of the microfusion cell it's attached to. These are an additional, smaller capacitor, using a system to automatically switch from the cell to the capacitor as it's depleted, maximizing the weapon's charge." + desc = "An attachment which increases the capacity of the microfusion cell it's attached to. \ + These are an additional, smaller capacitor, using a system to automatically switch from the cell to the capacitor as it's depleted, maximizing the weapon's charge." icon_state = "attachment_overcapacity" attachment_overlay_icon_state = "microfusion_overcapacity" /// How much the attachment increases the cell's capacity by, as a percentage @@ -62,7 +63,8 @@ The cell is stable and will not emit sparks when firing. /obj/item/microfusion_cell_attachment/stabiliser name = "stabilising microfusion cell attachment" - desc = "A stabilizer system attachment combining a grounding system with additional containment coils for self-charging purposes, this gives additional safety to the cell it's attached to; preventing both sparks and leakage." + desc = "A stabilizer system attachment combining a grounding system with additional containment coils for self-charging purposes, \ + this gives additional safety to the cell it's attached to; preventing both sparks and leakage." icon_state = "attachment_stabiliser" attachment_overlay_icon_state = "microfusion_stabiliser" @@ -83,7 +85,8 @@ If the cell isn't stabilised by a stabiliser, it may emit a radiation pulse. /obj/item/microfusion_cell_attachment/selfcharging name = "self-charging microfusion cell attachment" - desc = "While microfusion cells are normally shipped without their fuel source, this attachment comes with fifteen grams of hydrogen fuel; allowing the cell to sustain a small, yet active reaction to self-charge. These can keep going for weeks to months in ideal conditions, making them more than enough for most campaigns." + desc = "While microfusion cells are normally shipped without their fuel source, this attachment comes with fifteen grams of hydrogen fuel; allowing the cell to sustain a small, \ + yet active reaction to self-charge. These can keep going for weeks to months in ideal conditions, making them more than enough for most campaigns." icon_state = "attachment_selfcharge" attachment_overlay_icon_state = "microfusion_selfcharge" /// The amount of charge this cell will passively gain! From be366fb701f4c758f575ecdcded0a35073cda8d8 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 20 Jan 2024 18:07:08 -0500 Subject: [PATCH 45/49] Update construction.dm --- code/__DEFINES/construction.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm index 3bc3492c9617..f9e8c1af993f 100644 --- a/code/__DEFINES/construction.dm +++ b/code/__DEFINES/construction.dm @@ -75,7 +75,7 @@ // Defines related to the custom materials used on objects. ///The amount of materials you get from a sheet of mineral like iron/diamond/glass etc. 100 Units. -#define SHEET_MATERIAL_AMOUNT 100 +#define SHEET_MATERIAL_AMOUNT 2000 ///The amount of materials you get from half a sheet. Used in standard object quantities. 50 units. #define HALF_SHEET_MATERIAL_AMOUNT (SHEET_MATERIAL_AMOUNT/2) ///The amount of materials used in the smallest of objects, like pens and screwdrivers. 10 units. From 5400d0d87da96f3d1ca5aaaf43156fbf557ee155 Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Sun, 21 Jan 2024 17:08:55 -0800 Subject: [PATCH 46/49] firing range --- .../ghost_players/job_helpers/firing_range_helper.dm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/monkestation/code/modules/ghost_players/job_helpers/firing_range_helper.dm b/monkestation/code/modules/ghost_players/job_helpers/firing_range_helper.dm index f6b519ef0f0e..f60a15e07490 100644 --- a/monkestation/code/modules/ghost_players/job_helpers/firing_range_helper.dm +++ b/monkestation/code/modules/ghost_players/job_helpers/firing_range_helper.dm @@ -6,6 +6,11 @@ icon = 'icons/obj/money_machine.dmi' icon_state = "bogdanoff" blacklisted_items = list( + /obj/item/ammo_box/c38/trac, + /obj/item/ammo_box/magazine/m556/phasic, + /obj/item/ammo_box/magazine/sniper_rounds/penetrator, + /obj/item/ammo_box/magazine, + /obj/item/ammo_box/magazine/toy, /obj/item/gun/ballistic, /obj/item/gun/ballistic/automatic, /obj/item/gun/ballistic/shotgun/doublebarrel/brazil/death, @@ -34,11 +39,7 @@ /obj/item/gun/magic/wand/door, /obj/item/gun/magic/wand/polymorph, /obj/item/gun/magic/wand/teleport, - /obj/item/ammo_box/c38/trac, - /obj/item/ammo_box/magazine/m556/phasic, - /obj/item/ammo_box/magazine/sniper_rounds/penetrator, - /obj/item/ammo_box/magazine, - /obj/item/ammo_box/magazine/toy, + /obj/item/microfusion_gun_attachment/barrel/xray, ) blacklisted_types = list( /obj/item/ammo_box/magazine/internal, From e1ea710d89b3a21ca8dd4b9091434ac501b8f47f Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Tue, 23 Jan 2024 21:59:39 -0800 Subject: [PATCH 47/49] minor fix --- code/modules/mod/modules/modules_security.dm | 4 ++-- .../modules/antagonists/contractor/items/modsuit/theme.dm | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index f0946248ce84..8669e7debe8d 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -18,8 +18,8 @@ /obj/item/mod/module/magnetic_harness/Initialize(mapload) . = ..() if(!guns_typecache) - guns_typecache = typecacheof(list(/obj/item/gun/ballistic, /obj/item/gun/energy, /obj/item/gun/grenadelauncher, /obj/item/gun/chem, /obj/item/gun/syringe)) - + guns_typecache = typecacheof(list(/obj/item/gun/ballistic, /obj/item/gun/energy, /obj/item/gun/grenadelauncher, /obj/item/gun/chem, /obj/item/gun/syringe, /obj/item/gun/microfusion)) +//monkestation edit on previous line: adds microfusion guns /obj/item/mod/module/magnetic_harness/on_install() already_allowed_guns = guns_typecache & mod.chestplate.allowed mod.chestplate.allowed |= guns_typecache diff --git a/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm b/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm index 805f91d78eea..e3e461cb977b 100644 --- a/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm +++ b/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm @@ -31,6 +31,7 @@ /obj/item/shield/energy, /obj/item/gun/ballistic, /obj/item/gun/energy, + /obj/item/gun/microfusion, ) skins = list( "contractor" = list( From 04d1d56e16abb4c0a372b2d8a84a63dc3a9cf11d Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Sat, 27 Jan 2024 00:06:29 -0800 Subject: [PATCH 48/49] fixed unlimited ammo --- .../code/modules/microfusion/code/microfusion_energy_master.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm index ac2e2ebeefa1..b4f352f43a9a 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm @@ -143,7 +143,7 @@ update_appearance() /obj/item/gun/microfusion/can_shoot() - return !QDELETED(cell) ? (cell.charge >= microfusion_lens.e_cost) : FALSE + return !QDELETED(cell) ? (cell.charge >= (microfusion_lens.e_cost + extra_power_usage)) : FALSE /obj/item/gun/microfusion/recharge_newshot() if (!microfusion_lens || !cell || !phase_emitter) From 66ea3adce48990bd5aa6b3e5275b8839f44b5ee4 Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Sat, 27 Jan 2024 00:12:47 -0800 Subject: [PATCH 49/49] use() correctly --- .../modules/microfusion/code/microfusion_energy_master.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm index b4f352f43a9a..6d3b282672b3 100644 --- a/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm +++ b/monkestation/code/modules/microfusion/code/microfusion_energy_master.dm @@ -220,19 +220,19 @@ user.visible_message(span_danger("[user] tries to light [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src], but it doesn't do anything. Dumbass.")) playsound(user, microfusion_lens.fire_sound, 50, TRUE) playsound(user, loaded_projectile.hitsound, 50, TRUE) - cell.use(microfusion_lens.e_cost) + cell.use(microfusion_lens.e_cost + extra_power_usage) . = "" else if(loaded_projectile.damage_type != BURN) user.visible_message(span_danger("[user] tries to light [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src], but only succeeds in utterly destroying it. Dumbass.")) playsound(user, microfusion_lens.fire_sound, 50, TRUE) playsound(user, loaded_projectile.hitsound, 50, TRUE) - cell.use(microfusion_lens.e_cost) + cell.use(microfusion_lens.e_cost + extra_power_usage) qdel(to_ignite) . = "" else playsound(user, microfusion_lens.fire_sound, 50, TRUE) playsound(user, loaded_projectile.hitsound, 50, TRUE) - cell.use(microfusion_lens.e_cost) + cell.use(microfusion_lens.e_cost + extra_power_usage) . = span_danger("[user] casually lights [to_ignite.loc == user ? "[user.p_their()] [to_ignite.name]" : to_ignite] with [src]. Damn.") /obj/item/gun/microfusion/attackby(obj/item/attacking_item, mob/user, params) @@ -304,7 +304,7 @@ if(user.is_holding(src)) user.visible_message(span_suicide("[user] melts [user.p_their()] face off with [src]!")) playsound(loc, fire_sound, 50, TRUE, -1) - cell.use(microfusion_lens.e_cost) + cell.use(microfusion_lens.e_cost + extra_power_usage) update_appearance() return(FIRELOSS) else
act('change_gun_name')} /> - )}> + title={'Gun Info'}> {gun_name} From 6d00b910d7ad613a6b5c47e7eec0aabaf939cf0b Mon Sep 17 00:00:00 2001 From: Zonespace <41448081+Zonespace27@users.noreply.github.com> Date: Sat, 23 Apr 2022 09:34:08 -0700 Subject: [PATCH 15/49] Adds Gun Cargo (#12632) * mega-commit * js fix 1 * js fix 2 * documentation1 * balance? * balance pass * 2 -> 20 mins * m90 increase * thanks prophet (balance and stuff) * more touchups * mini correction * cmg update * tgui fix * this took me too long * permit pin removal (testing) * price bump * accidental commit * ammo cheapening * weh * this is incredibly embarassing * woo * woo * pepperballs * permit-pins are lame anyway * dep guards get permits * CI fix * model75 increase * fix lint * model75 removal * Update cargo_stuff.dm * ZONESPACE REEEEE * not the bluie's anymore * interdyne company fixes and stuff * fix * fix2 * nagant revolver removal * threshold changes * undo * techshell to dynamics * mag cost 3.5 -> 3 * dynamics 10mm auto * ammo gens manifest * ladon/osprey price changes * if ixed it for you sir * assault rifle rebalancing * review * Update modular_skyrat/modules/gun_cargo/code/datums/cargo_pack.dm Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Dragonfruits <51841793+Spc-Dragonfruits@users.noreply.github.com> * Update modular_skyrat/modules/sec_haul/code/guns/guns.dm Co-authored-by: Dragonfruits <51841793+Spc-Dragonfruits@users.noreply.github.com> * weh * add disabler crates back Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com> Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> Co-authored-by: Dragonfruits <51841793+Spc-Dragonfruits@users.noreply.github.com> --- code/__DEFINES/atom_hud.dm | 17 +- code/__DEFINES/~skyrat_defines/armaments.dm | 43 + code/__DEFINES/~skyrat_defines/gun.dm | 23 + code/__DEFINES/~skyrat_defines/projectiles.dm | 23 + code/__DEFINES/~skyrat_defines/span.dm | 19 + code/controllers/subsystem/shuttle.dm | 4 + code/datums/hud.dm | 2 +- code/game/data_huds.dm | 5 +- .../crates_lockers/closets/secure/cargo.dm | 3 + .../crates_lockers/closets/secure/security.dm | 54 +- code/modules/cargo/goodies.dm | 19 +- code/modules/cargo/orderconsole.dm | 41 +- code/modules/cargo/packs.dm | 3021 +++++++++++++++++ .../file_system/programs/budgetordering.dm | 10 + .../projectiles/guns/ballistic/pistol.dm | 2 +- .../security_levels/keycard_authentication.dm | 12 + code/modules/shuttle/supply.dm | 1 + code/modules/uplink/uplink_items/nukeops.dm | 6 +- interface/stylesheet.dm | 4 + .../projectiles/guns/ballistic/automatic.dm | 346 ++ .../code/modules/projectiles/guns/gun.dm | 43 + .../master_files/icons/mob/huds/hud.dmi | Bin 0 -> 12766 bytes .../modules/ERT_Factions/FTU/code/items.dm | 139 + .../modules/aesthetics/guns/code/guns.dm | 329 ++ .../armaments/code/armament_component.dm | 275 ++ .../code/armaments/_armament_primary.dm | 72 + .../code/armaments/_armaments_secondary.dm | 62 + .../code/armaments/armament_headgear.dm | 29 + .../code/armaments/armament_medical.dm | 73 + .../code/armaments/armament_melee.dm | 33 + .../code/armaments/_armament_primary.dm | 75 + .../modules/blueshield/code/blueshield.dm | 107 + modular_skyrat/modules/cargo/code/goodies.dm | 107 + modular_skyrat/modules/cargo/code/packs.dm | 598 ++++ .../modules/goofsec/code/department_guards.dm | 498 +++ .../modules/goofsec/code/projectiles.dm | 6 + .../gun_cargo/code/armament_component.dm | 516 +++ .../gun_cargo/code/armament_datums/allstar.dm | 62 + .../code/armament_datums/armadyne.dm | 69 + .../code/armament_datums/armadyne_oldarms.dm | 58 + .../gun_cargo/code/armament_datums/bolt.dm | 60 + .../code/armament_datums/cantalan.dm | 81 + .../code/armament_datums/dynamics.dm | 119 + .../code/armament_datums/interdyne.dm | 64 + .../gun_cargo/code/armament_datums/izhevsk.dm | 50 + .../gun_cargo/code/armament_datums/micron.dm | 142 + .../code/armament_datums/nanotrasen.dm | 55 + .../code/armament_datums/parent_armament.dm | 20 + .../code/armament_datums/scarborough.dm | 64 + .../modules/gun_cargo/code/company_datums.dm | 113 + .../gun_cargo/code/datums/cargo_order.dm | 29 + .../gun_cargo/code/datums/cargo_pack.dm | 13 + .../modules/gun_cargo/code/datums/hud.dm | 2 + .../modules/gun_cargo/code/gun_companies.dm | 39 + .../modules/gun_cargo/code/gun_subsystem.dm | 150 + .../modules/gun_cargo/code/objects/access.dm | 8 + .../gun_cargo/code/objects/ammo_boxes.dm | 130 + .../modules/gun_cargo/code/objects/box.dm | 15 + .../gun_cargo/code/objects/cargo_console.dm | 3 + .../gun_cargo/code/objects/firing_pin.dm | 34 + .../gun_cargo/code/objects/guns/interdyne.dm | 28 + .../gun_cargo/code/objects/hud_glasses.dm | 7 + .../gun_cargo/code/objects/keycard_auth.dm | 4 + .../modules/gun_cargo/icons/ammo.dmi | Bin 0 -> 541 bytes .../modules/gun_cargo/icons/honeybee.dmi | Bin 0 -> 595 bytes .../modules/gun_cargo/icons/hud_goggles.dmi | Bin 0 -> 302 bytes .../gun_cargo/icons/hud_goggles_worn.dmi | Bin 0 -> 288 bytes .../modules/gunsgalore/code/guns/akm.dm | 48 + .../modules/gunsgalore/code/guns/luger.dm | 17 + .../modules/gunsgalore/code/guns/mp40.dm | 42 + .../modules/gunsgalore/code/guns/ppsh.dm | 45 + .../modules/gunsgalore/code/guns/stg.dm | 37 + .../modules/mapping/code/shuttles.dm | 191 ++ .../modular_weapons/code/autolathe_designs.dm | 120 + .../modules/modular_weapons/code/automatic.dm | 112 + .../modules/modular_weapons/code/energy.dm | 230 ++ .../code/modular_projectiles.dm | 401 +++ .../modules/modular_weapons/code/pistol.dm | 98 + .../modules/modular_weapons/code/revolver.dm | 54 + .../modules/modular_weapons/code/rifle.dm | 163 + .../modular_weapons/icons/obj/ammo.dmi | Bin 0 -> 2182 bytes .../sec_haul/code/guns/armory_spawns.dm | 116 + .../modules/sec_haul/code/guns/guns.dm | 811 +++++ .../sec_haul/code/guns/pepperball_gun.dm | 74 + .../code/guns/token_system/gunsets.dm | 379 +++ .../modules/sec_haul/code/misc/packs.dm | 17 + .../modules/microfusion/code/cargo_stuff.dm | 7 +- .../modules/microfusion/code/gun_types.dm | 10 +- .../tgui-panel/styles/goon/chat-dark.scss | 1043 ++++++ .../tgui-panel/styles/goon/chat-light.scss | 994 ++++++ tgui/packages/tgui/interfaces/Cargo.js | 7 + .../tgui/interfaces/CargoGunConsole.js | 201 ++ tgui/packages/tgui/interfaces/KeycardAuth.js | 9 +- 93 files changed, 13198 insertions(+), 64 deletions(-) create mode 100644 code/__DEFINES/~skyrat_defines/armaments.dm create mode 100644 code/__DEFINES/~skyrat_defines/gun.dm create mode 100644 code/__DEFINES/~skyrat_defines/projectiles.dm create mode 100644 code/__DEFINES/~skyrat_defines/span.dm create mode 100644 code/modules/cargo/packs.dm create mode 100644 modular_skyrat/master_files/code/modules/projectiles/guns/ballistic/automatic.dm create mode 100644 modular_skyrat/master_files/icons/mob/huds/hud.dmi create mode 100644 modular_skyrat/modules/ERT_Factions/FTU/code/items.dm create mode 100644 modular_skyrat/modules/aesthetics/guns/code/guns.dm create mode 100644 modular_skyrat/modules/armaments/code/armament_component.dm create mode 100644 modular_skyrat/modules/assault_operatives/code/armaments/_armament_primary.dm create mode 100644 modular_skyrat/modules/assault_operatives/code/armaments/_armaments_secondary.dm create mode 100644 modular_skyrat/modules/assault_operatives/code/armaments/armament_headgear.dm create mode 100644 modular_skyrat/modules/assault_operatives/code/armaments/armament_medical.dm create mode 100644 modular_skyrat/modules/assault_operatives/code/armaments/armament_melee.dm create mode 100644 modular_skyrat/modules/black_mesa/code/armaments/_armament_primary.dm create mode 100644 modular_skyrat/modules/blueshield/code/blueshield.dm create mode 100644 modular_skyrat/modules/cargo/code/goodies.dm create mode 100644 modular_skyrat/modules/cargo/code/packs.dm create mode 100644 modular_skyrat/modules/goofsec/code/department_guards.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_component.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/allstar.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne_oldarms.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/bolt.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/cantalan.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/dynamics.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/interdyne.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/izhevsk.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/micron.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/nanotrasen.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/parent_armament.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/armament_datums/scarborough.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/company_datums.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/datums/cargo_order.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/datums/cargo_pack.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/datums/hud.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/gun_companies.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/gun_subsystem.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/access.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/ammo_boxes.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/box.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/cargo_console.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/firing_pin.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/guns/interdyne.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/hud_glasses.dm create mode 100644 modular_skyrat/modules/gun_cargo/code/objects/keycard_auth.dm create mode 100644 modular_skyrat/modules/gun_cargo/icons/ammo.dmi create mode 100644 modular_skyrat/modules/gun_cargo/icons/honeybee.dmi create mode 100644 modular_skyrat/modules/gun_cargo/icons/hud_goggles.dmi create mode 100644 modular_skyrat/modules/gun_cargo/icons/hud_goggles_worn.dmi create mode 100644 modular_skyrat/modules/gunsgalore/code/guns/akm.dm create mode 100644 modular_skyrat/modules/gunsgalore/code/guns/luger.dm create mode 100644 modular_skyrat/modules/gunsgalore/code/guns/mp40.dm create mode 100644 modular_skyrat/modules/gunsgalore/code/guns/ppsh.dm create mode 100644 modular_skyrat/modules/gunsgalore/code/guns/stg.dm create mode 100644 modular_skyrat/modules/mapping/code/shuttles.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/autolathe_designs.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/automatic.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/energy.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/pistol.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/revolver.dm create mode 100644 modular_skyrat/modules/modular_weapons/code/rifle.dm create mode 100644 modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi create mode 100644 modular_skyrat/modules/sec_haul/code/guns/armory_spawns.dm create mode 100644 modular_skyrat/modules/sec_haul/code/guns/guns.dm create mode 100644 modular_skyrat/modules/sec_haul/code/guns/pepperball_gun.dm create mode 100644 modular_skyrat/modules/sec_haul/code/guns/token_system/gunsets.dm create mode 100644 modular_skyrat/modules/sec_haul/code/misc/packs.dm create mode 100644 tgui/packages/tgui-panel/styles/goon/chat-dark.scss create mode 100644 tgui/packages/tgui-panel/styles/goon/chat-light.scss create mode 100644 tgui/packages/tgui/interfaces/CargoGunConsole.js diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index 94c94521deea..31e9a07a8fb4 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -42,14 +42,13 @@ //for antag huds. these are used at the /mob level #define ANTAG_HUD "20" // for fans to identify pins -#define FAN_HUD "21" -/// Mech camera HUD -#define DIAG_CAMERA_HUD "22" - -#define NANITE_HUD "23" -#define DIAG_NANITE_FULL_HUD "24" -// for gun permit -#define PERMIT_HUD "25" +#define FAN_HUD "24" +//SKYRAT EDIT START +/// ammo of guns +#define AMMO_HUD "25" +/// if they have a gun permit +#define PERMIT_HUD "26" +//SKYRAT EDIT END //by default everything in the hud_list of an atom is an image //a value in hud_list with one of these will change that behavior @@ -67,7 +66,7 @@ #define DATA_HUD_SENTIENT_DISEASE 8 #define DATA_HUD_AI_DETECT 9 #define DATA_HUD_FAN 10 -#define DATA_HUD_PERMIT 11 +#define DATA_HUD_PERMIT 11 //SKYRAT EDIT // Notification action types #define NOTIFY_JUMP "jump" diff --git a/code/__DEFINES/~skyrat_defines/armaments.dm b/code/__DEFINES/~skyrat_defines/armaments.dm new file mode 100644 index 000000000000..e73bc8664a76 --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/armaments.dm @@ -0,0 +1,43 @@ +// Armament categories +#define ARMAMENT_CATEGORY_STANDARD "Standard Equipment" +#define ARMAMENT_CATEGORY_STANDARD_LIMIT 1 + +// Armament subcategories +#define ARMAMENT_SUBCATEGORY_NONE "Uncategorised" + +/// To identify the limit of the category type in the associative list. Techical stuff. +#define CATEGORY_LIMIT "Category Limit" +#define CATEGORY_ENTRY "Category Entry" + +// All the categories +#define ARMAMENT_CATEGORY_MELEE "Melee Weapons" +#define ARMAMENT_CATEGORY_MELEE_LIMIT 1 +#define ARMAMENT_CATEGORY_PRIMARY "Primary Weapons" +#define ARMAMENT_CATEGORY_PRIMARY_LIMIT 1 +#define ARMAMENT_CATEGORY_SECONDARY "Secondary Weapons" +#define ARMAMENT_CATEGORY_SECONDARY_LIMIT 1 +#define ARMAMENT_CATEGORY_ARMOR_HEAD "Headgear" +#define ARMAMENT_CATEGORY_ARMOR_HEAD_LIMIT 1 +#define ARMAMENT_CATEGORY_MEDICAL "Medical Supplies" +#define ARMAMENT_CATEGORY_MEDICAL_LIMIT 5 + + +// All the subcategories +#define ARMAMENT_SUBCATEGORY_AMMO "Ammunition" +#define ARMAMENT_SUBCATEGORY_MELEE_LETHAL "Lethal Weaponry" +#define ARMAMENT_SUBCATEGORY_MELEE_NONLETHAL "Non-Lethal Weaponry" +#define ARMAMENT_SUBCATEGORY_SUBMACHINEGUN "Submachine Guns" +#define ARMAMENT_SUBCATEGORY_ASSAULTRIFLE "Assault Rifles" +#define ARMAMENT_SUBCATEGORY_SPECIAL "Special Weapons" +#define ARMAMENT_SUBCATEGORY_PISTOL "Pistols" +#define ARMAMENT_SUBCATEGORY_HELMET "Helmets" +#define ARMAMENT_SUBCATEGORY_BERETS "Berets" +#define ARMAMENT_SUBCATEGORY_MEDKIT "Medkits" +#define ARMAMENT_SUBCATEGORY_INJECTOR "Injectors" +#define ARMAMENT_SUBCATEGORY_SHOTGUN "Shotguns" +#define ARMAMENT_SUBCATEGORY_LASER "Laser Weaponry" +#define ARMAMENT_SUBCATEGORY_ARMOR "Armor" +#define ARMAMENT_SUBCATEGORY_GUNPART "Gun Parts" +#define ARMAMENT_SUBCATEGORY_EMITTER "Phase Emitter" +#define ARMAMENT_SUBCATEGORY_CELL_UPGRADE "Cell Upgrade" +#define ARMAMENT_SUBCATEGORY_CHEMICAL "Chemicals" diff --git a/code/__DEFINES/~skyrat_defines/gun.dm b/code/__DEFINES/~skyrat_defines/gun.dm new file mode 100644 index 000000000000..da453fe65258 --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/gun.dm @@ -0,0 +1,23 @@ +#define SELECT_SEMI_AUTOMATIC 1 +#define SELECT_BURST_SHOT 2 +#define SELECT_FULLY_AUTOMATIC 3 + +// Bitflags for what company produces the gun +#define COMPANY_CANTALAN (1<<0) +#define COMPANY_ARMADYNE (1<<1) +#define COMPANY_SCARBOROUGH (1<<2) +#define COMPANY_DONK (1<<3) +#define COMPANY_BOLT (1<<4) +#define COMPANY_OLDARMS (1<<5) +#define COMPANY_IZHEVSK (1<<6) +#define COMPANY_NANOTRASEN (1<<7) +#define COMPANY_ALLSTAR (1<<8) +#define COMPANY_MICRON (1<<9) +#define COMPANY_DYNAMICS (1<<10) +#define COMPANY_INTERDYNE (1<<12) + +#define COMPANY_INTEREST_GUN 10 +#define COMPANY_INTEREST_CHEMICAL 5 +#define COMPANY_INTEREST_ATTACHMENT 4 +#define COMPANY_INTEREST_AMMO_BULK 3 +#define COMPANY_INTEREST_AMMO 1 diff --git a/code/__DEFINES/~skyrat_defines/projectiles.dm b/code/__DEFINES/~skyrat_defines/projectiles.dm new file mode 100644 index 000000000000..96e0e61a103d --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/projectiles.dm @@ -0,0 +1,23 @@ +#define CALIBER_PEPPERBALL "pepperball" + +#define CALIBER_12MM "12mm" +#define CALIBER_473MM "473mm" +#define CALIBER_6MM "6mm" +#define CALIBER_10MMAUTO "10x25mm" + +/// The caliber used by the Automag. +#define CALIBER_44 ".44 AMP" + +/// The caliber used by the M45A5 +#define CALIBER_460 ".460 RM JHP" + +/// The caliber used by Armadyne shotguns. +#define CALIBER_14GAUGE "14 Gauge" + +#define CALIBER_50BMG ".50 BMG" + +/// The caliber used by the CFA Lynx. +#define CALIBER_42X30MM "4.2x30mm" + +/// The caliber used by the Catanheim. +#define CALIBER_A68 "a68" diff --git a/code/__DEFINES/~skyrat_defines/span.dm b/code/__DEFINES/~skyrat_defines/span.dm new file mode 100644 index 000000000000..df1212e462aa --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/span.dm @@ -0,0 +1,19 @@ +#define span_emote(str) ("" + str + "") +#define span_header(str) ("" + str + "") +#define span_italics(str) ("" + str + "") +#define span_maptext(str) ("" + str + "") +#define span_mentor(str) ("" + str + "") +#define span_mentornotice(str) ("" + str + "") +#define span_oocplain(str) ("" + str + "") +#define span_pink(str) ("" + str + "") +#define span_rlooc(str) ("" + str + "") +#define span_smalldanger(str) ("" + str + "") +#define span_userlove(str) ("" + str + "") +#define span_warningplain(str) ("" + str + "") +#define span_crossooc(str) ("" + str + "") +#define span_crossasay(str) ("" + str + "") +#define span_doyourjobidiot(str) ("" + str + "") +#define span_brown(str) ("" + str + "") +#define span_cyan(str) ("" + str + "") +#define span_orange(str) ("" + str + "") +#define span_yellow(str) ("" + str + "") diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 3a8ccad63adb..65f8ceca84e1 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -150,6 +150,10 @@ SUBSYSTEM_DEF(shuttle) while(length(pack_processing)) var/datum/supply_pack/pack = pack_processing[length(pack_processing)] pack_processing.len-- + //SKYRAT EDIT START + if(pack == /datum/supply_pack/armament) + continue + //SKYRAT EDIT END if(ispath(pack, /datum/supply_pack)) pack = new pack diff --git a/code/datums/hud.dm b/code/datums/hud.dm index 39698510962a..aefec0f44a90 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -18,7 +18,7 @@ GLOBAL_LIST_INIT(huds, list( DATA_HUD_SENTIENT_DISEASE = new/datum/atom_hud/sentient_disease(), DATA_HUD_AI_DETECT = new/datum/atom_hud/ai_detector(), DATA_HUD_FAN = new/datum/atom_hud/data/human/fan_hud(), - DATA_HUD_PERMIT = new/datum/atom_hud/data/human/permit() + DATA_HUD_PERMIT = new/datum/atom_hud/data/human/permit(), // SKYRAT EDIT )) /datum/atom_hud diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index a81e6ea68b96..bec2556aa55a 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -47,7 +47,7 @@ hud_icons = list(ID_HUD) /datum/atom_hud/data/human/security/advanced - hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD, WANTED_HUD, NANITE_HUD, PERMIT_HUD) + hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD, WANTED_HUD, NANITE_HUD, PERMIT_HUD) //monkestation edit: adds NANITE_HUD and PERMIT_HUD /datum/atom_hud/data/human/fan_hud hud_icons = list(FAN_HUD) @@ -272,13 +272,14 @@ Security HUDs! Basic mode shows only the job. sechud_icon_state = "hudno_id" holder.icon_state = sechud_icon_state sec_hud_set_security_status() - +//monkestation edit start var/image/permit_holder = hud_list[PERMIT_HUD] permit_holder.pixel_y = I.Height() - world.icon_size var/permit_icon_state = wear_id?.get_gun_permit_iconstate() if(!permit_icon_state) permit_icon_state = "hudfan_no" permit_holder.icon_state = permit_icon_state +//monkestation edit end /mob/living/proc/sec_hud_set_implants() var/image/holder diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm index 74de666ed80e..6c17794ad458 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm @@ -21,3 +21,6 @@ // Traitor steal objective new /obj/item/card/id/departmental_budget/car(src) + new /obj/item/gun/ballistic/rifle/boltaction/brand_new/quartermaster(src) // SKYRAT EDIT - The QM's 'special' head item. It spawns loaded, but you have to find more ammo if you run out and get ready to manually load rounds in! + new /obj/item/cargo_teleporter(src) // SKYRAT EDIT - Adds a cargo teleporter to QM locker, so they can intice others to research it + new /obj/item/clothing/glasses/hud/gun_permit(src) //SKYRAT EDIT - GUN CARGO diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 49fadd6ec983..76640e3b160c 100755 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -126,30 +126,60 @@ /obj/structure/closet/secure_closet/security/cargo /obj/structure/closet/secure_closet/security/cargo/PopulateContents() - ..() - new /obj/item/clothing/accessory/armband/cargo(src) - new /obj/item/encryptionkey/headset_cargo(src) + new /obj/item/radio/headset/headset_cargo(src) + new /obj/item/clothing/shoes/sneakers/black(src) + new /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/customs_agent(src) + new /obj/item/clothing/head/helmet/blueshirt/skyrat/guard(src) + new /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/customs_agent(src) + new /obj/item/restraints/handcuffs/cable/orange(src) + new /obj/item/assembly/flash/handheld(src) + new /obj/item/melee/baton/security/loaded/departmental/cargo(src) + new /obj/item/clothing/glasses/hud/security(src) + new /obj/item/clothing/glasses/hud/gun_permit(src) + new /obj/item/storage/box/gunset/pepperball(src) /obj/structure/closet/secure_closet/security/engine /obj/structure/closet/secure_closet/security/engine/PopulateContents() - ..() - new /obj/item/clothing/accessory/armband/engine(src) - new /obj/item/encryptionkey/headset_eng(src) + new /obj/item/radio/headset/headset_eng(src) + new /obj/item/clothing/shoes/workboots(src) + new /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/engineering_guard(src) + new /obj/item/clothing/head/helmet/blueshirt/skyrat/guard(src) + new /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/engineering_guard(src) + new /obj/item/restraints/handcuffs/cable/yellow(src) + new /obj/item/assembly/flash/handheld(src) + new /obj/item/melee/baton/security/loaded/departmental/engineering(src) + new /obj/item/clothing/glasses/hud/security(src) + new /obj/item/storage/box/gunset/pepperball(src) /obj/structure/closet/secure_closet/security/science /obj/structure/closet/secure_closet/security/science/PopulateContents() - ..() - new /obj/item/clothing/accessory/armband/science(src) - new /obj/item/encryptionkey/headset_sci(src) + new /obj/item/radio/headset/headset_sci(src) + new /obj/item/clothing/shoes/sneakers/black(src) + new /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat(src) + new /obj/item/clothing/head/helmet/blueshirt/skyrat(src) + new /obj/item/clothing/suit/armor/vest/blueshirt/skyrat(src) + new /obj/item/restraints/handcuffs/cable/pink(src) + new /obj/item/assembly/flash/handheld(src) + new /obj/item/melee/baton/security/loaded/departmental/science(src) + new /obj/item/clothing/glasses/hud/security(src) + new /obj/item/storage/box/gunset/pepperball(src) /obj/structure/closet/secure_closet/security/med /obj/structure/closet/secure_closet/security/med/PopulateContents() - ..() - new /obj/item/clothing/accessory/armband/medblue(src) - new /obj/item/encryptionkey/headset_med(src) + new /obj/item/radio/headset/headset_med(src) + new /obj/item/clothing/shoes/sneakers/white(src) + new /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/orderly(src) + new /obj/item/clothing/head/helmet/blueshirt/skyrat/guard(src) + new /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/orderly(src) + new /obj/item/restraints/handcuffs/cable/blue(src) + new /obj/item/assembly/flash/handheld(src) + new /obj/item/melee/baton/security/loaded/departmental/medical(src) + new /obj/item/clothing/glasses/hud/security(src) + new /obj/item/storage/box/gunset/pepperball(src) +// SKYRAT EDIT CHANGE END -- GOOFSEC DEP GUARDS /obj/structure/closet/secure_closet/detective name = "\improper detective's cabinet" diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm index 593d2ae94fd0..b3c3d96a6993 100644 --- a/code/modules/cargo/goodies.dm +++ b/code/modules/cargo/goodies.dm @@ -3,7 +3,7 @@ access = NONE group = "Goodies" goody = TRUE - +/* // SKYRAT EDIT START - CARGO GUN /datum/supply_pack/goody/dumdum38 name = ".38 DumDum Speedloader" desc = "Contains one speedloader of .38 DumDum ammunition, good for embedding in soft targets." @@ -28,10 +28,10 @@ /datum/supply_pack/goody/mars_single name = "Colt Detective Special Single-Pack" desc = "The HoS took your gun and your badge? No problem! Just pay the absurd taxation fee and you too can be reunited with the lethal power of a .38!" - cost = PAYCHECK_CREW * 40 //they really mean a premium here - access_view = ACCESS_WEAPONS - contains = list(/obj/item/gun/ballistic/revolver/c38/detective) - + cost = PAYCHECK_HARD * 40 //they really mean a premium here + access_view = ACCESS_FORENSICS + contains = list(/obj/item/gun/ballistic/revolver/detective) +*/ //SKYRAT EDIT END /datum/supply_pack/goody/stingbang name = "Stingbang Single-Pack" desc = "Contains one \"stingbang\" grenade, perfect for playing meanhearted pranks." @@ -44,7 +44,7 @@ desc = "Contains one sharpened survival knive. Guaranteed to fit snugly inside any Nanotrasen-standard boot." cost = PAYCHECK_COMMAND * 1.75 contains = list(/obj/item/knife/combat/survival) - +/* //SKYRAT EDIT START - GUN CARGO /datum/supply_pack/goody/ballistic_single name = "Combat Shotgun Single-Pack" desc = "For when the enemy absolutely needs to be replaced with lead. Contains one Aussec-designed Combat Shotgun, and one Shotgun Bandolier." @@ -83,9 +83,10 @@ /datum/supply_pack/goody/thermal_single name = "Thermal Pistol Holster Single-Pack" desc = "Contains twinned thermal pistols in a holster, ready for use in the field." - cost = PAYCHECK_COMMAND * 15 - access_view = ACCESS_WEAPONS - contains = list(/obj/item/storage/belt/holster/energy/thermal) + cost = PAYCHECK_HARD * 15 + access_view = ACCESS_ARMORY + contains = list(/obj/item/storage/belt/holster/thermal) +*/ //SKYRAT EDIT END /datum/supply_pack/goody/sologamermitts name = "Insulated Gloves Single-Pack" diff --git a/code/modules/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm index 393b07d6e10d..653feb96ef76 100644 --- a/code/modules/cargo/orderconsole.dm +++ b/code/modules/cargo/orderconsole.dm @@ -458,27 +458,20 @@ for(var/datum/supply_order/order in shopping_cart) if(order.pack.name != order_name) continue - if(remove_item(list("id" = order.id))) - return TRUE - - return TRUE - if("modify") - var/order_name = params["order_name"] - - //clear out all orders with the above mentioned order_name name to make space for the new amount - var/list/shopping_cart = SSshuttle.shopping_list.Copy() //we operate on the list copy else we would get runtimes when removing & iterating over the same SSshuttle.shopping_list - for(var/datum/supply_order/order in shopping_cart) //find corresponding order id for the order name - if(order.pack.name == order_name) - remove_item(list("id" = "[order.id]")) - - //now add the new amount stuff - var/amount = text2num(params["amount"]) - if(amount == 0) - return TRUE - var/supply_pack_id = name_to_id(order_name) //map order name to supply pack id for adding - if(!supply_pack_id) - return - return add_item(list("id" = supply_pack_id, "amount" = amount, "account_to_charge" = cargo_account)) + if(SO.department_destination) + say("Only the department that ordered this item may cancel it.") + return + if(SO.applied_coupon) + say("Coupon refunded.") + SO.applied_coupon.forceMove(get_turf(src)) + //SKYRAT EDIT START + if(istype(SO, /datum/supply_order/armament)) + var/datum/supply_order/armament/the_order = SO + the_order.reimburse_armament() + //SKYRAT EDIT END + SSshuttle.shopping_list -= SO + . = TRUE + break if("clear") //create copy of list else we will get runtimes when iterating & removing items on the same list SSshuttle.shopping_list var/list/shopping_cart = SSshuttle.shopping_list.Copy() @@ -507,6 +500,12 @@ if("toggleprivate") self_paid = !self_paid . = TRUE + //SKYRAT EDIT START + if("gun_window") + var/datum/component/armament/cargo_gun/gun_comp = GetComponent(/datum/component/armament/cargo_gun) + gun_comp.ui_interact(usr) + . = TRUE + //SKYRAT EDIT END if(.) post_signal(cargo_shuttle) diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm new file mode 100644 index 000000000000..dd3a904e4223 --- /dev/null +++ b/code/modules/cargo/packs.dm @@ -0,0 +1,3021 @@ +/datum/supply_pack + var/name = "Crate" + var/group = "" + var/hidden = FALSE + var/contraband = FALSE + /// Cost of the crate. DO NOT GO ANY LOWER THAN X1.4 the "CARGO_CRATE_VALUE" value if using regular crates, or infinite profit will be possible! + var/cost = CARGO_CRATE_VALUE * 1.4 + var/access = FALSE + var/access_view = FALSE + var/access_any = FALSE + var/list/contains = null + var/crate_name = "crate" + var/id + var/desc = ""//no desc by default + var/crate_type = /obj/structure/closet/crate + var/dangerous = FALSE // Should we message admins? + var/special = FALSE //Event/Station Goals/Admin enabled packs + var/special_enabled = FALSE + var/DropPodOnly = FALSE //only usable by the Bluespace Drop Pod via the express cargo console + var/special_pod //If this pack comes shipped in a specific pod when launched from the express console + var/admin_spawned = FALSE + var/goody = FALSE //Goodies can only be purchased by private accounts and can have coupons apply to them. They also come in a lockbox instead of a full crate, so the 700 min doesn't apply + +/datum/supply_pack/New() + id = type + +/datum/supply_pack/proc/generate(atom/A, datum/bank_account/paying_account) + var/obj/structure/closet/crate/C + if(paying_account) + C = new /obj/structure/closet/crate/secure/owned(A, paying_account) + C.name = "[crate_name] - Purchased by [paying_account.account_holder]" + else + C = new crate_type(A) + C.name = crate_name + if(access) + C.req_access = list(access) + if(access_any) + C.req_one_access = access_any + + fill(C) + return C + +/datum/supply_pack/proc/get_cost() + . = cost + . *= SSeconomy.pack_price_modifier + +/datum/supply_pack/proc/fill(obj/structure/closet/crate/C) + if (admin_spawned) + for(var/item in contains) + var/atom/A = new item(C) + A.flags_1 |= ADMIN_SPAWNED_1 + else + for(var/item in contains) + new item(C) + +/// For generating supply packs at runtime. Returns a list of supply packs to use instead of this one. +/datum/supply_pack/proc/generate_supply_packs() + return + +// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Emergency /////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/emergency + group = "Emergency" + +/datum/supply_pack/emergency/vehicle + name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN + desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!" + cost = CARGO_CRATE_VALUE * 4 + contraband = TRUE + contains = list(/obj/vehicle/ridden/atv, + /obj/item/key/atv, + /obj/item/clothing/suit/jacket/leather/overcoat, + /obj/item/clothing/gloves/color/black, + /obj/item/clothing/head/soft, + /obj/item/clothing/mask/bandana/color/skull)//so you can properly #cargoniabikergang + crate_name = "Biker Kit" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/emergency/bio + name = "Biological Emergency Crate" + desc = "This crate holds 2 full bio suits which will protect you from viruses." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/head/bio_hood, + /obj/item/clothing/head/bio_hood, + /obj/item/clothing/suit/bio_suit, + /obj/item/clothing/suit/bio_suit, + /obj/item/storage/bag/bio, + /obj/item/reagent_containers/syringe/antiviral, + /obj/item/reagent_containers/syringe/antiviral, + /obj/item/clothing/gloves/color/latex/nitrile, + /obj/item/clothing/gloves/color/latex/nitrile) + crate_name = "bio suit crate" + +/datum/supply_pack/emergency/equipment + name = "Emergency Bot/Internals Crate" + desc = "Explosions got you down? These supplies are guaranteed to patch up holes, in stations and people alike! Comes with two floorbots, two medbots, five oxygen masks and five small oxygen tanks." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/mob/living/simple_animal/bot/floorbot, + /mob/living/simple_animal/bot/floorbot, + /mob/living/simple_animal/bot/medbot, + /mob/living/simple_animal/bot/medbot, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath) + crate_name = "emergency crate" + crate_type = /obj/structure/closet/crate/internals + +/datum/supply_pack/emergency/bomb + name = "Explosive Emergency Crate" + desc = "Science gone bonkers? Beeping behind the airlock? Buy now and be the hero the station des... I mean needs! (time not included)" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/head/bomb_hood, + /obj/item/clothing/suit/bomb_suit, + /obj/item/clothing/mask/gas, + /obj/item/screwdriver, + /obj/item/wirecutters, + /obj/item/multitool) + crate_name = "bomb suit crate" + +/datum/supply_pack/emergency/firefighting + name = "Firefighting Crate" + desc = "Only you can prevent station fires. Partner up with two firefighter suits, gas masks, flashlights, large oxygen tanks, extinguishers, and hardhats!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/suit/fire/firefighter, + /obj/item/clothing/suit/fire/firefighter, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/flashlight, + /obj/item/flashlight, + /obj/item/tank/internals/oxygen/red, + /obj/item/tank/internals/oxygen/red, + /obj/item/extinguisher/advanced, + /obj/item/extinguisher/advanced, + /obj/item/clothing/head/hardhat/red, + /obj/item/clothing/head/hardhat/red) + crate_name = "firefighting crate" + +/datum/supply_pack/emergency/atmostank + name = "Firefighting Tank Backpack" + desc = "Mow down fires with this high-capacity fire fighting tank backpack. Requires Atmospherics access to open." + cost = CARGO_CRATE_VALUE * 1.8 + access = ACCESS_ATMOSPHERICS + contains = list(/obj/item/watertank/atmos) + crate_name = "firefighting backpack crate" + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/emergency/internals + name = "Internals Crate" + desc = "Master your life energy and control your breathing with three breath masks, three emergency oxygen tanks and three large air tanks."//IS THAT A + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/oxygen, + /obj/item/tank/internals/oxygen, + /obj/item/tank/internals/oxygen) + crate_name = "internals crate" + crate_type = /obj/structure/closet/crate/internals + +/datum/supply_pack/emergency/metalfoam + name = "Metal Foam Grenade Crate" + desc = "Seal up those pesky hull breaches with 7 Metal Foam Grenades." + cost = CARGO_CRATE_VALUE * 2.4 + contains = list(/obj/item/storage/box/metalfoam) + crate_name = "metal foam grenade crate" + +/datum/supply_pack/emergency/plasma_spacesuit + name = "Plasmaman Space Envirosuits" + desc = "Contains two space-worthy envirosuits for Plasmamen. Order now and we'll throw in two free helmets! Requires EVA access to open." + cost = CARGO_CRATE_VALUE * 3.5 + access = ACCESS_EVA + contains = list(/obj/item/clothing/suit/space/eva/plasmaman, + /obj/item/clothing/suit/space/eva/plasmaman, + /obj/item/clothing/head/helmet/space/plasmaman, + /obj/item/clothing/head/helmet/space/plasmaman) + crate_name = "plasmaman EVA crate" + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/emergency/plasmaman + name = "Plasmaman Supply Kit" + desc = "Keep those Plasmamen alive with two sets of Plasmaman outfits. Each set contains a plasmaman jumpsuit, gloves, internals tank, and helmet." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/clothing/under/plasmaman, + /obj/item/clothing/under/plasmaman, + /obj/item/tank/internals/plasmaman/belt/full, + /obj/item/tank/internals/plasmaman/belt/full, + /obj/item/clothing/head/helmet/space/plasmaman, + /obj/item/clothing/head/helmet/space/plasmaman, + /obj/item/clothing/gloves/color/plasmaman, + /obj/item/clothing/gloves/color/plasmaman) + crate_name = "plasmaman supply kit" + +/datum/supply_pack/emergency/radiation + name = "Radiation Protection Crate" + desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a bottle of vodka and some glasses too, considering the life-expectancy of people who order this." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/head/radiation, + /obj/item/clothing/head/radiation, + /obj/item/clothing/suit/radiation, + /obj/item/clothing/suit/radiation, + /obj/item/geiger_counter, + /obj/item/geiger_counter, + /obj/item/reagent_containers/food/drinks/bottle/vodka, + /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass, + /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass) + crate_name = "radiation protection crate" + crate_type = /obj/structure/closet/crate/radiation + +/datum/supply_pack/emergency/spacesuit + name = "Space Suit Crate" + desc = "Contains one aging suit from Space-Goodwill and a jetpack. Requires EVA access to open." + cost = CARGO_CRATE_VALUE * 3 + access = ACCESS_EVA + contains = list(/obj/item/clothing/suit/space, + /obj/item/clothing/head/helmet/space, + /obj/item/clothing/mask/breath, + /obj/item/tank/jetpack/carbondioxide) + crate_name = "space suit crate" + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/emergency/specialops + name = "Special Ops Supplies" + desc = "(*!&@#SAD ABOUT THAT NULL_ENTRY, HUH OPERATIVE? WELL, THIS LITTLE ORDER CAN STILL HELP YOU OUT IN A PINCH. CONTAINS A BOX OF FIVE EMP GRENADES, THREE SMOKEBOMBS, AN INCENDIARY GRENADE, AND A \"SLEEPY PEN\" FULL OF NICE TOXINS!#@*$" + hidden = TRUE + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/storage/box/emps, + /obj/item/grenade/smokebomb, + /obj/item/grenade/smokebomb, + /obj/item/grenade/smokebomb, + /obj/item/pen/sleepy, + /obj/item/grenade/chem_grenade/incendiary) + crate_name = "emergency crate" + crate_type = /obj/structure/closet/crate/internals + +/datum/supply_pack/emergency/weedcontrol + name = "Weed Control Crate" + desc = "Keep those invasive species OUT. Contains a scythe, gasmask, and two anti-weed chemical grenades. Warranty void if used on ambrosia. Requires Hydroponics access to open." + cost = CARGO_CRATE_VALUE * 2.5 + access = ACCESS_HYDROPONICS + contains = list(/obj/item/scythe, + /obj/item/clothing/mask/gas, + /obj/item/grenade/chem_grenade/antiweed, + /obj/item/grenade/chem_grenade/antiweed) + crate_name = "weed control crate" + crate_type = /obj/structure/closet/crate/secure/hydroponics + +/datum/supply_pack/emergency/mothic_rations + name = "Surplus Mothic Rations Triple-Pak" + desc = "Crew starving? Chef slacking off? Keep everyone fed on the barest minimum of what can be considered food with surplus ration packs, directly from the Mothic Fleet! Pack includes 3 packs of 3 bars each." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/storage/box/mothic_rations, + /obj/item/storage/box/mothic_rations, + /obj/item/storage/box/mothic_rations,) + crate_name = "surplus rations box" + crate_type = /obj/structure/closet/crate/cardboard/mothic + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Security //////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/security + group = "Security" + access = ACCESS_SECURITY + crate_type = /obj/structure/closet/crate/secure/gear +/* //SKYRAT EDIT START - CARGO ARMAMENTS +/datum/supply_pack/security/ammo + name = "Ammo Crate" + desc = "Contains three boxes of beanbag shotgun shells, three boxes of rubbershot shotgun shells and one of each special .38 speedloarders. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 8 + access_view = ACCESS_ARMORY + contains = list(/obj/item/storage/box/beanbag, + /obj/item/storage/box/beanbag, + /obj/item/storage/box/beanbag, + /obj/item/storage/box/rubbershot, + /obj/item/storage/box/rubbershot, + /obj/item/storage/box/rubbershot, + /obj/item/ammo_box/c38/trac, + /obj/item/ammo_box/c38/hotshot, + /obj/item/ammo_box/c38/iceblox) + crate_name = "ammo crate" +*/ //SKYRAT EDIT END +/* SKYRAT EDIT: Moved to Bloat.dm name = "Armor Crate" +/datum/supply_pack/security/armor + name = "Armor Crate" + desc = "Three vests of well-rounded, decently-protective armor. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2 + access_view = ACCESS_SECURITY + contains = list(/obj/item/clothing/suit/armor/vest, + /obj/item/clothing/suit/armor/vest, + /obj/item/clothing/suit/armor/vest) + crate_name = "armor crate" +*/ //SKYRAT EDIT END + +/datum/supply_pack/security/disabler + name = "Disabler Crate" + desc = "Three stamina-draining disabler weapons. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 5 //SKYRAT EDIT 3 -> 5 + access_view = ACCESS_SECURITY + contains = list(/obj/item/gun/energy/disabler, + /obj/item/gun/energy/disabler, + /obj/item/gun/energy/disabler) + crate_name = "disabler crate" + +/datum/supply_pack/security/forensics + name = "Forensics Crate" + desc = "Stay hot on the criminal's heels with Nanotrasen's Detective Essentials(tm). Contains a forensics scanner, six evidence bags, camera, tape recorder, white crayon, and of course, a fedora. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2.5 + access_view = ACCESS_MORGUE + contains = list(/obj/item/detective_scanner, + /obj/item/storage/box/evidence, + /obj/item/camera, + /obj/item/taperecorder, + /obj/item/toy/crayon/white, + /obj/item/clothing/head/fedora/det_hat) + crate_name = "forensics crate" + +/datum/supply_pack/security/helmets + name = "Helmets Crate" + desc = "Contains three standard-issue brain buckets. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/head/helmet/sec, + /obj/item/clothing/head/helmet/sec, + /obj/item/clothing/head/helmet/sec) + crate_name = "helmet crate" + +/* //SKYRAT EDIT START - CARGO ARMAMENTS +/datum/supply_pack/security/laser + name = "Lasers Crate" + desc = "Contains three lethal, high-energy laser guns. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 4 + access_view = ACCESS_ARMORY + contains = list(/obj/item/gun/energy/laser, + /obj/item/gun/energy/laser, + /obj/item/gun/energy/laser) + crate_name = "laser crate" +*/ //SKYRAT EDIT END + +/datum/supply_pack/security/securitybarriers + name = "Security Barrier Grenades" + desc = "Stem the tide with four Security Barrier grenades. Requires Security access to open." + access_view = ACCESS_BRIG + contains = list(/obj/item/grenade/barrier, + /obj/item/grenade/barrier, + /obj/item/grenade/barrier, + /obj/item/grenade/barrier) + cost = CARGO_CRATE_VALUE * 2 + crate_name = "security barriers crate" + +/* - SKYRAT EDIT REMOVAL - SEC_HUAL +/datum/supply_pack/security/securityclothes + name = "Security Clothing Crate" + desc = "Contains appropriate outfits for the station's private security force. Contains outfits for the Warden, Head of Security, and two Security Officers. Each outfit comes with a rank-appropriate jumpsuit, suit, and beret. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 3 + access_view = ACCESS_SECURITY + contains = list(/obj/item/clothing/under/rank/security/officer/formal, + /obj/item/clothing/under/rank/security/officer/formal, + /obj/item/clothing/suit/security/officer, + /obj/item/clothing/suit/security/officer, + /obj/item/clothing/head/beret/sec/navyofficer, + /obj/item/clothing/head/beret/sec/navyofficer, + /obj/item/clothing/under/rank/security/warden/formal, + /obj/item/clothing/suit/security/warden, + /obj/item/clothing/head/beret/sec/navywarden, + /obj/item/clothing/under/rank/security/head_of_security/formal, + /obj/item/clothing/suit/security/hos, + /obj/item/clothing/head/hos/beret/navyhos) + crate_name = "security clothing crate" +*/ + +/datum/supply_pack/security/stingpack + name = "Stingbang Grenade Pack" + desc = "Contains five \"stingbang\" grenades, perfect for stopping riots and playing morally unthinkable pranks. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 5 + access_view = ACCESS_ARMORY + contains = list(/obj/item/storage/box/stingbangs) + crate_name = "stingbang grenade pack crate" + +/datum/supply_pack/security/supplies + name = "Security Supplies Crate" + desc = "Contains seven flashbangs, seven teargas grenades, six flashes, and seven handcuffs. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 3.5 + access_view = ACCESS_ARMORY + contains = list(/obj/item/storage/box/flashbangs, + /obj/item/storage/box/teargas, + /obj/item/storage/box/flashes, + /obj/item/storage/box/handcuffs) + crate_name = "security supply crate" + +/datum/supply_pack/security/firingpins + name = "Standard Firing Pins Crate" + desc = "Upgrade your arsenal with 10 standard firing pins. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 4 + access_view = ACCESS_ARMORY + contains = list(/obj/item/storage/box/firingpins, + /obj/item/storage/box/firingpins) + crate_name = "firing pins crate" + +/datum/supply_pack/security/firingpins/paywall + name = "Paywall Firing Pins Crate" + desc = "Specialized firing pins with a built-in configurable paywall. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2 + access_view = ACCESS_ARMORY + contains = list(/obj/item/storage/box/firingpins/paywall, + /obj/item/storage/box/firingpins/paywall) + crate_name = "paywall firing pins crate" + +/datum/supply_pack/security/justiceinbound + name = "Standard Justice Enforcer Crate" + desc = "This is it. The Bee's Knees. The Creme of the Crop. The Pick of the Litter. The best of the best of the best. The Crown Jewel of Nanotrasen. The Alpha and the Omega of security headwear. Guaranteed to strike fear into the hearts of each and every criminal aboard the station. Also comes with a security gasmask. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 6 //justice comes at a price. An expensive, noisy price. + contraband = TRUE + contains = list(/obj/item/clothing/head/helmet/justice, + /obj/item/clothing/mask/gas/sechailer) + crate_name = "security clothing crate" + +/datum/supply_pack/security/baton + name = "Stun Batons Crate" + desc = "Arm the Civil Protection Forces with three stun batons. Batteries included. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2 + access_view = ACCESS_SECURITY + contains = list(/obj/item/melee/baton/security/loaded, + /obj/item/melee/baton/security/loaded, + /obj/item/melee/baton/security/loaded) + crate_name = "stun baton crate" + +/datum/supply_pack/security/wall_flash + name = "Wall-Mounted Flash Crate" + desc = "Contains four wall-mounted flashes. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/box/wall_flash, + /obj/item/storage/box/wall_flash, + /obj/item/storage/box/wall_flash, + /obj/item/storage/box/wall_flash) + crate_name = "wall-mounted flash crate" + +/datum/supply_pack/security/constable + name = "Traditional Equipment Crate" + desc = "Spare equipment found in a warehouse." + cost = CARGO_CRATE_VALUE * 2.2 + contraband = TRUE + contains = list(/obj/item/clothing/under/rank/security/constable, + /obj/item/clothing/head/helmet/constable, + /obj/item/clothing/gloves/color/white, + /obj/item/clothing/mask/whistle, + /obj/item/conversion_kit) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Armory ////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/security/armory + group = "Armory" + access = ACCESS_ARMORY + access_view = ACCESS_ARMORY + crate_type = /obj/structure/closet/crate/secure/weapon + +/datum/supply_pack/security/armory/bulletarmor + name = "Bulletproof Armor Crate" + desc = "Contains three sets of bulletproof armor. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/clothing/suit/armor/bulletproof, + /obj/item/clothing/suit/armor/bulletproof, + /obj/item/clothing/suit/armor/bulletproof) + crate_name = "bulletproof armor crate" + +/datum/supply_pack/security/armory/bullethelmets + name = "Bulletproof Helmets Crate" + desc = "Contains three bulletproof helmets. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/clothing/head/helmet/alt, + /obj/item/clothing/head/helmet/alt, + /obj/item/clothing/head/helmet/alt) + crate_name = "bulletproof helmets crate" + +/datum/supply_pack/security/armory/chemimp + name = "Chemical Implants Crate" + desc = "Contains five Remote Chemical implants. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 3.5 + contains = list(/obj/item/storage/box/chemimp) + crate_name = "chemical implant crate" +/* //SKYRAT EDIT START - CARGO ARMAMENTS +/datum/supply_pack/security/armory/ballistic + name = "Combat Shotguns Crate" + desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, and three Shotgun Bandoliers. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 17.5 + contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat, + /obj/item/gun/ballistic/shotgun/automatic/combat, + /obj/item/gun/ballistic/shotgun/automatic/combat, + /obj/item/storage/belt/bandolier, + /obj/item/storage/belt/bandolier, + /obj/item/storage/belt/bandolier) + crate_name = "combat shotguns crate" + +/datum/supply_pack/security/armory/dragnet + name = "DRAGnet Crate" + desc = "Contains three \"Dynamic Rapid-Apprehension of the Guilty\" netting devices, a recent breakthrough in law enforcement prisoner management technology. Requires armory access to open." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/gun/energy/e_gun/dragnet, + /obj/item/gun/energy/e_gun/dragnet, + /obj/item/gun/energy/e_gun/dragnet) + crate_name = "\improper DRAGnet crate" + + +/datum/supply_pack/security/armory/energy + name = "Energy Guns Crate" + desc = "Contains two Energy Guns, capable of firing both nonlethal and lethal blasts of light. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 18 + contains = list(/obj/item/gun/energy/e_gun, + /obj/item/gun/energy/e_gun) + crate_name = "energy gun crate" + crate_type = /obj/structure/closet/crate/secure/plasma +*/ //SKYRAT EDIT END + +/datum/supply_pack/security/armory/exileimp + name = "Exile Implants Crate" + desc = "Contains five Exile implants. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 3.5 + contains = list(/obj/item/storage/box/exileimp) + crate_name = "exile implant crate" + +/datum/supply_pack/security/armory/fire + name = "Incendiary Weapons Crate" + desc = "Burn, baby burn. Contains three incendiary grenades, three plasma canisters, and a flamethrower. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 7 + access = ACCESS_HEADS + contains = list(/obj/item/flamethrower/full, + /obj/item/tank/internals/plasma, + /obj/item/tank/internals/plasma, + /obj/item/tank/internals/plasma, + /obj/item/grenade/chem_grenade/incendiary, + /obj/item/grenade/chem_grenade/incendiary, + /obj/item/grenade/chem_grenade/incendiary) + crate_name = "incendiary weapons crate" + crate_type = /obj/structure/closet/crate/secure/plasma + dangerous = TRUE + +/datum/supply_pack/security/armory/mindshield + name = "Mindshield Implants Crate" + desc = "Prevent against radical thoughts with three Mindshield implants. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/storage/lockbox/loyalty) + crate_name = "mindshield implant crate" + +/datum/supply_pack/security/armory/trackingimp + name = "Tracking Implants Crate" + desc = "Contains four tracking implants and three tracking speedloaders of tracing .38 ammo. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 4.5 + contains = list(/obj/item/storage/box/trackimp, + /obj/item/ammo_box/c38/trac, + /obj/item/ammo_box/c38/trac, + /obj/item/ammo_box/c38/trac) + crate_name = "tracking implant crate" + +/datum/supply_pack/security/armory/riotshotguns //SKYRAT EDIT ADDITION + +/datum/supply_pack/security/armory/laserarmor + name = "Reflector Vest Crate" + desc = "Contains two vests of highly reflective material. Each armor piece diffuses a laser's energy by over half, as well as offering a good chance to reflect the laser entirely. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/suit/armor/laserproof) + crate_name = "reflector vest crate" + crate_type = /obj/structure/closet/crate/secure/plasma + +/datum/supply_pack/security/armory/riotarmor + name = "Riot Armor Crate" + desc = "Contains three sets of heavy body armor. Advanced padding protects against close-ranged weaponry, making melee attacks feel only half as potent to the user. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/clothing/suit/armor/riot, + /obj/item/clothing/suit/armor/riot, + /obj/item/clothing/suit/armor/riot) + crate_name = "riot armor crate" + +/datum/supply_pack/security/armory/riothelmets + name = "Riot Helmets Crate" + desc = "Contains three riot helmets. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/clothing/head/helmet/riot, + /obj/item/clothing/head/helmet/riot, + /obj/item/clothing/head/helmet/riot) + crate_name = "riot helmets crate" + +/datum/supply_pack/security/armory/riotshields + name = "Riot Shields Crate" + desc = "For when the greytide gets really uppity. Contains three riot shields. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/shield/riot, + /obj/item/shield/riot, + /obj/item/shield/riot) + crate_name = "riot shields crate" + +/datum/supply_pack/security/armory/russian + name = "Russian Surplus Crate" + desc = "Hello Comrade, we have the most modern russian military equipment the black market can offer, for the right price of course. Sadly we couldnt remove the lock so it requires Armory access to open." + cost = CARGO_CRATE_VALUE * 12 + contraband = TRUE + contains = list(/obj/item/food/rationpack, + /obj/item/ammo_box/a762, + /obj/item/storage/toolbox/ammo, + /obj/item/storage/toolbox/maint_kit, + /obj/item/clothing/suit/armor/vest/russian, + /obj/item/clothing/head/helmet/rus_helmet, + /obj/item/clothing/shoes/russian, + /obj/item/clothing/gloves/tackler/combat, + /obj/item/clothing/under/syndicate/rus_army, + /obj/item/clothing/under/costume/soviet, + /obj/item/clothing/mask/russian_balaclava, + /obj/item/clothing/head/helmet/rus_ushanka, + /obj/item/clothing/suit/armor/vest/russian_coat, + /obj/item/gun/ballistic/rifle/boltaction, + /obj/item/gun/ballistic/rifle/boltaction) + crate_name = "surplus military crate" + +/datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C) + for(var/i in 1 to 10) + var/item = pick(contains) + new item(C) + +/datum/supply_pack/security/armory/mafia //SKYRAT EDIT ADDITION + +/datum/supply_pack/security/armory/swat + name = "SWAT Crate" + desc = "Contains two fullbody sets of tough, fireproof suits designed in a joint effort by IS-ERI and Nanotrasen. Each set contains a suit, helmet, mask, combat belt, and combat gloves. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 7 + contains = list(/obj/item/clothing/head/helmet/swat/nanotrasen, + /obj/item/clothing/head/helmet/swat/nanotrasen, + /obj/item/clothing/suit/armor/swat, + /obj/item/clothing/suit/armor/swat, + /obj/item/clothing/mask/gas/sechailer/swat, + /obj/item/clothing/mask/gas/sechailer/swat, + /obj/item/storage/belt/military/assault, + /obj/item/storage/belt/military/assault, + /obj/item/clothing/gloves/tackler/combat, + /obj/item/clothing/gloves/tackler/combat) + crate_name = "swat crate" +/* //SKYRAT EDIT START - CARGO ARMAMENTS +/datum/supply_pack/security/armory/thermal + name = "Thermal Pistol Crate" + desc = "Contains a pair of holsters each with two experimental thermal pistols, using nanites as the basis for their ammo. Requires Armory access to open." + cost = CARGO_CRATE_VALUE * 7 + contains = list(/obj/item/storage/belt/holster/thermal, + /obj/item/storage/belt/holster/thermal) + crate_name = "thermal pistol crate" +*/ //SKYRAT EDIT END +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Engineering ///////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/engineering + group = "Engineering" + crate_type = /obj/structure/closet/crate/engineering + +/datum/supply_pack/engineering/shieldgen + name = "Anti-breach Shield Projector Crate" + desc = "Hull breaches again? Say no more with the Nanotrasen Anti-Breach Shield Projector! Uses forcefield technology to keep the air in, and the space out. Contains two shield projectors." + cost = CARGO_CRATE_VALUE * 3 + access_view = ACCESS_ENGINE_EQUIP + contains = list(/obj/machinery/shieldgen, + /obj/machinery/shieldgen) + crate_name = "anti-breach shield projector crate" + +/datum/supply_pack/engineering/ripley + name = "APLU MK-I Crate" + desc = "A do-it-yourself kit for building an ALPU MK-I \"Ripley\", designed for lifting and carrying heavy equipment, and other station tasks. Batteries not included." + cost = CARGO_CRATE_VALUE * 10 + access_view = ACCESS_ROBOTICS + contains = list(/obj/item/mecha_parts/chassis/ripley, + /obj/item/mecha_parts/part/ripley_torso, + /obj/item/mecha_parts/part/ripley_right_arm, + /obj/item/mecha_parts/part/ripley_left_arm, + /obj/item/mecha_parts/part/ripley_right_leg, + /obj/item/mecha_parts/part/ripley_left_leg, + /obj/item/stock_parts/capacitor, + /obj/item/stock_parts/scanning_module, + /obj/item/circuitboard/mecha/ripley/main, + /obj/item/circuitboard/mecha/ripley/peripherals, + /obj/item/mecha_parts/mecha_equipment/drill, + /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) + crate_name= "\improper APLU MK-I kit" + +/datum/supply_pack/engineering/conveyor + name = "Conveyor Assembly Crate" + desc = "Keep production moving along with thirty conveyor belts. Conveyor switch included. If you have any questions, check out the enclosed instruction book." + cost = CARGO_CRATE_VALUE * 3.5 + contains = list(/obj/item/stack/conveyor/thirty, + /obj/item/conveyor_switch_construct, + /obj/item/paper/guides/conveyor) + crate_name = "conveyor assembly crate" + +/datum/supply_pack/engineering/engiequipment + name = "Engineering Gear Crate" + desc = "Gear up with three toolbelts, high-visibility vests, welding helmets, hardhats, and two pairs of meson goggles!" + cost = CARGO_CRATE_VALUE * 4 + access_view = ACCESS_ENGINE + contains = list(/obj/item/storage/belt/utility, + /obj/item/storage/belt/utility, + /obj/item/storage/belt/utility, + /obj/item/clothing/suit/hazardvest, + /obj/item/clothing/suit/hazardvest, + /obj/item/clothing/suit/hazardvest, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/hardhat, + /obj/item/clothing/head/hardhat, + /obj/item/clothing/head/hardhat, + /obj/item/clothing/glasses/meson/engine, + /obj/item/clothing/glasses/meson/engine) + crate_name = "engineering gear crate" + +/datum/supply_pack/engineering/powergamermitts + name = "Insulated Gloves Crate" + desc = "The backbone of modern society. Barely ever ordered for actual engineering. Contains three insulated gloves." + cost = CARGO_CRATE_VALUE * 8 //Made of pure-grade bullshittinium + access_view = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/clothing/gloves/color/yellow, + /obj/item/clothing/gloves/color/yellow, + /obj/item/clothing/gloves/color/yellow) + crate_name = "insulated gloves crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engineering/inducers + name = "NT-75 Electromagnetic Power Inducers Crate" + desc = "No rechargers? No problem, with the NT-75 EPI, you can recharge any standard cell-based equipment anytime, anywhere. Contains two Inducers." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}, /obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}) //FALSE doesn't work in modified type paths apparently. + crate_name = "inducer crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engineering/pacman + name = "P.A.C.M.A.N Generator Crate" + desc = "Engineers can't set up the engine? Not an issue for you, once you get your hands on this P.A.C.M.A.N. Generator! Takes in plasma and spits out sweet sweet energy." + cost = CARGO_CRATE_VALUE * 5 + access_view = ACCESS_ENGINE + contains = list(/obj/machinery/power/port_gen/pacman) + crate_name = "\improper PACMAN generator crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engineering/power + name = "Power Cell Crate" + desc = "Looking for power overwhelming? Look no further. Contains three high-voltage power cells." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/stock_parts/cell/high, + /obj/item/stock_parts/cell/high, + /obj/item/stock_parts/cell/high) + crate_name = "power cell crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engineering/shuttle_engine + name = "Shuttle Engine Crate" + desc = "Through advanced bluespace-shenanigans, our engineers have managed to fit an entire shuttle engine into one tiny little crate. Requires CE access to open." + cost = CARGO_CRATE_VALUE * 6 + access = ACCESS_CE + access_view = ACCESS_CE + contains = list(/obj/structure/shuttle/engine/propulsion/burst/cargo) + crate_name = "shuttle engine crate" + crate_type = /obj/structure/closet/crate/secure/engineering + special = TRUE + +/datum/supply_pack/engineering/tools + name = "Toolbox Crate" + desc = "Any robust spaceman is never far from their trusty toolbox. Contains three electrical toolboxes and three mechanical toolboxes." + access_view = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/storage/toolbox/electrical, + /obj/item/storage/toolbox/electrical, + /obj/item/storage/toolbox/electrical, + /obj/item/storage/toolbox/mechanical, + /obj/item/storage/toolbox/mechanical, + /obj/item/storage/toolbox/mechanical) + cost = CARGO_CRATE_VALUE * 5 + crate_name = "toolbox crate" + +/datum/supply_pack/engineering/portapump + name = "Portable Air Pump Crate" + desc = "Did someone let the air out of the shuttle again? We've got you covered. Contains two portable air pumps." + cost = CARGO_CRATE_VALUE * 4.5 + access_view = ACCESS_ATMOSPHERICS + contains = list(/obj/machinery/portable_atmospherics/pump, + /obj/machinery/portable_atmospherics/pump) + crate_name = "portable air pump crate" + +/datum/supply_pack/engineering/portascrubber + name = "Portable Scrubber Crate" + desc = "Clean up that pesky plasma leak with your very own set of two portable scrubbers." + cost = CARGO_CRATE_VALUE * 4.5 + access_view = ACCESS_ATMOSPHERICS + contains = list(/obj/machinery/portable_atmospherics/scrubber, + /obj/machinery/portable_atmospherics/scrubber) + crate_name = "portable scrubber crate" + +/datum/supply_pack/engineering/hugescrubber + name = "Huge Portable Scrubber Crate" + desc = "A huge portable scrubber for huge atmospherics mistakes." + cost = CARGO_CRATE_VALUE * 7.5 + access_view = ACCESS_ATMOSPHERICS + contains = list(/obj/machinery/portable_atmospherics/scrubber/huge/movable/cargo) + crate_name = "huge portable scrubber crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/engineering/space_heater + name = "Space Heater Crate" + desc = "A dual purpose heater/cooler for when things are too chilly/toasty." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/machinery/space_heater) + crate_name = "space heater crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/engineering/bsa + name = "Bluespace Artillery Parts" + desc = "The pride of Nanotrasen Naval Command. The legendary Bluespace Artillery Cannon is a devastating feat of human engineering and testament to wartime determination. Highly advanced research is required for proper construction. " + cost = CARGO_CRATE_VALUE * 30 + special = TRUE + access_view = ACCESS_HEADS + contains = list(/obj/item/circuitboard/machine/bsa/front, + /obj/item/circuitboard/machine/bsa/middle, + /obj/item/circuitboard/machine/bsa/back, + /obj/item/circuitboard/machine/bsa/powercore, //SKYRAT EDIT ADDITION + /obj/item/circuitboard/computer/bsa_control + ) + crate_name= "bluespace artillery parts crate" + +/datum/supply_pack/engineering/dna_vault + name = "DNA Vault Parts" + desc = "Secure the longevity of the current state of humanity within this massive library of scientific knowledge, capable of granting superhuman powers and abilities. Highly advanced research is required for proper construction. Also contains five DNA probes." + cost = CARGO_CRATE_VALUE * 24 + special = TRUE + access_view = ACCESS_HEADS + contains = list( + /obj/item/circuitboard/machine/dna_vault, + /obj/item/dna_probe, + /obj/item/dna_probe, + /obj/item/dna_probe, + /obj/item/dna_probe, + /obj/item/dna_probe + ) + crate_name= "dna vault parts crate" + +/datum/supply_pack/engineering/dna_probes + name = "DNA Vault Samplers" + desc = "Contains five DNA probes for use in the DNA vault." + cost = CARGO_CRATE_VALUE * 6 + special = TRUE + access_view = ACCESS_HEADS + contains = list(/obj/item/dna_probe, + /obj/item/dna_probe, + /obj/item/dna_probe, + /obj/item/dna_probe, + /obj/item/dna_probe + ) + crate_name= "dna samplers crate" + + +/datum/supply_pack/engineering/shield_sat + name = "Shield Generator Satellite" + desc = "Protect the very existence of this station with these Anti-Meteor defenses. Contains three Shield Generator Satellites." + cost = CARGO_CRATE_VALUE * 6 + special = TRUE + access_view = ACCESS_HEADS + contains = list( + /obj/machinery/satellite/meteor_shield, + /obj/machinery/satellite/meteor_shield, + /obj/machinery/satellite/meteor_shield + ) + crate_name= "shield sat crate" + + +/datum/supply_pack/engineering/shield_sat_control + name = "Shield System Control Board" + desc = "A control system for the Shield Generator Satellite system." + cost = CARGO_CRATE_VALUE * 10 + special = TRUE + access_view = ACCESS_HEADS + contains = list(/obj/item/circuitboard/computer/sat_control) + crate_name= "shield control board crate" + + +////////////////////////////////////////////////////////////////////////////// +//////////////////////// Engine Construction ///////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/engine + group = "Engine Construction" + access_view = ACCESS_ENGINE + crate_type = /obj/structure/closet/crate/engineering + +/datum/supply_pack/engine/emitter + name = "Emitter Crate" + desc = "Useful for powering forcefield generators while destroying locked crates and intruders alike. Contains two high-powered energy emitters. Requires CE access to open." + cost = CARGO_CRATE_VALUE * 7 + access = ACCESS_CE + contains = list(/obj/machinery/power/emitter, + /obj/machinery/power/emitter) + crate_name = "emitter crate" + crate_type = /obj/structure/closet/crate/secure/engineering + dangerous = TRUE + +/datum/supply_pack/engine/field_gen + name = "Field Generator Crate" + desc = "Typically the only thing standing between the station and a messy death. Powered by emitters. Contains two field generators." + cost = CARGO_CRATE_VALUE * 7 + contains = list(/obj/machinery/field/generator, + /obj/machinery/field/generator) + crate_name = "field generator crate" + +/datum/supply_pack/engine/grounding_rods + name = "Grounding Rod Crate" + desc = "Four grounding rods guaranteed to keep any uppity tesla coil's lightning under control." + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/machinery/power/energy_accumulator/grounding_rod, + /obj/machinery/power/energy_accumulator/grounding_rod, + /obj/machinery/power/energy_accumulator/grounding_rod, + /obj/machinery/power/energy_accumulator/grounding_rod) + crate_name = "grounding rod crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engine/solar + name = "Solar Panel Crate" + desc = "Go green with this DIY advanced solar array. Contains twenty one solar assemblies, a solar-control circuit board, and tracker. If you have any questions, please check out the enclosed instruction book." + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/circuitboard/computer/solar_control, + /obj/item/electronics/tracker, + /obj/item/paper/guides/jobs/engi/solars) + crate_name = "solar panel crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engine/supermatter_shard + name = "Supermatter Shard Crate" + desc = "The power of the heavens condensed into a single crystal. Requires CE access to open." + cost = CARGO_CRATE_VALUE * 20 + access = ACCESS_CE + contains = list(/obj/machinery/power/supermatter_crystal/shard) + crate_name = "supermatter shard crate" + crate_type = /obj/structure/closet/crate/secure/engineering + dangerous = TRUE + +/datum/supply_pack/engine/tesla_coils + name = "Tesla Coil Crate" + desc = "Whether it's high-voltage executions, creating research points, or just plain old assistant electrofrying: This pack of four Tesla coils can do it all!" + cost = CARGO_CRATE_VALUE * 10 + contains = list(/obj/machinery/power/energy_accumulator/tesla_coil, + /obj/machinery/power/energy_accumulator/tesla_coil, + /obj/machinery/power/energy_accumulator/tesla_coil, + /obj/machinery/power/energy_accumulator/tesla_coil) + crate_name = "tesla coil crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +/datum/supply_pack/engine/hypertorus_fusion_reactor + name = "HFR Crate" + desc = "The new and improved fusion reactor. Requires CE access to open." + cost = CARGO_CRATE_VALUE * 23 + access = ACCESS_CE + contains = list(/obj/item/hfr_box/corner, + /obj/item/hfr_box/corner, + /obj/item/hfr_box/corner, + /obj/item/hfr_box/corner, + /obj/item/hfr_box/body/fuel_input, + /obj/item/hfr_box/body/moderator_input, + /obj/item/hfr_box/body/waste_output, + /obj/item/hfr_box/body/interface, + /obj/item/hfr_box/core) + crate_name = "HFR crate" + crate_type = /obj/structure/closet/crate/secure/engineering + dangerous = TRUE + +////////////////////////////////////////////////////////////////////////////// +/////////////////////// Canisters & Materials //////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/materials + group = "Canisters & Materials" + +/datum/supply_pack/materials/cardboard50 + name = "50 Cardboard Sheets" + desc = "Create a bunch of boxes." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/stack/sheet/cardboard/fifty) + crate_name = "cardboard sheets crate" + +/datum/supply_pack/materials/license50 + name = "50 Empty License Plates" + desc = "Create a bunch of boxes." + cost = CARGO_CRATE_VALUE * 2 // 50 * 25 + 700 - 1000 = 950 credits profit + access_view = ACCESS_BRIG_ENTRANCE + contains = list(/obj/item/stack/license_plates/empty/fifty) + crate_name = "empty license plate crate" + +/datum/supply_pack/materials/glass50 + name = "50 Glass Sheets" + desc = "Let some nice light in with fifty glass sheets!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/stack/sheet/glass/fifty) + crate_name = "glass sheets crate" + +/datum/supply_pack/materials/iron50 + name = "50 Iron Sheets" + desc = "Any construction project begins with a good stack of fifty iron sheets!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/stack/sheet/iron/fifty) + crate_name = "iron sheets crate" + +/datum/supply_pack/materials/plasteel20 + name = "20 Plasteel Sheets" + desc = "Reinforce the station's integrity with twenty plasteel sheets!" + cost = CARGO_CRATE_VALUE * 15 + contains = list(/obj/item/stack/sheet/plasteel/twenty) + crate_name = "plasteel sheets crate" + +/datum/supply_pack/materials/plasteel50 + name = "50 Plasteel Sheets" + desc = "For when you REALLY have to reinforce something." + cost = CARGO_CRATE_VALUE * 33 + contains = list(/obj/item/stack/sheet/plasteel/fifty) + crate_name = "plasteel sheets crate" + +/datum/supply_pack/materials/plastic50 + name = "50 Plastic Sheets" + desc = "Build a limitless amount of toys with fifty plastic sheets!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/stack/sheet/plastic/fifty) + crate_name = "plastic sheets crate" + +/datum/supply_pack/materials/sandstone30 + name = "30 Sandstone Blocks" + desc = "Neither sandy nor stoney, these thirty blocks will still get the job done." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/stack/sheet/mineral/sandstone/thirty) + crate_name = "sandstone blocks crate" + +/datum/supply_pack/materials/wood50 + name = "50 Wood Planks" + desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!" + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/stack/sheet/mineral/wood/fifty) + crate_name = "wood planks crate" + +/datum/supply_pack/materials/foamtank + name = "Firefighting Foam Tank Crate" + desc = "Contains a tank of firefighting foam. Also known as \"plasmaman's bane\"." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/structure/reagent_dispensers/foamtank) + crate_name = "foam tank crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/materials/fueltank + name = "Fuel Tank Crate" + desc = "Contains a welding fuel tank. Caution, highly flammable." + cost = CARGO_CRATE_VALUE * 1.6 + contains = list(/obj/structure/reagent_dispensers/fueltank) + crate_name = "fuel tank crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/materials/hightank + name = "Large Water Tank Crate" + desc = "Contains a high-capacity water tank. Useful for botany or other service jobs." + cost = CARGO_CRATE_VALUE * 2.4 + contains = list(/obj/structure/reagent_dispensers/watertank/high) + crate_name = "high-capacity water tank crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/materials/hightankfuel + name = "Large Fuel Tank Crate" + desc = "Contains a high-capacity fuel tank. Keep contents away from open flame." + cost = CARGO_CRATE_VALUE * 4 + access_view = ACCESS_ENGINE + contains = list(/obj/structure/reagent_dispensers/fueltank/large) + crate_name = "high-capacity fuel tank crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/materials/watertank + name = "Water Tank Crate" + desc = "Contains a tank of dihydrogen monoxide... sounds dangerous." + cost = CARGO_CRATE_VALUE * 1.2 + contains = list(/obj/structure/reagent_dispensers/watertank) + crate_name = "water tank crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/materials/gas_canisters + cost = CARGO_CRATE_VALUE * 0.05 + contains = list(/obj/machinery/portable_atmospherics/canister) + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/materials/gas_canisters/generate_supply_packs() + var/list/canister_packs = list() + + var/obj/machinery/portable_atmospherics/canister/fakeCanister = /obj/machinery/portable_atmospherics/canister + // This is the amount of moles in a default canister + var/moleCount = (initial(fakeCanister.maximum_pressure) * initial(fakeCanister.filled)) * initial(fakeCanister.volume) / (R_IDEAL_GAS_EQUATION * T20C) + + for(var/gasType in GLOB.meta_gas_info) + var/datum/gas/gas = gasType + var/name = initial(gas.name) + if(!initial(gas.purchaseable)) + continue + var/datum/supply_pack/materials/pack = new + pack.name = "[name] Canister" + pack.desc = "Contains a canister of [name]." + if(initial(gas.dangerous)) + pack.desc = "[pack.desc] Requires Atmospherics access to open." + pack.access = ACCESS_ATMOSPHERICS + pack.access_view = ACCESS_ATMOSPHERICS + pack.crate_name = "[name] canister crate" + pack.id = "[type]([name])" + + pack.cost = cost + moleCount * initial(gas.base_value) * 1.6 + pack.cost = CEILING(pack.cost, 10) + + pack.contains = list(GLOB.gas_id_to_canister[initial(gas.id)]) + + pack.crate_type = crate_type + + canister_packs += pack + + return canister_packs + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Medical ///////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/medical + group = "Medical" + access_view = ACCESS_MEDICAL + crate_type = /obj/structure/closet/crate/medical + +/datum/supply_pack/medical/bloodpacks + name = "Blood Pack Variety Crate" + desc = "Contains ten different blood packs for reintroducing blood to patients." + cost = CARGO_CRATE_VALUE * 7 + contains = list(/obj/item/reagent_containers/blood, + /obj/item/reagent_containers/blood, + /obj/item/reagent_containers/blood/a_plus, + /obj/item/reagent_containers/blood/a_minus, + /obj/item/reagent_containers/blood/b_plus, + /obj/item/reagent_containers/blood/b_minus, + /obj/item/reagent_containers/blood/o_plus, + /obj/item/reagent_containers/blood/o_minus, + /obj/item/reagent_containers/blood/lizard, + /obj/item/reagent_containers/blood/ethereal) + crate_name = "blood freezer" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/medical/medipen_variety + name = "Medipen Variety-Pak" + desc = "Contains eight different medipens in three different varieties, to assist in quickly treating seriously injured patients." + cost = CARGO_CRATE_VALUE * 3.5 + contains = list(/obj/item/reagent_containers/hypospray/medipen/, + /obj/item/reagent_containers/hypospray/medipen/, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/blood_loss, + /obj/item/reagent_containers/hypospray/medipen/blood_loss, + /obj/item/reagent_containers/hypospray/medipen/blood_loss +) + crate_name = "medipen crate" + +/datum/supply_pack/medical/chemical + name = "Chemical Starter Kit Crate" + desc = "Contains thirteen different chemicals, for all the fun experiments you can make." + cost = CARGO_CRATE_VALUE * 2.6 + contains = list(/obj/item/reagent_containers/glass/bottle/hydrogen, + /obj/item/reagent_containers/glass/bottle/carbon, + /obj/item/reagent_containers/glass/bottle/nitrogen, + /obj/item/reagent_containers/glass/bottle/oxygen, + /obj/item/reagent_containers/glass/bottle/fluorine, + /obj/item/reagent_containers/glass/bottle/phosphorus, + /obj/item/reagent_containers/glass/bottle/silicon, + /obj/item/reagent_containers/glass/bottle/chlorine, + /obj/item/reagent_containers/glass/bottle/radium, + /obj/item/reagent_containers/glass/bottle/sacid, + /obj/item/reagent_containers/glass/bottle/ethanol, + /obj/item/reagent_containers/glass/bottle/potassium, + /obj/item/reagent_containers/glass/bottle/sugar, + /obj/item/clothing/glasses/science, + /obj/item/reagent_containers/dropper, + /obj/item/storage/box/beakers) + crate_name = "chemical crate" + +/datum/supply_pack/medical/defibs + name = "Defibrillator Crate" + desc = "Contains two defibrillators for bringing the recently deceased back to life." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/defibrillator/loaded, + /obj/item/defibrillator/loaded) + crate_name = "defibrillator crate" + +/datum/supply_pack/medical/iv_drip + name = "IV Drip Crate" + desc = "Contains a single IV drip for administering blood to patients." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/machinery/iv_drip) + crate_name = "iv drip crate" + +/datum/supply_pack/medical/supplies + name = "Medical Supplies Crate" + desc = "Contains several medical supplies. German doctor not included." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/reagent_containers/glass/bottle/multiver, + /obj/item/reagent_containers/glass/bottle/epinephrine, + /obj/item/reagent_containers/glass/bottle/morphine, + /obj/item/reagent_containers/glass/bottle/toxin, + /obj/item/reagent_containers/glass/beaker/large, + /obj/item/reagent_containers/pill/insulin, + /obj/item/stack/medical/gauze, + /obj/item/storage/box/beakers, + /obj/item/storage/box/medigels, + /obj/item/storage/box/syringes, + /obj/item/storage/box/bodybags, + /obj/item/storage/medkit/regular, + /obj/item/storage/medkit/o2, + /obj/item/storage/medkit/toxin, + /obj/item/storage/medkit/brute, + /obj/item/storage/medkit/fire, + /obj/item/defibrillator/loaded, + /obj/item/reagent_containers/blood/o_minus, + /obj/item/storage/pill_bottle/mining, + /obj/item/reagent_containers/pill/neurine, + /obj/item/stack/medical/bone_gel/four, + /obj/item/stack/medical/bone_gel/four, + /obj/item/vending_refill/medical, + /obj/item/vending_refill/drugs) + crate_name = "medical supplies crate" + +/datum/supply_pack/medical/supplies/fill(obj/structure/closet/crate/C) + for(var/i in 1 to 10) + var/item = pick(contains) + new item(C) + +/datum/supply_pack/medical/surgery + name = "Surgical Supplies Crate" + desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/storage/backpack/duffelbag/med/surgery, + /obj/item/reagent_containers/medigel/sterilizine, + /obj/item/roller) + crate_name = "surgical supplies crate" + +/datum/supply_pack/medical/salglucanister + name = "Heavy-Duty Saline Canister" + desc = "Contains a bulk supply of saline-glucose condensed into a single canister that should last several days, with a large pump to fill containers with. Direct injection of saline should be left to medical professionals as the pump is capable of overdosing patients. Requires medbay access to open." + cost = CARGO_CRATE_VALUE * 6 + access = ACCESS_MEDICAL + contains = list(/obj/machinery/iv_drip/saline) + +/datum/supply_pack/medical/virus + name = "Virus Crate" + desc = "Contains twelve different bottles, containing several viral samples for virology research. Also includes seven beakers and syringes. Balled-up jeans not included. Requires CMO access to open." + cost = CARGO_CRATE_VALUE * 5 + access = ACCESS_CMO + access_view = ACCESS_VIROLOGY + contains = list(/obj/item/reagent_containers/glass/bottle/flu_virion, + /obj/item/reagent_containers/glass/bottle/cold, + /obj/item/reagent_containers/glass/bottle/random_virus, + /obj/item/reagent_containers/glass/bottle/random_virus, + /obj/item/reagent_containers/glass/bottle/random_virus, + /obj/item/reagent_containers/glass/bottle/random_virus, + /obj/item/reagent_containers/glass/bottle/fake_gbs, + /obj/item/reagent_containers/glass/bottle/magnitis, + /obj/item/reagent_containers/glass/bottle/pierrot_throat, + /obj/item/reagent_containers/glass/bottle/brainrot, + /obj/item/reagent_containers/glass/bottle/anxiety, + /obj/item/reagent_containers/glass/bottle/beesease, + /obj/item/storage/box/syringes, + /obj/item/storage/box/beakers, + /obj/item/reagent_containers/glass/bottle/mutagen) + crate_name = "virus crate" + crate_type = /obj/structure/closet/crate/secure/plasma + dangerous = TRUE + +/datum/supply_pack/medical/cmoturtlenecks + name = "Chief Medical Officer Turtlenecks" + desc = "Contains the CMO's turtleneck and turtleneck skirt. Requires CMO access to open." + cost = CARGO_CRATE_VALUE * 2 + access = ACCESS_CMO + contains = list(/obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck, + /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck/skirt) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Science ///////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/science + group = "Science" + access_view = ACCESS_RESEARCH + crate_type = /obj/structure/closet/crate/science + +/datum/supply_pack/science/plasma + name = "Plasma Assembly Crate" + desc = "Everything you need to burn something to the ground, this contains three plasma assembly sets. Each set contains a plasma tank, igniter, proximity sensor, and timer! Warranty void if exposed to high temperatures. Requires Ordnance access to open." + cost = CARGO_CRATE_VALUE * 2 + access = ACCESS_ORDNANCE + access_view = ACCESS_ORDNANCE + contains = list(/obj/item/tank/internals/plasma, + /obj/item/tank/internals/plasma, + /obj/item/tank/internals/plasma, + /obj/item/assembly/igniter, + /obj/item/assembly/igniter, + /obj/item/assembly/igniter, + /obj/item/assembly/prox_sensor, + /obj/item/assembly/prox_sensor, + /obj/item/assembly/prox_sensor, + /obj/item/assembly/timer, + /obj/item/assembly/timer, + /obj/item/assembly/timer) + crate_name = "plasma assembly crate" + crate_type = /obj/structure/closet/crate/secure/plasma + +/datum/supply_pack/science/raw_flux_anomaly + name = "Raw Flux Anomaly" + desc = "The raw core of a flux anomaly, ready to be implosion-compressed into a powerful artifact." + cost = CARGO_CRATE_VALUE * 10 + access = ACCESS_ORDNANCE + access_view = ACCESS_ORDNANCE + contains = list(/obj/item/raw_anomaly_core/flux) + crate_name = "raw flux anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_grav_anomaly + name = "Raw Gravitational Anomaly" + desc = "The raw core of a gravitational anomaly, ready to be implosion-compressed into a powerful artifact." + cost = CARGO_CRATE_VALUE * 10 + access = ACCESS_ORDNANCE + access_view = ACCESS_ORDNANCE + contains = list(/obj/item/raw_anomaly_core/grav) + crate_name = "raw gravitational anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_vortex_anomaly + name = "Raw Vortex Anomaly" + desc = "The raw core of a vortex anomaly, ready to be implosion-compressed into a powerful artifact." + cost = CARGO_CRATE_VALUE * 10 + access = ACCESS_ORDNANCE + access_view = ACCESS_ORDNANCE + contains = list(/obj/item/raw_anomaly_core/vortex) + crate_name = "raw vortex anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_bluespace_anomaly + name = "Raw Bluespace Anomaly" + desc = "The raw core of a bluespace anomaly, ready to be implosion-compressed into a powerful artifact." + cost = CARGO_CRATE_VALUE * 10 + access = ACCESS_ORDNANCE + access_view = ACCESS_ORDNANCE + contains = list(/obj/item/raw_anomaly_core/bluespace) + crate_name = "raw bluespace anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_pyro_anomaly + name = "Raw Pyro Anomaly" + desc = "The raw core of a pyro anomaly, ready to be implosion-compressed into a powerful artifact." + cost = CARGO_CRATE_VALUE * 10 + access = ACCESS_ORDNANCE + access_view = ACCESS_ORDNANCE + contains = list(/obj/item/raw_anomaly_core/pyro) + crate_name = "raw pyro anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/robotics + name = "Robotics Assembly Crate" + desc = "The tools you need to replace those finicky humans with a loyal robot army! Contains four proximity sensors, two empty first aid kits, two health analyzers, two red hardhats, two mechanical toolboxes, and two cleanbot assemblies! Requires Robotics access to open." + cost = CARGO_CRATE_VALUE * 3 + access = ACCESS_ROBOTICS + access_view = ACCESS_ROBOTICS + contains = list(/obj/item/assembly/prox_sensor, + /obj/item/assembly/prox_sensor, + /obj/item/assembly/prox_sensor, + /obj/item/assembly/prox_sensor, + /obj/item/storage/medkit, + /obj/item/storage/medkit, + /obj/item/healthanalyzer, + /obj/item/healthanalyzer, + /obj/item/clothing/head/hardhat/red, + /obj/item/clothing/head/hardhat/red, + /obj/item/storage/toolbox/mechanical, + /obj/item/storage/toolbox/mechanical, + /obj/item/bot_assembly/cleanbot, + /obj/item/bot_assembly/cleanbot) + crate_name = "robotics assembly crate" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/rped + name = "RPED crate" + desc = "Need to rebuild the ORM but science got annihialted after a bomb test? Buy this for the most advanced parts NT can give you." + cost = CARGO_CRATE_VALUE * 3 + access_view = FALSE + contains = list(/obj/item/storage/part_replacer/cargo) + crate_name = "\improper RPED crate" + +/datum/supply_pack/science/shieldwalls + name = "Shield Generator Crate" + desc = "These high powered Shield Wall Generators are guaranteed to keep any unwanted lifeforms on the outside, where they belong! Contains four shield wall generators. Requires Teleporter access to open." + cost = CARGO_CRATE_VALUE * 4 + access = ACCESS_TELEPORTER + access_view = ACCESS_TELEPORTER + contains = list(/obj/machinery/power/shieldwallgen, + /obj/machinery/power/shieldwallgen, + /obj/machinery/power/shieldwallgen, + /obj/machinery/power/shieldwallgen) + crate_name = "shield generators crate" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/techshellpack //SKYRAT EDIT ADDITION + +/datum/supply_pack/science/transfer_valves + name = "Tank Transfer Valves Crate" + desc = "The key ingredient for making a lot of people very angry very fast. Contains two tank transfer valves. Requires RD access to open." + cost = CARGO_CRATE_VALUE * 12 + access = ACCESS_RD + contains = list(/obj/item/transfer_valve, + /obj/item/transfer_valve) + crate_name = "tank transfer valves crate" + crate_type = /obj/structure/closet/crate/secure/science + dangerous = TRUE + +/datum/supply_pack/science/monkey_helmets + name = "Monkey Mind Magnification Helmet crate" + desc = "Some research is best done with monkeys, yet sometimes they're just too dumb to complete more complicated tasks. These helmets should help." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/clothing/head/helmet/monkey_sentience, + /obj/item/clothing/head/helmet/monkey_sentience) + crate_name = "monkey mind magnification crate" + +/datum/supply_pack/science/cytology + name = "Cytology supplies crate" + desc = "Did out of control specimens pulverize xenobiology? Here is some more supplies for further testing." + cost = CARGO_CRATE_VALUE * 3 + access_view = ACCESS_XENOBIOLOGY + contains = list(/obj/structure/microscope, + /obj/item/biopsy_tool, + /obj/item/storage/box/petridish, + /obj/item/storage/box/petridish, + /obj/item/storage/box/swab, + /obj/item/construction/plumbing/research) + crate_name = "cytology supplies crate" + +/datum/supply_pack/science/mod_core + name = "MOD core Crate" + desc = "Three cores, perfect for any MODsuit construction! Naturally harvested™, of course." + cost = CARGO_CRATE_VALUE * 3 + access = ACCESS_ROBOTICS + access_view = ACCESS_ROBOTICS + contains = list(/obj/item/mod/core/standard, + /obj/item/mod/core/standard, + /obj/item/mod/core/standard) + crate_name = "\improper MOD core crate" + crate_type = /obj/structure/closet/crate/secure/science + +////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// Service ////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/service + group = "Service" + +/datum/supply_pack/service/cargo_supples + name = "Cargo Supplies Crate" + desc = "Sold everything that wasn't bolted down? You can get right back to work with this crate containing stamps, an export scanner, destination tagger, hand labeler and some package wrapping." + cost = CARGO_CRATE_VALUE * 1.75 + contains = list(/obj/item/stamp, + /obj/item/stamp/denied, + /obj/item/export_scanner, + /obj/item/dest_tagger, + /obj/item/hand_labeler, + /obj/item/stack/package_wrap) + crate_name = "cargo supplies crate" + +/datum/supply_pack/service/noslipfloor + name = "High-traction Floor Tiles" + desc = "Make slipping a thing of the past with thirty industrial-grade anti-slip floor tiles!" + cost = CARGO_CRATE_VALUE * 4 + access_view = ACCESS_JANITOR + contains = list(/obj/item/stack/tile/noslip/thirty) + crate_name = "high-traction floor tiles crate" + +/datum/supply_pack/service/janitor + name = "Janitorial Supplies Crate" + desc = "Fight back against dirt and grime with Nanotrasen's Janitorial Essentials(tm)! Contains three buckets, caution signs, and cleaner grenades. Also has a single mop, broom, spray cleaner, rag, and trash bag." + cost = CARGO_CRATE_VALUE * 2 + access_view = ACCESS_JANITOR + contains = list(/obj/item/reagent_containers/glass/bucket, + /obj/item/reagent_containers/glass/bucket, + /obj/item/reagent_containers/glass/bucket, + /obj/item/mop, + /obj/item/pushbroom, + /obj/item/clothing/suit/caution, + /obj/item/clothing/suit/caution, + /obj/item/clothing/suit/caution, + /obj/item/storage/bag/trash, + /obj/item/reagent_containers/spray/cleaner, + /obj/item/reagent_containers/glass/rag, + /obj/item/grenade/chem_grenade/cleaner, + /obj/item/grenade/chem_grenade/cleaner, + /obj/item/grenade/chem_grenade/cleaner) + crate_name = "janitorial supplies crate" + +/datum/supply_pack/service/janitor/janicart + name = "Janitorial Cart and Galoshes Crate" + desc = "The keystone to any successful janitor. As long as you have feet, this pair of galoshes will keep them firmly planted on the ground. Also contains a janitorial cart." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/structure/janitorialcart, + /obj/item/clothing/shoes/galoshes) + crate_name = "janitorial cart crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/service/janitor/janitank + name = "Janitor Backpack Crate" + desc = "Call forth divine judgement upon dirt and grime with this high capacity janitor backpack. Contains 500 units of station-cleansing cleaner. Requires janitor access to open." + cost = CARGO_CRATE_VALUE * 2 + access = ACCESS_JANITOR + contains = list(/obj/item/watertank/janitor) + crate_name = "janitor backpack crate" + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/service/mule + name = "MULEbot Crate" + desc = "Pink-haired Quartermaster not doing her job? Replace her with this tireless worker, today!" + cost = CARGO_CRATE_VALUE * 4 + contains = list(/mob/living/simple_animal/bot/mulebot) + crate_name = "\improper MULEbot Crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/service/party + name = "Party Equipment" + desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, six beers, six sodas, two ales, and a bottle of patron, goldschlager, and shaker!" + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/storage/box/drinkingglasses, + /obj/item/reagent_containers/food/drinks/shaker, + /obj/item/reagent_containers/food/drinks/bottle/patron, + /obj/item/reagent_containers/food/drinks/bottle/goldschlager, + /obj/item/reagent_containers/food/drinks/bottle/ale, + /obj/item/reagent_containers/food/drinks/bottle/ale, + /obj/item/storage/cans/sixbeer, + /obj/item/storage/cans/sixsoda, + /obj/item/flashlight/glowstick, + /obj/item/flashlight/glowstick/red, + /obj/item/flashlight/glowstick/blue, + /obj/item/flashlight/glowstick/cyan, + /obj/item/flashlight/glowstick/orange, + /obj/item/flashlight/glowstick/yellow, + /obj/item/flashlight/glowstick/pink) + crate_name = "party equipment crate" + +/datum/supply_pack/service/carpet + name = "Premium Carpet Crate" + desc = "Iron floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/stack/tile/carpet/fifty, + /obj/item/stack/tile/carpet/fifty, + /obj/item/stack/tile/carpet/black/fifty, + /obj/item/stack/tile/carpet/black/fifty) + crate_name = "premium carpet crate" + +/datum/supply_pack/service/carpet_exotic + name = "Exotic Carpet Crate" + desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 8 different flooring patterns." + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/item/stack/tile/carpet/blue/fifty, + /obj/item/stack/tile/carpet/blue/fifty, + /obj/item/stack/tile/carpet/cyan/fifty, + /obj/item/stack/tile/carpet/cyan/fifty, + /obj/item/stack/tile/carpet/green/fifty, + /obj/item/stack/tile/carpet/green/fifty, + /obj/item/stack/tile/carpet/orange/fifty, + /obj/item/stack/tile/carpet/orange/fifty, + /obj/item/stack/tile/carpet/purple/fifty, + /obj/item/stack/tile/carpet/purple/fifty, + /obj/item/stack/tile/carpet/red/fifty, + /obj/item/stack/tile/carpet/red/fifty, + /obj/item/stack/tile/carpet/royalblue/fifty, + /obj/item/stack/tile/carpet/royalblue/fifty, + /obj/item/stack/tile/carpet/royalblack/fifty, + /obj/item/stack/tile/carpet/royalblack/fifty) + crate_name = "exotic carpet crate" + +/datum/supply_pack/service/carpet_neon + name = "Simple Neon Carpet Crate" + desc = "Simple rubbery mats with phosphorescent lining. Contains 120 tiles each of 13 color variants. Limited edition release." + cost = CARGO_CRATE_VALUE * 15 + contains = list( + /obj/item/stack/tile/carpet/neon/simple/white/sixty, + /obj/item/stack/tile/carpet/neon/simple/white/sixty, + /obj/item/stack/tile/carpet/neon/simple/black/sixty, + /obj/item/stack/tile/carpet/neon/simple/black/sixty, + /obj/item/stack/tile/carpet/neon/simple/red/sixty, + /obj/item/stack/tile/carpet/neon/simple/red/sixty, + /obj/item/stack/tile/carpet/neon/simple/orange/sixty, + /obj/item/stack/tile/carpet/neon/simple/orange/sixty, + /obj/item/stack/tile/carpet/neon/simple/yellow/sixty, + /obj/item/stack/tile/carpet/neon/simple/yellow/sixty, + /obj/item/stack/tile/carpet/neon/simple/lime/sixty, + /obj/item/stack/tile/carpet/neon/simple/lime/sixty, + /obj/item/stack/tile/carpet/neon/simple/green/sixty, + /obj/item/stack/tile/carpet/neon/simple/green/sixty, + /obj/item/stack/tile/carpet/neon/simple/teal/sixty, + /obj/item/stack/tile/carpet/neon/simple/teal/sixty, + /obj/item/stack/tile/carpet/neon/simple/cyan/sixty, + /obj/item/stack/tile/carpet/neon/simple/cyan/sixty, + /obj/item/stack/tile/carpet/neon/simple/blue/sixty, + /obj/item/stack/tile/carpet/neon/simple/blue/sixty, + /obj/item/stack/tile/carpet/neon/simple/purple/sixty, + /obj/item/stack/tile/carpet/neon/simple/purple/sixty, + /obj/item/stack/tile/carpet/neon/simple/violet/sixty, + /obj/item/stack/tile/carpet/neon/simple/violet/sixty, + /obj/item/stack/tile/carpet/neon/simple/pink/sixty, + /obj/item/stack/tile/carpet/neon/simple/pink/sixty, + ) + crate_name = "neon carpet crate" + +/datum/supply_pack/service/lightbulbs + name = "Replacement Lights" + desc = "May the light of Aether shine upon this station! Or at least, the light of forty two light tubes and twenty one light bulbs." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/box/lights/mixed, + /obj/item/storage/box/lights/mixed, + /obj/item/storage/box/lights/mixed) + crate_name = "replacement lights" + +/datum/supply_pack/service/minerkit + name = "Shaft Miner Starter Kit" + desc = "All the miners died too fast? Assistant wants to get a taste of life off-station? Either way, this kit is the best way to turn a regular crewman into an ore-producing, monster-slaying machine. Contains meson goggles, a pickaxe, advanced mining scanner, cargo headset, ore bag, gasmask, an explorer suit and a miner ID upgrade. Requires QM access to open." + cost = CARGO_CRATE_VALUE * 4 + access = ACCESS_QM + access_view = ACCESS_MINING_STATION + contains = list(/obj/item/storage/backpack/duffelbag/mining_conscript) + crate_name = "shaft miner starter kit" + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/service/survivalknives + name = "Survival Knives Crate" + desc = "Contains three sharpened survival knives. Each knife guaranteed to fit snugly inside any Nanotrasen-standard boot." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/knife/combat/survival, + /obj/item/knife/combat/survival, + /obj/item/knife/combat/survival) + crate_name = "survival knife crate" + +/datum/supply_pack/service/wedding + name = "Wedding Crate" + desc = "Everything you need to host a wedding! Now you just need an officiant." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/clothing/under/dress/wedding_dress, + /obj/item/clothing/under/suit/tuxedo, + /obj/item/storage/belt/cummerbund, + /obj/item/clothing/head/weddingveil, + /obj/item/bouquet, + /obj/item/bouquet/sunflower, + /obj/item/bouquet/poppy, + /obj/item/reagent_containers/food/drinks/bottle/champagne) + crate_name = "wedding crate" + +/// Box of 7 grey IDs. +/datum/supply_pack/service/greyidbox + name = "Grey ID Card Multipack Cate" + desc = "A convenient crate containing a box of cheap ID cards in a handy wallet-sized form factor. Cards come in every colour you can imagne, as long as it's grey." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/storage/box/ids) + crate_name = "basic id card crate" + +/// Single silver ID. +/datum/supply_pack/service/silverid + name = "Silver ID Card Crate" + desc = "Did we forget to hire any Heads of Staff? Recruit your own with this high value ID card capable of holding advanced levels of access in a handy wallet-sized form factor" + cost = CARGO_CRATE_VALUE * 7 + contains = list(/obj/item/card/id/advanced/silver) + crate_name = "silver id card crate" + +/datum/supply_pack/service/emptycrate + name = "Empty Crate" + desc = "It's an empty crate, for all your storage needs." + cost = CARGO_CRATE_VALUE * 1.4 //Net Zero Profit. + contains = list() + crate_name = "crate" + +/datum/supply_pack/service/randomized/donkpockets + name = "Donk Pocket Variety Crate" + desc = "Featuring a line up of Donk Co.'s most popular pastry!" + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/storage/box/donkpockets/donkpocketspicy, + /obj/item/storage/box/donkpockets/donkpocketteriyaki, + /obj/item/storage/box/donkpockets/donkpocketpizza, + /obj/item/storage/box/donkpockets/donkpocketberry, + /obj/item/storage/box/donkpockets/donkpockethonk) + crate_name = "donk pocket crate" + +/datum/supply_pack/service/randomized/donkpockets/fill(obj/structure/closet/crate/C) + for(var/i in 1 to 3) + var/item = pick(contains) + new item(C) + +/datum/supply_pack/service/randomized/ready_donk + name = "Ready-Donk Variety Crate" + desc = "Featuring a line up of Donk Co.'s most popular pastry!" + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/food/ready_donk, + /obj/item/food/ready_donk/mac_n_cheese, + /obj/item/food/ready_donk/donkhiladas) + crate_name = "\improper Ready-Donk crate" + +/datum/supply_pack/service/randomized/ready_donk/fill(obj/structure/closet/crate/C) + for(var/i in 1 to 3) + var/item = pick(contains) + new item(C) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Organic ///////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/organic + group = "Food & Hydroponics" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/hydroponics + access_view = ACCESS_HYDROPONICS + +/datum/supply_pack/organic/hydroponics/beekeeping_suits + name = "Beekeeper Suit Crate" + desc = "Bee business booming? Better be benevolent and boost botany by bestowing bi-Beekeeper-suits! Contains two beekeeper suits and matching headwear." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/head/beekeeper_head, + /obj/item/clothing/suit/beekeeper_suit, + /obj/item/clothing/head/beekeeper_head, + /obj/item/clothing/suit/beekeeper_suit) + crate_name = "beekeeper suits" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/organic/hydroponics/beekeeping_fullkit + name = "Beekeeping Starter Crate" + desc = "BEES BEES BEES. Contains three honey frames, a beekeeper suit and helmet, flyswatter, bee house, and, of course, a pure-bred Nanotrasen-Standardized Queen Bee!" + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/structure/beebox/unwrenched, + /obj/item/honey_frame, + /obj/item/honey_frame, + /obj/item/honey_frame, + /obj/item/queen_bee/bought, + /obj/item/clothing/head/beekeeper_head, + /obj/item/clothing/suit/beekeeper_suit, + /obj/item/melee/flyswatter) + crate_name = "beekeeping starter crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/organic/randomized/chef + name = "Excellent Meat Crate" + desc = "The best cuts in the whole galaxy." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/food/meat/slab/human/mutant/slime, + /obj/item/food/meat/slab/killertomato, + /obj/item/food/meat/slab/bear, + /obj/item/food/meat/slab/xeno, + /obj/item/food/meat/slab/spider, + /obj/item/food/meat/rawbacon, + /obj/item/food/meat/slab/penguin, + /obj/item/food/spiderleg, + /obj/item/food/fishmeat/carp, + /obj/item/food/meat/slab/human) + crate_name = "food crate" + +/datum/supply_pack/organic/randomized/chef/fill(obj/structure/closet/crate/C) + for(var/i in 1 to 15) + var/item = pick(contains) + new item(C) + +/datum/supply_pack/organic/exoticseeds + name = "Exotic Seeds Crate" + desc = "Any entrepreneuring botanist's dream. Contains fourteen different seeds, including one replica-pod seed and two mystery seeds!" + cost = CARGO_CRATE_VALUE * 3 + access_view = ACCESS_HYDROPONICS + contains = list(/obj/item/seeds/nettle, + /obj/item/seeds/replicapod, + /obj/item/seeds/plump, + /obj/item/seeds/liberty, + /obj/item/seeds/amanita, + /obj/item/seeds/reishi, + /obj/item/seeds/bamboo, + /obj/item/seeds/eggplant/eggy, + /obj/item/seeds/rainbow_bunch, + /obj/item/seeds/shrub, + /obj/item/seeds/random, + /obj/item/seeds/random) + crate_name = "exotic seeds crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/organic/food + name = "Food Crate" + desc = "Get things cooking with this crate full of useful ingredients! Contains a dozen eggs, three bananas, and some flour, rice, milk, soymilk, salt, pepper, enzyme, sugar, and monkeymeat." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/reagent_containers/food/condiment/flour, + /obj/item/reagent_containers/food/condiment/rice, + /obj/item/reagent_containers/food/condiment/milk, + /obj/item/reagent_containers/food/condiment/soymilk, + /obj/item/reagent_containers/food/condiment/saltshaker, + /obj/item/reagent_containers/food/condiment/peppermill, + /obj/item/storage/fancy/egg_box, + /obj/item/reagent_containers/food/condiment/enzyme, + /obj/item/reagent_containers/food/condiment/sugar, + /obj/item/food/meat/slab/monkey, + /obj/item/food/grown/banana, + /obj/item/food/grown/banana, + /obj/item/food/grown/banana) + crate_name = "food crate" + +/datum/supply_pack/organic/randomized/chef/fruits + name = "Fruit Crate" + desc = "Rich of vitamins, may contain oranges." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/food/grown/citrus/lime, + /obj/item/food/grown/citrus/orange, + /obj/item/food/grown/watermelon, + /obj/item/food/grown/apple, + /obj/item/food/grown/berries, + /obj/item/food/grown/citrus/lemon) + crate_name = "food crate" + +/datum/supply_pack/organic/cream_piee + name = "High-yield Clown-grade Cream Pie Crate" + desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results." + cost = CARGO_CRATE_VALUE * 12 + contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie) + crate_name = "party equipment crate" + contraband = TRUE + access = ACCESS_THEATRE + access_view = ACCESS_THEATRE + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/organic/hydroponics + name = "Hydroponics Crate" + desc = "Supplies for growing a great garden! Contains two bottles of ammonia, two Plant-B-Gone spray bottles, a hatchet, cultivator, plant analyzer, as well as a pair of leather gloves and a botanist's apron." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/reagent_containers/spray/plantbgone, + /obj/item/reagent_containers/spray/plantbgone, + /obj/item/reagent_containers/glass/bottle/ammonia, + /obj/item/reagent_containers/glass/bottle/ammonia, + /obj/item/hatchet, + /obj/item/cultivator, + /obj/item/plant_analyzer, + /obj/item/clothing/gloves/botanic_leather, + /obj/item/clothing/suit/apron) + crate_name = "hydroponics crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/organic/hydroponics/hydrotank + name = "Hydroponics Backpack Crate" + desc = "Bring on the flood with this high-capacity backpack crate. Contains 500 units of life-giving H2O. Requires hydroponics access to open." + cost = CARGO_CRATE_VALUE * 2 + access = ACCESS_HYDROPONICS + contains = list(/obj/item/watertank) + crate_name = "hydroponics backpack crate" + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/organic/pizza + name = "Pizza Crate" + desc = "Why visit the kitchen when you can have five random pizzas in a fraction of the time? \ + Best prices this side of the galaxy! All deliveries are guaranteed to be 99% anomaly-free." + cost = CARGO_CRATE_VALUE * 10 // Best prices this side of the galaxy. + contains = list(/obj/item/pizzabox/margherita, + /obj/item/pizzabox/mushroom, + /obj/item/pizzabox/meat, + /obj/item/pizzabox/vegetable, + /obj/item/pizzabox/pineapple) + crate_name = "pizza crate" + ///Whether we've provided an infinite pizza box already this shift or not. + var/static/anomalous_box_provided = FALSE + ///The percentage chance (per pizza) of this supply pack to spawn an anomalous pizza box. + var/anna_molly_box_chance = 1 + ///Total tickets in our figurative lottery (per pizza) to decide if we create a bomb box, and if so what type. 1 to 3 create a bomb. The rest do nothing. + var/boombox_tickets = 100 + ///Whether we've provided a bomb pizza box already this shift or not. + var/boombox_provided = FALSE + +/datum/supply_pack/organic/pizza/fill(obj/structure/closet/crate/C) + . = ..() + + var/list/pizza_types = list( + /obj/item/food/pizza/margherita = 10, + /obj/item/food/pizza/meat = 10, + /obj/item/food/pizza/mushroom = 10, + /obj/item/food/pizza/vegetable = 10, + /obj/item/food/pizza/donkpocket = 10, + /obj/item/food/pizza/dank = 7, + /obj/item/food/pizza/sassysage = 10, + /obj/item/food/pizza/pineapple = 10, + /obj/item/food/pizza/arnold = 3 + ) //weighted by chance to disrupt eaters' rounds + + for(var/obj/item/pizzabox/P in C) + if(!anomalous_box_provided) + if(prob(anna_molly_box_chance)) //1% chance for each box, so 4% total chance per order + var/obj/item/pizzabox/infinite/fourfiveeight = new(C) + fourfiveeight.boxtag = P.boxtag + fourfiveeight.boxtag_set = TRUE + fourfiveeight.update_appearance() + qdel(P) + anomalous_box_provided = TRUE + log_game("An anomalous pizza box was provided in a pizza crate at during cargo delivery") + if(prob(50)) + addtimer(CALLBACK(src, .proc/anomalous_pizza_report), rand(300, 1800)) + else + message_admins("An anomalous pizza box was silently created with no command report in a pizza crate delivery.") + continue + + if(!boombox_provided) + var/boombox_lottery = rand(1,boombox_tickets) + var/boombox_type + switch(boombox_lottery) + if(1 to 2) + boombox_type = /obj/item/pizzabox/bomb/armed //explodes after opening + if(3) + boombox_type = /obj/item/pizzabox/bomb //free bomb + + if(boombox_type) + new boombox_type(C) + qdel(P) + boombox_provided = TRUE + log_game("A bomb pizza box was created by a pizza crate delivery.") + message_admins("A bomb pizza box has arrived in a pizza crate delivery.") + continue + + //here we randomly replace our pizzas for a chance at the full range + var/obj/item/food/pizza/replacement_type = pick_weight(pizza_types) + pizza_types -= replacement_type + if(replacement_type && !istype(P.pizza, replacement_type)) + QDEL_NULL(P.pizza) + P.pizza = new replacement_type + P.boxtag = P.pizza.boxtag + P.boxtag_set = TRUE + P.update_appearance() + +/datum/supply_pack/organic/pizza/proc/anomalous_pizza_report() + print_command_report("[station_name()], our anomalous materials divison has reported a missing object that is highly likely to have been sent to your station during a routine cargo \ + delivery. Please search all crates and manifests provided with the delivery and return the object if is located. The object resembles a standard \[DATA EXPUNGED\] and is to be \ + considered \[REDACTED\] and returned at your leisure. Note that objects the anomaly produces are specifically attuned exactly to the individual opening the anomaly; regardless \ + of species, the individual will find the object edible and it will taste great according to their personal definitions, which vary significantly based on person and species.") + +/datum/supply_pack/organic/potted_plants + name = "Potted Plants Crate" + desc = "Spruce up the station with these lovely plants! Contains a random assortment of five potted plants from Nanotrasen's potted plant research division. Warranty void if thrown." + cost = CARGO_CRATE_VALUE * 1.5 + contains = list(/obj/item/kirbyplants/random, + /obj/item/kirbyplants/random, + /obj/item/kirbyplants/random, + /obj/item/kirbyplants/random, + /obj/item/kirbyplants/random) + crate_name = "potted plants crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/organic/seeds + name = "Seeds Crate" + desc = "Big things have small beginnings. Contains fifteen different seeds." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/seeds/chili, + /obj/item/seeds/cotton, + /obj/item/seeds/berry, + /obj/item/seeds/corn, + /obj/item/seeds/eggplant, + /obj/item/seeds/tomato, + /obj/item/seeds/soya, + /obj/item/seeds/wheat, + /obj/item/seeds/wheat/rice, + /obj/item/seeds/carrot, + /obj/item/seeds/sunflower, + /obj/item/seeds/rose, + /obj/item/seeds/chanter, + /obj/item/seeds/potato, + /obj/item/seeds/sugarcane) + crate_name = "seeds crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/organic/randomized/chef/vegetables + name = "Vegetables Crate" + desc = "Grown in vats." + cost = CARGO_CRATE_VALUE * 1.8 + contains = list(/obj/item/food/grown/chili, + /obj/item/food/grown/corn, + /obj/item/food/grown/tomato, + /obj/item/food/grown/potato, + /obj/item/food/grown/carrot, + /obj/item/food/grown/mushroom/chanterelle, + /obj/item/food/grown/onion, + /obj/item/food/grown/pumpkin) + crate_name = "food crate" + +/datum/supply_pack/organic/grill + name = "Grilling Starter Kit" + desc = "Hey dad I'm Hungry. Hi Hungry I'm THE NEW GRILLING STARTER KIT ONLY 5000 BUX GET NOW! Contains a grill and fuel." + cost = CARGO_CRATE_VALUE * 8 + crate_type = /obj/structure/closet/crate + contains = list(/obj/item/stack/sheet/mineral/coal/five, + /obj/machinery/grill/unwrenched, + /obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy + ) + crate_name = "grilling starter kit crate" + +/datum/supply_pack/organic/grillfuel + name = "Grilling Fuel Kit" + desc = "Contains propane and propane accessories. (Note: doesn't contain any actual propane.)" + cost = CARGO_CRATE_VALUE * 4 + crate_type = /obj/structure/closet/crate + contains = list(/obj/item/stack/sheet/mineral/coal/ten, + /obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy + ) + crate_name = "grilling fuel kit crate" + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////// Livestock ///////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/critter + group = "Livestock" + crate_type = /obj/structure/closet/crate/critter + +/datum/supply_pack/critter/parrot + name = "Bird Crate" + desc = "Contains five expert telecommunication birds." + cost = CARGO_CRATE_VALUE * 8 + access_view = ACCESS_CE + contains = list(/mob/living/simple_animal/parrot) + crate_name = "parrot crate" + +/datum/supply_pack/critter/parrot/generate() + . = ..() + for(var/i in 1 to 4) + new /mob/living/simple_animal/parrot(.) + +/datum/supply_pack/critter/butterfly + name = "Butterflies Crate" + desc = "Not a very dangerous insect, but they do give off a better image than, say, flies or cockroaches."//is that a motherfucking worm reference + contraband = TRUE + cost = CARGO_CRATE_VALUE * 5 + access_view = ACCESS_THEATRE + contains = list(/mob/living/simple_animal/butterfly) + crate_name = "entomology samples crate" + +/datum/supply_pack/critter/butterfly/generate() + . = ..() + for(var/i in 1 to 49) + new /mob/living/simple_animal/butterfly(.) + +/datum/supply_pack/critter/cat + name = "Cat Crate" + desc = "The cat goes meow! Comes with a collar and a nice cat toy! Cheeseburger not included."//i can't believe im making this reference + cost = CARGO_CRATE_VALUE * 10 //Cats are worth as much as corgis. + access_view = ACCESS_MEDICAL + contains = list(/mob/living/simple_animal/pet/cat, + /obj/item/clothing/neck/petcollar, + /obj/item/toy/cattoy) + crate_name = "cat crate" + +/datum/supply_pack/critter/cat/generate() + . = ..() + if(prob(50)) + var/mob/living/simple_animal/pet/cat/C = locate() in . + qdel(C) + new /mob/living/simple_animal/pet/cat/_proc(.) + +/datum/supply_pack/critter/chick + name = "Chicken Crate" + desc = "The chicken goes bwaak!" + cost = CARGO_CRATE_VALUE * 4 + access_view = ACCESS_KITCHEN + contains = list( /mob/living/simple_animal/chick) + crate_name = "chicken crate" + +/datum/supply_pack/critter/corgi + name = "Corgi Crate" + desc = "Considered the optimal dog breed by thousands of research scientists, this Corgi is but one dog from the millions of Ian's noble bloodline. Comes with a cute collar!" + cost = CARGO_CRATE_VALUE * 10 + access_view = ACCESS_HOP + contains = list(/mob/living/simple_animal/pet/dog/corgi, + /obj/item/clothing/neck/petcollar) + crate_name = "corgi crate" + +/datum/supply_pack/critter/corgi/generate() + . = ..() + if(prob(50)) + var/mob/living/simple_animal/pet/dog/corgi/D = locate() in . + if(D.gender == FEMALE) + qdel(D) + new /mob/living/simple_animal/pet/dog/corgi/lisa(.) + +/datum/supply_pack/critter/cow + name = "Cow Crate" + desc = "The cow goes moo!" + cost = CARGO_CRATE_VALUE * 6 + access_view = ACCESS_HYDROPONICS + contains = list(/mob/living/basic/cow) + crate_name = "cow crate" + +/datum/supply_pack/critter/crab + name = "Crab Rocket" + desc = "CRAAAAAAB ROCKET. CRAB ROCKET. CRAB ROCKET. CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB ROCKET. CRAFT. ROCKET. BUY. CRAFT ROCKET. CRAB ROOOCKET. CRAB ROOOOCKET. CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB ROOOOOOOOOOOOOOOOOOOOOOCK EEEEEEEEEEEEEEEEEEEEEEEEE EEEETTTTTTTTTTTTAAAAAAAAA AAAHHHHHHHHHHHHH. CRAB ROCKET. CRAAAB ROCKEEEEEEEEEGGGGHHHHTT CRAB CRAB CRAABROCKET CRAB ROCKEEEET."//fun fact: i actually spent like 10 minutes and transcribed the entire video. + cost = CARGO_CRATE_VALUE * 8 + access_view = ACCESS_HOS + contains = list(/mob/living/simple_animal/crab) + crate_name = "look sir free crabs" + DropPodOnly = TRUE + +/datum/supply_pack/critter/crab/generate() + . = ..() + for(var/i in 1 to 49) + new /mob/living/simple_animal/crab(.) + +/datum/supply_pack/critter/corgis/exotic + name = "Exotic Corgi Crate" + desc = "Corgis fit for a king, these corgis come in a unique color to signify their superiority. Comes with a cute collar!" + cost = CARGO_CRATE_VALUE * 11 + contains = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi, + /obj/item/clothing/neck/petcollar) + crate_name = "exotic corgi crate" + +/datum/supply_pack/critter/fox + name = "Fox Crate" + desc = "The fox goes...? Comes with a collar!"//what does the fox say + cost = CARGO_CRATE_VALUE * 10 + access_view = ACCESS_CAPTAIN + contains = list(/mob/living/simple_animal/pet/fox, + /obj/item/clothing/neck/petcollar) + crate_name = "fox crate" + +/datum/supply_pack/critter/goat + name = "Goat Crate" + desc = "The goat goes baa! Warranty void if used as a replacement for Pete." + cost = CARGO_CRATE_VALUE * 5 + access_view = ACCESS_KITCHEN + contains = list(/mob/living/simple_animal/hostile/retaliate/goat) + crate_name = "goat crate" + +/datum/supply_pack/critter/monkey + name = "Monkey Cube Crate" + desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!" + cost = CARGO_CRATE_VALUE * 4 + contains = list (/obj/item/storage/box/monkeycubes) + crate_type = /obj/structure/closet/crate + crate_name = "monkey cube crate" + +/datum/supply_pack/critter/pug + name = "Pug Crate" + desc = "Like a normal dog, but... squished. Comes with a nice collar!" + cost = CARGO_CRATE_VALUE * 10 + contains = list(/mob/living/simple_animal/pet/dog/pug, + /obj/item/clothing/neck/petcollar) + crate_name = "pug crate" + +/datum/supply_pack/critter/bullterrier + name = "Bull Terrier Crate" + desc = "Like a normal dog, but with a head the shape of an egg. Comes with a nice collar!" + cost = CARGO_CRATE_VALUE * 10 + contains = list(/mob/living/simple_animal/pet/dog/bullterrier, + /obj/item/clothing/neck/petcollar) + crate_name = "bull terrier crate" + +/datum/supply_pack/critter/snake + name = "Snake Crate" + desc = "Tired of these MOTHER FUCKING snakes on this MOTHER FUCKING space station? Then this isn't the crate for you. Contains three poisonous snakes." + cost = CARGO_CRATE_VALUE * 6 + access_view = ACCESS_SECURITY + contains = list(/mob/living/simple_animal/hostile/retaliate/snake, + /mob/living/simple_animal/hostile/retaliate/snake, + /mob/living/simple_animal/hostile/retaliate/snake) + crate_name = "snake crate" + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Costumes & Toys ///////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/costumes_toys + group = "Costumes & Toys" + +/datum/supply_pack/costumes_toys/randomised + name = "Collectable Hats Crate" + desc = "Flaunt your status with three unique, highly-collectable hats!" + cost = CARGO_CRATE_VALUE * 40 + var/num_contained = 3 //number of items picked to be contained in a randomised crate + contains = list(/obj/item/clothing/head/collectable/chef, + /obj/item/clothing/head/collectable/paper, + /obj/item/clothing/head/collectable/tophat, + /obj/item/clothing/head/collectable/captain, + /obj/item/clothing/head/collectable/beret, + /obj/item/clothing/head/collectable/welding, + /obj/item/clothing/head/collectable/flatcap, + /obj/item/clothing/head/collectable/pirate, + /obj/item/clothing/head/collectable/kitty, + /obj/item/clothing/head/collectable/rabbitears, + /obj/item/clothing/head/collectable/wizard, + /obj/item/clothing/head/collectable/hardhat, + /obj/item/clothing/head/collectable/hos, + /obj/item/clothing/head/collectable/hop, + /obj/item/clothing/head/collectable/thunderdome, + /obj/item/clothing/head/collectable/swat, + /obj/item/clothing/head/collectable/slime, + /obj/item/clothing/head/collectable/police, + /obj/item/clothing/head/collectable/slime, + /obj/item/clothing/head/collectable/xenom, + /obj/item/clothing/head/collectable/petehat) + crate_name = "collectable hats crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/randomised/contraband + name = "Contraband Crate" + desc = "Psst.. bud... want some contraband? I can get you a poster, some nice cigs, dank, even some sponsored items...you know, the good stuff. Just keep it away from the cops, kay?" + contraband = TRUE + cost = CARGO_CRATE_VALUE * 6 + num_contained = 7 + contains = list(/obj/item/poster/random_contraband, + /obj/item/poster/random_contraband, + /obj/item/food/grown/cannabis, + /obj/item/food/grown/cannabis/rainbow, + /obj/item/food/grown/cannabis/white, + /obj/item/storage/box/fireworks/dangerous, + /obj/item/storage/pill_bottle/zoom, + /obj/item/storage/pill_bottle/happy, + /obj/item/storage/pill_bottle/lsd, + /obj/item/storage/pill_bottle/aranesp, + /obj/item/storage/pill_bottle/stimulant, + /obj/item/toy/cards/deck/syndicate, + /obj/item/reagent_containers/food/drinks/bottle/absinthe, + /obj/item/clothing/under/syndicate/tacticool, + /obj/item/storage/fancy/cigarettes/cigpack_syndicate, + /obj/item/storage/fancy/cigarettes/cigpack_shadyjims, + /obj/item/clothing/mask/gas/syndicate, + /obj/item/clothing/neck/necklace/dope, + /obj/item/vending_refill/donksoft) + crate_name = "crate" + +/datum/supply_pack/costumes_toys/foamforce + name = "Foam Force Crate" + desc = "Break out the big guns with eight Foam Force shotguns!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy, + /obj/item/gun/ballistic/shotgun/toy) + crate_name = "foam force crate" + +/datum/supply_pack/costumes_toys/foamforce/bonus + name = "Foam Force Pistols Crate" + desc = "Psst.. hey bud... remember those old foam force pistols that got discontinued for being too cool? Well I got two of those right here with your name on em. I'll even throw in a spare mag for each, waddya say?" + contraband = TRUE + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/item/gun/ballistic/automatic/pistol/toy, + /obj/item/gun/ballistic/automatic/pistol/toy, + /obj/item/ammo_box/magazine/toy/pistol, + /obj/item/ammo_box/magazine/toy/pistol) + crate_name = "foam force crate" + +/datum/supply_pack/costumes_toys/formalwear + name = "Formalwear Crate" + desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing." + cost = CARGO_CRATE_VALUE * 4 //Lots of very expensive items. You gotta pay up to look good! + contains = list(/obj/item/clothing/under/dress/blacktango, + /obj/item/clothing/under/misc/assistantformal, + /obj/item/clothing/under/misc/assistantformal, + /obj/item/clothing/under/rank/civilian/lawyer/bluesuit, + /obj/item/clothing/suit/toggle/lawyer, + /obj/item/clothing/under/rank/civilian/lawyer/purpsuit, + /obj/item/clothing/suit/toggle/lawyer/purple, + /obj/item/clothing/suit/toggle/lawyer/black, + /obj/item/clothing/accessory/waistcoat, + /obj/item/clothing/neck/tie/blue, + /obj/item/clothing/neck/tie/red, + /obj/item/clothing/neck/tie/black, + /obj/item/clothing/head/bowler, + /obj/item/clothing/head/fedora, + /obj/item/clothing/head/flatcap, + /obj/item/clothing/head/beret, + /obj/item/clothing/head/that, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/under/suit/charcoal, + /obj/item/clothing/under/suit/navy, + /obj/item/clothing/under/suit/burgundy, + /obj/item/clothing/under/suit/checkered, + /obj/item/clothing/under/suit/tan, + /obj/item/lipstick/random) + crate_name = "formalwear crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/clownpin + name = "Hilarious Firing Pin Crate" + desc = "I uh... I'm not really sure what this does. Wanna buy it?" + cost = CARGO_CRATE_VALUE * 10 + contraband = TRUE + contains = list(/obj/item/firing_pin/clown) + crate_name = "toy crate" // It's /technically/ a toy. For the clown, at least. + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/lasertag + name = "Laser Tag Crate" + desc = "Foam Force is for boys. Laser Tag is for men. Contains three sets of red suits, blue suits, matching helmets, and matching laser tag guns." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/gun/energy/laser/redtag, + /obj/item/gun/energy/laser/redtag, + /obj/item/gun/energy/laser/redtag, + /obj/item/gun/energy/laser/bluetag, + /obj/item/gun/energy/laser/bluetag, + /obj/item/gun/energy/laser/bluetag, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/bluetag, + /obj/item/clothing/suit/bluetag, + /obj/item/clothing/suit/bluetag, + /obj/item/clothing/head/helmet/redtaghelm, + /obj/item/clothing/head/helmet/redtaghelm, + /obj/item/clothing/head/helmet/redtaghelm, + /obj/item/clothing/head/helmet/bluetaghelm, + /obj/item/clothing/head/helmet/bluetaghelm, + /obj/item/clothing/head/helmet/bluetaghelm) + crate_name = "laser tag crate" + +/datum/supply_pack/costumes_toys/lasertag/pins + name = "Laser Tag Firing Pins Crate" + desc = "Three laser tag firing pins used in laser-tag units to ensure users are wearing their vests." + cost = CARGO_CRATE_VALUE * 3.5 + contraband = TRUE + contains = list(/obj/item/storage/box/lasertagpins) + crate_name = "laser tag crate" + +/datum/supply_pack/costumes_toys/mech_suits + name = "Mech Pilot's Suit Crate" + desc = "Suits for piloting big robots. Contains four of those!" + cost = CARGO_CRATE_VALUE * 3 //state-of-the-art technology doesn't come cheap + contains = list(/obj/item/clothing/under/costume/mech_suit, + /obj/item/clothing/under/costume/mech_suit, + /obj/item/clothing/under/costume/mech_suit, + /obj/item/clothing/under/costume/mech_suit) + crate_name = "mech pilot's suit crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/costume_original + name = "Original Costume Crate" + desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/clothing/head/snowman, + /obj/item/clothing/suit/snowman, + /obj/item/clothing/head/chicken, + /obj/item/clothing/suit/chickensuit, + /obj/item/clothing/mask/gas/monkeymask, + /obj/item/clothing/suit/monkeysuit, + /obj/item/clothing/head/cardborg, + /obj/item/clothing/suit/cardborg, + /obj/item/clothing/head/xenos, + /obj/item/clothing/suit/xenos, + /obj/item/clothing/suit/hooded/ian_costume, + /obj/item/clothing/suit/hooded/carp_costume, + /obj/item/clothing/suit/hooded/bee_costume) + crate_name = "original costume crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/costume + name = "Standard Costume Crate" + desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing." + cost = CARGO_CRATE_VALUE * 2 + access = ACCESS_THEATRE + contains = list(/obj/item/storage/backpack/clown, + /obj/item/clothing/shoes/clown_shoes, + /obj/item/clothing/mask/gas/clown_hat, + /obj/item/clothing/under/rank/civilian/clown, + /obj/item/bikehorn, + /obj/item/clothing/under/rank/civilian/mime, + /obj/item/clothing/shoes/sneakers/black, + /obj/item/clothing/gloves/color/white, + /obj/item/clothing/mask/gas/mime, + /obj/item/clothing/head/frenchberet, + /obj/item/clothing/suit/toggle/suspenders, + /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing, + /obj/item/storage/backpack/mime) + crate_name = "standard costume crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/randomised/toys + name = "Toy Crate" + desc = "Who cares about pride and accomplishment? Skip the gaming and get straight to the sweet rewards with this product! Contains five random toys. Warranty void if used to prank research directors." + cost = CARGO_CRATE_VALUE * 8 // or play the arcade machines ya lazy bum + num_contained = 5 + contains = list() + crate_name = "toy crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/randomised/toys/fill(obj/structure/closet/crate/C) + var/the_toy + for(var/i in 1 to num_contained) + if(prob(50)) + the_toy = pick_weight(GLOB.arcade_prize_pool) + else + //the_toy = pick(subtypesof(/obj/item/toy/plush)) // SKYRAT EDIT -- Original + the_toy = pick(subtypesof(/obj/item/toy/plush) - typesof(/obj/item/toy/plush/donator)) // SKYRAT EDIT -- No more donator plushies in toy crates + new the_toy(C) + +/datum/supply_pack/costumes_toys/wizard + name = "Wizard Costume Crate" + desc = "Pretend to join the Wizard Federation with this full wizard outfit! Nanotrasen would like to remind its employees that actually joining the Wizard Federation is subject to termination of job and life." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/staff, + /obj/item/clothing/suit/wizrobe/fake, + /obj/item/clothing/shoes/sandal, + /obj/item/clothing/head/wizard/fake) + crate_name = "wizard costume crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C) + var/list/L = contains.Copy() + for(var/i in 1 to num_contained) + var/item = pick_n_take(L) + new item(C) + +/datum/supply_pack/costumes_toys/mafia + name = "Cosa Nostra Starter Pack" + desc = "This crate contains everything you need to set up your own ethnicity-based racketeering operation." + cost = CARGO_CRATE_VALUE * 4 + contains = list() + contraband = TRUE + +/datum/supply_pack/costumes_toys/mafia/fill(obj/structure/closet/crate/C) + for(var/i in 1 to 4) + new /obj/effect/spawner/random/clothing/mafia_outfit(C) + new /obj/item/virgin_mary(C) + if(prob(30)) //Not all mafioso have mustaches, some people also find this item annoying. + new /obj/item/clothing/mask/fakemoustache/italian(C) + if(prob(10)) //A little extra sugar every now and then to shake things up. + new /obj/item/switchblade(C) + +/datum/supply_pack/costumes_toys/randomised/tcg + name = "Big-Ass Booster Pack Pack" + desc = "A bumper load of NT TCG Booster Packs of varying series. Collect them all!" + cost = 1000 + contains = list() + crate_name = "booster pack pack" + +/datum/supply_pack/costumes_toys/randomised/tcg/fill(obj/structure/closet/crate/C) + var/cardpacktype + for(var/i in 1 to 10) + cardpacktype = pick(subtypesof(/obj/item/cardpack)) + new cardpacktype(C) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Miscellaneous /////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/misc + group = "Miscellaneous Supplies" + +/datum/supply_pack/misc/artsupply + name = "Art Supplies" + desc = "Make some happy little accidents with a rapid pipe cleaner layer, three spraycans, and lots of crayons!" + cost = CARGO_CRATE_VALUE * 1.8 + contains = list(/obj/item/rcl, + /obj/item/storage/toolbox/artistic, + /obj/item/toy/crayon/spraycan, + /obj/item/toy/crayon/spraycan, + /obj/item/toy/crayon/spraycan, + /obj/item/storage/crayons, + /obj/item/toy/crayon/white, + /obj/item/toy/crayon/rainbow) + crate_name = "art supply crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/misc + group = "Miscellaneous Supplies" + +/datum/supply_pack/misc/tattoo_kit + name = "Tattoo Kit" + desc = "A tattoo kit with some extra starting ink." + cost = CARGO_CRATE_VALUE * 1.8 + contains = list( + /obj/item/tattoo_kit, + /obj/item/toner, + /obj/item/toner, + ) + crate_name = "tattoo crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/misc/aquarium_kit + name = "Aquarium Kit" + desc = "Everything you need to start your own aquarium. Contains aquarium construction kit, fish catalog, feed can and three freshwater fish from our collection." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/book/fish_catalog, + /obj/item/storage/fish_case/random/freshwater, + /obj/item/storage/fish_case/random/freshwater, + /obj/item/storage/fish_case/random/freshwater, + /obj/item/fish_feed, + /obj/item/storage/box/aquarium_props, + /obj/item/aquarium_kit) + crate_name = "aquarium kit crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/misc/aquarium_fish + name = "Aquarium Fish Case" + desc = "An aquarium fish bundle handpicked by monkeys from our collection." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/fish_case/random, + /obj/item/storage/fish_case/random, + /obj/item/storage/fish_case/random) + crate_name = "aquarium fish crate" + +/datum/supply_pack/misc/freshwater_fish + name = "Freshwater Fish Case" + desc = "Aquarium fish that have had most of their mud cleaned off." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/fish_case/random/freshwater, + /obj/item/storage/fish_case/random/freshwater) + crate_name = "freshwater fish crate" + +/datum/supply_pack/misc/saltwater_fish + name = "Saltwater Fish Case" + desc = "Aquarium fish that fill the room with the smell of salt." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/fish_case/random/saltwater, + /obj/item/storage/fish_case/random/saltwater) + crate_name = "saltwater fish crate" + +/datum/supply_pack/misc/tiziran_fish + name = "Tirizan Fish Case" + desc = "Tiziran saltwater fish imported from the Zagos Sea." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/fish_case/tiziran, + /obj/item/storage/fish_case/tiziran) + crate_name = "tiziran fish crate" + +/datum/supply_pack/misc/bicycle + name = "Bicycle" + desc = "Nanotrasen reminds all employees to never toy with powers outside their control." + cost = 1000000 //Special case, we don't want to make this in terms of crates because having bikes be a million credits is the whole meme. + contains = list(/obj/vehicle/ridden/bicycle) + crate_name = "bicycle crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/misc/bigband + name = "Big Band Instrument Collection" + desc = "Get your sad station movin' and groovin' with this fine collection! Contains nine different instruments!" + cost = CARGO_CRATE_VALUE * 10 + crate_name = "Big band musical instruments collection" + contains = list(/obj/item/instrument/violin, + /obj/item/instrument/guitar, + /obj/item/instrument/glockenspiel, + /obj/item/instrument/accordion, + /obj/item/instrument/saxophone, + /obj/item/instrument/trombone, + /obj/item/instrument/recorder, + /obj/item/instrument/harmonica, + /obj/structure/musician/piano/unanchored) + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/misc/book_crate + name = "Book Crate" + desc = "Surplus from the Nanotrasen Archives, these seven books are sure to be good reads." + cost = CARGO_CRATE_VALUE * 3 + access_view = ACCESS_LIBRARY + contains = list(/obj/item/book/codex_gigas, + /obj/item/book/manual/random/, + /obj/item/book/manual/random/, + /obj/item/book/manual/random/, + /obj/item/book/random, + /obj/item/book/random, + /obj/item/book/random) + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/misc/commandkeys + name = "Command Encryption Key Crate" + desc = "A pack of encryption keys that give access to the command radio network. Nanotrasen reminds unauthorized employees not to eavesdrop in on secure communications channels, or at least to keep heckling of the command staff to a minimum." + access_view = ACCESS_HEADS + access = ACCESS_HEADS + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/encryptionkey/headset_com, + /obj/item/encryptionkey/headset_com, + /obj/item/encryptionkey/headset_com) + crate_type = /obj/structure/closet/crate/secure + crate_name = "command encryption key crate" + +/datum/supply_pack/misc/exploration_drone + name = "Exploration Drone" + desc = "A replacement long-range exploration drone." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/exodrone) + crate_name = "exodrone crate" + +/datum/supply_pack/misc/exploration_fuel + name = "Drone Fuel Pellet" + desc = "A fresh tank of exploration drone fuel." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/fuel_pellet) + crate_name = "exodrone fuel crate" + +/datum/supply_pack/misc/paper + name = "Bureaucracy Crate" + desc = "High stacks of papers on your desk Are a big problem - make it Pea-sized with these bureaucratic supplies! Contains six pens, some camera film, hand labeler supplies, a paper bin, a carbon paper bin, three folders, a laser pointer, two clipboards and two stamps."//that was too forced + cost = CARGO_CRATE_VALUE * 3.2 + contains = list(/obj/structure/filingcabinet/chestdrawer/wheeled, + /obj/item/camera_film, + /obj/item/hand_labeler, + /obj/item/hand_labeler_refill, + /obj/item/hand_labeler_refill, + /obj/item/paper_bin, + /obj/item/paper_bin/carbon, + /obj/item/pen/fourcolor, + /obj/item/pen/fourcolor, + /obj/item/pen, + /obj/item/pen/fountain, + /obj/item/pen/blue, + /obj/item/pen/red, + /obj/item/folder/blue, + /obj/item/folder/red, + /obj/item/folder/yellow, + /obj/item/clipboard, + /obj/item/clipboard, + /obj/item/stamp, + /obj/item/stamp/denied, + /obj/item/laser_pointer/purple) + crate_name = "bureaucracy crate" + +/datum/supply_pack/misc/fountainpens + name = "Calligraphy Crate" + desc = "Sign death warrants in style with these seven executive fountain pens." + cost = CARGO_CRATE_VALUE * 1.45 + contains = list(/obj/item/storage/box/fountainpens) + crate_type = /obj/structure/closet/crate/wooden + crate_name = "calligraphy crate" + +/datum/supply_pack/misc/wrapping_paper + name = "Festive Wrapping Paper Crate" + desc = "Want to mail your loved ones gift-wrapped chocolates, stuffed animals, the Clown's severed head? You can do all that, with this crate full of wrapping paper." + cost = CARGO_CRATE_VALUE * 1.8 + contains = list(/obj/item/stack/wrapping_paper) + crate_type = /obj/structure/closet/crate/wooden + crate_name = "festive wrapping paper crate" + + +/datum/supply_pack/misc/funeral + name = "Funeral Supply crate" + desc = "At the end of the day, someone's gonna want someone dead. Give them a proper send-off with these funeral supplies! Contains a coffin with burial garmets and flowers." + cost = CARGO_CRATE_VALUE * 1.6 + access_view = ACCESS_CHAPEL_OFFICE + contains = list(/obj/item/clothing/under/misc/burial, + /obj/item/food/grown/harebell, + /obj/item/food/grown/poppy/geranium) + crate_name = "coffin" + crate_type = /obj/structure/closet/crate/coffin + +/datum/supply_pack/misc/empty + name = "Empty Supplypod" + desc = "Presenting the New Nanotrasen-Brand Bluespace Supplypod! Transport cargo with grace and ease! Call today and we'll shoot over a demo unit for just 300 credits!" + cost = CARGO_CRATE_VALUE * 0.6 //Empty pod, so no crate refund + contains = list() + DropPodOnly = TRUE + crate_type = null + special_pod = /obj/structure/closet/supplypod/bluespacepod + +/datum/supply_pack/misc/religious_supplies + name = "Religious Supplies Crate" + desc = "Keep your local chaplain happy and well-supplied, lest they call down judgement upon your cargo bay. Contains two bottles of holywater, bibles, chaplain robes, and burial garmets." + cost = CARGO_CRATE_VALUE * 6 // it costs so much because the Space Church needs funding to build a cathedral + access_view = ACCESS_CHAPEL_OFFICE + contains = list(/obj/item/reagent_containers/food/drinks/bottle/holywater, + /obj/item/reagent_containers/food/drinks/bottle/holywater, + /obj/item/storage/book/bible/booze, + /obj/item/storage/book/bible/booze, + /obj/item/clothing/suit/hooded/chaplain_hoodie, + /obj/item/clothing/suit/hooded/chaplain_hoodie, + /obj/item/clothing/under/misc/burial, + /obj/item/clothing/under/misc/burial, + ) + crate_name = "religious supplies crate" + +/datum/supply_pack/misc/toner + name = "Toner Crate" + desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/toner, + /obj/item/toner, + /obj/item/toner, + /obj/item/toner, + /obj/item/toner, + /obj/item/toner) + crate_name = "toner crate" + +/datum/supply_pack/misc/toner_large + name = "Toner Crate (Large)" + desc = "Tired of changing toner cartridges? These six extra heavy duty refills contain roughly five times as much toner as the base model!" + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/toner/large, + /obj/item/toner/large, + /obj/item/toner/large, + /obj/item/toner/large, + /obj/item/toner/large, + /obj/item/toner/large) + crate_name = "large toner crate" + +/datum/supply_pack/misc/training_toolbox + name = "Training Toolbox Crate" + desc = "Hone your combat abiltities with two AURUMILL-Brand Training Toolboxes! Guarenteed to count hits made against living beings!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/training_toolbox, + /obj/item/training_toolbox + ) + crate_name = "training toolbox crate" + +/datum/supply_pack/misc/blackmarket_telepad + name = "Black Market LTSRBT" + desc = "Need a faster and better way of transporting your illegal goods from and to the station? Fear not, the Long-To-Short-Range-Bluespace-Transceiver (LTSRBT for short) is here to help. Contains a LTSRBT circuit, two bluespace crystals, and one ansible." + cost = CARGO_CRATE_VALUE * 20 + contraband = TRUE + contains = list( + /obj/item/circuitboard/machine/ltsrbt, + /obj/item/stack/ore/bluespace_crystal/artificial, + /obj/item/stack/ore/bluespace_crystal/artificial, + /obj/item/stock_parts/subspace/ansible + ) + crate_name = "crate" + +///Special supply crate that generates random syndicate gear up to a determined TC value +/datum/supply_pack/misc/syndicate + name = "Assorted Syndicate Gear" + desc = "Contains a random assortment of syndicate gear." + special = TRUE ///Cannot be ordered via cargo + contains = list() + crate_name = "syndicate gear crate" + crate_type = /obj/structure/closet/crate + var/crate_value = 30 ///Total TC worth of contained uplink items + var/uplink_flag = UPLINK_TRAITORS + +///Generate assorted uplink items, taking into account the same surplus modifiers used for surplus crates +/datum/supply_pack/misc/syndicate/fill(obj/structure/closet/crate/C) + var/list/uplink_items = list() + for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) + var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path] + if(item.purchasable_from & UPLINK_TRAITORS && item.item) + uplink_items += item + + while(crate_value) + var/datum/uplink_item/uplink_item = pick(uplink_items) + if(!uplink_item.surplus || prob(100 - uplink_item.surplus)) + continue + if(crate_value < uplink_item.cost) + continue + crate_value -= uplink_item.cost + new uplink_item.item(C) + +////////////////////////////////////////////////////////////////////////////// +/////////////////////// General Vending Restocks ///////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/vending + group = "Vending Restocks" + +/datum/supply_pack/vending/bartending + name = "Booze-o-mat and Coffee Supply Crate" + desc = "Bring on the booze and coffee vending machine refills." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/vending_refill/boozeomat, + /obj/item/vending_refill/coffee) + crate_name = "bartending supply crate" + +/datum/supply_pack/vending/cigarette + name = "Cigarette Supply Crate" + desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/cigarette) + crate_name = "cigarette supply crate" + crate_type = /obj/structure/closet/crate + +/datum/supply_pack/vending/dinnerware + name = "Dinnerware Supply Crate" + desc = "More knives for the chef." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/vending_refill/dinnerware) + crate_name = "dinnerware supply crate" + +/datum/supply_pack/vending/science/modularpc + name = "Deluxe Silicate Selections Restock" + desc = "What's a computer? Contains a Deluxe Silicate Selections restocking unit." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/modularpc) + crate_name = "computer supply crate" + +/datum/supply_pack/vending/engivend + name = "EngiVend Supply Crate" + desc = "The engineers are out of metal foam grenades? This should help." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/engivend) + crate_name = "engineering supply crate" + +/datum/supply_pack/vending/games + name = "Games Supply Crate" + desc = "Get your game on with this game vending machine refill." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/vending_refill/games) + crate_name = "games supply crate" + crate_type = /obj/structure/closet/crate + +/datum/supply_pack/vending/hydro_refills + name = "Hydroponics Vending Machines Refills" + desc = "When the clown takes all the banana seeds. Contains a NutriMax refill and a MegaSeed Servitor refill." + cost = CARGO_CRATE_VALUE * 4 + crate_type = /obj/structure/closet/crate + contains = list(/obj/item/vending_refill/hydroseeds, + /obj/item/vending_refill/hydronutrients) + crate_name = "hydroponics supply crate" + +/datum/supply_pack/vending/imported + name = "Imported Vending Machines" + desc = "Vending machines famous in other parts of the galaxy." + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/item/vending_refill/sustenance, + /obj/item/vending_refill/robotics, + /obj/item/vending_refill/sovietsoda, + /obj/item/vending_refill/engineering) + crate_name = "unlabeled supply crate" + +/datum/supply_pack/vending/medical + name = "Medical Vending Crate" + desc = "Contains one NanoMed Plus refill, one NanoDrug Plus refill, and one wall-mounted NanoMed refill." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/vending_refill/medical, + /obj/item/vending_refill/drugs, + /obj/item/vending_refill/wallmed) + crate_name = "medical vending crate" + +/datum/supply_pack/vending/ptech + name = "PTech Supply Crate" + desc = "Not enough cartridges after half the crew lost their PDA to explosions? This may fix it." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/cart) + crate_name = "\improper PTech supply crate" + +/* - SKYRAT EDIT REMOVAL - SEC_HAUL - MOVED TO PACKS.DM +/datum/supply_pack/vending/sectech + name = "SecTech Supply Crate" + desc = "Officer Paul bought all the donuts? Then refill the security vendor with ths crate." + cost = CARGO_CRATE_VALUE * 3 + access = ACCESS_SECURITY + contains = list(/obj/item/vending_refill/security) + crate_name = "\improper SecTech supply crate" + crate_type = /obj/structure/closet/crate/secure/gear +*/ + +/datum/supply_pack/vending/snack + name = "Snack Supply Crate" + desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!" + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/snack) + crate_name = "snacks supply crate" + +/datum/supply_pack/vending/cola + name = "Softdrinks Supply Crate" + desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!" + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/cola) + crate_name = "soft drinks supply crate" + +/datum/supply_pack/vending/vendomat + name = "Part-Mart & YouTool Supply Crate" + desc = "More tools for your IED testing facility." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/vending_refill/assist, + /obj/item/vending_refill/youtool) + crate_name = "\improper Part-Mart & YouTool supply crate" + +/datum/supply_pack/vending/clothesmate + name = "ClothesMate Supply Crate" + desc = "Out of cowboy boots? Buy this crate." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/vending_refill/clothing) + crate_name = "\improper ClothesMate supply crate" + +////////////////////////////////////////////////////////////////////////////// +/////////////////////// Clothing Vending Restocks //////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/vending/wardrobes/autodrobe + name = "Autodrobe Supply Crate" + desc = "Autodrobe missing your favorite dress? Solve that issue today with this autodrobe refill." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/autodrobe) + crate_name = "autodrobe supply crate" + +/datum/supply_pack/vending/wardrobes/cargo + name = "Cargo Wardrobe Supply Crate" + desc = "This crate contains a refill for the CargoDrobe." + cost = CARGO_CRATE_VALUE * 1.5 + contains = list(/obj/item/vending_refill/wardrobe/cargo_wardrobe) + crate_name = "cargo department supply crate" + +/datum/supply_pack/vending/wardrobes/engineering + name = "Engineering Wardrobe Supply Crate" + desc = "This crate contains refills for the EngiDrobe and AtmosDrobe." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/wardrobe/engi_wardrobe, + /obj/item/vending_refill/wardrobe/atmos_wardrobe) + crate_name = "engineering department wardrobe supply crate" + +/datum/supply_pack/vending/wardrobes/general + name = "General Wardrobes Supply Crate" + desc = "This crate contains refills for the CuraDrobe, BarDrobe, ChefDrobe, JaniDrobe, ChapDrobe." + cost = CARGO_CRATE_VALUE * 7.5 + contains = list(/obj/item/vending_refill/wardrobe/curator_wardrobe, + /obj/item/vending_refill/wardrobe/bar_wardrobe, + /obj/item/vending_refill/wardrobe/chef_wardrobe, + /obj/item/vending_refill/wardrobe/jani_wardrobe, + /obj/item/vending_refill/wardrobe/chap_wardrobe) + crate_name = "general wardrobes vendor refills" + +/datum/supply_pack/vending/wardrobes/hydroponics + name = "Hydrobe Supply Crate" + desc = "This crate contains a refill for the Hydrobe." + cost = CARGO_CRATE_VALUE * 1.5 + contains = list(/obj/item/vending_refill/wardrobe/hydro_wardrobe) + crate_name = "hydrobe supply crate" + +/datum/supply_pack/vending/wardrobes/medical + name = "Medical Wardrobe Supply Crate" + desc = "This crate contains refills for the MediDrobe, ChemDrobe, and ViroDrobe." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/vending_refill/wardrobe/medi_wardrobe, + /obj/item/vending_refill/wardrobe/chem_wardrobe, + /obj/item/vending_refill/wardrobe/viro_wardrobe) + crate_name = "medical department wardrobe supply crate" + +/datum/supply_pack/vending/wardrobes/science + name = "Science Wardrobe Supply Crate" + desc = "This crate contains refills for the SciDrobe, GeneDrobe, and RoboDrobe." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe, + /obj/item/vending_refill/wardrobe/gene_wardrobe, + /obj/item/vending_refill/wardrobe/science_wardrobe) + crate_name = "science department wardrobe supply crate" + +/* - SKYRAT EDIT REMOVAL - SEC_HAUL - MOVED TO PACKS.DM +/datum/supply_pack/vending/wardrobes/security + name = "Security Wardrobe Supply Crate" + desc = "This crate contains refills for the SecDrobe, DetDrobe and LawDrobe." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/vending_refill/wardrobe/sec_wardrobe, + /obj/item/vending_refill/wardrobe/det_wardrobe, + /obj/item/vending_refill/wardrobe/law_wardrobe) + crate_name = "security department supply crate" +*/ + +/// Exploration drone unlockables /// + +/datum/supply_pack/exploration + special = TRUE + group = "Outsourced" + +/datum/supply_pack/exploration/scrapyard + name = "Scrapyard Crate" + desc = "Outsourced crate containing various junk." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/relic, + /obj/item/broken_bottle, + /obj/item/pickaxe/rusted) + crate_name = "scrapyard crate" + +/datum/supply_pack/exploration/catering + name = "Catering Crate" + desc = "No cook? No problem! Food quality may vary depending on provider." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/food/sandwich, + /obj/item/food/sandwich, + /obj/item/food/sandwich, + /obj/item/food/sandwich, + /obj/item/food/sandwich) + crate_name = "outsourced food crate" + +/datum/supply_pack/exploration/catering/fill(obj/structure/closet/crate/C) + . = ..() + if(prob(30)) + for(var/obj/item/food/F in C) + F.name = "spoiled [F.name]" + F.foodtypes |= GROSS + F.MakeEdible() + +/datum/supply_pack/exploration/shrubbery + name = "Shrubbery Crate" + desc = "Crate full of hedge shrubs." + cost = CARGO_CRATE_VALUE * 5 + crate_name = "shrubbery crate" + var/shrub_amount = 8 + +/datum/supply_pack/exploration/shrubbery/fill(obj/structure/closet/crate/C) + for(var/i in 1 to shrub_amount) + new /obj/item/grown/shrub(C) diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index 1fd4eecd83d7..7ea8ebe2c204 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -282,6 +282,16 @@ if("toggleprivate") self_paid = !self_paid . = TRUE + //SKYRAT EDIT START + if("gun_window") + var/datum/component/armament/cargo_gun/gun_comp = holder.holder.GetComponent(/datum/component/armament/cargo_gun) + if(!gun_comp) + holder.holder.AddComponent(/datum/component/armament/cargo_gun, subtypesof(/datum/armament_entry/cargo_gun), 0) + gun_comp = holder.holder.GetComponent(/datum/component/armament/cargo_gun) + gun_comp.parent_prog ||= src + gun_comp.ui_interact(usr) + . = TRUE + //SKYRAT EDIT END if(.) post_signal(cargo_shuttle) diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 703b908f2bee..b029ed1f1cdd 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -101,7 +101,7 @@ /obj/item/gun/ballistic/automatic/pistol/aps name = "\improper Stechkin APS machine pistol" - desc = "An old Soviet machine pistol. It fires quickly, but kicks like a mule. Uses 9mm ammo. Has a threaded barrel for suppressors." + desc = "A modernized reproduction of an old Soviet machine pistol. It fires quickly, but kicks like a mule. Uses 9mm ammo. Has a threaded barrel for suppressors." //SKYRAT EDIT icon_state = "aps" w_class = WEIGHT_CLASS_NORMAL mag_type = /obj/item/ammo_box/magazine/m9mm_aps diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index 1512055d0c97..bddb3defb82a 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -5,6 +5,7 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new) #define KEYCARD_BSA_UNLOCK "Bluespace Artillery Unlock" #define ACCESS_GRANTING_COOLDOWN (30 SECONDS) +#define KEYCARD_PIN_UNRESTRICT "Unrestrict Permit Firing Pins" //SKYRAT EDIT /obj/machinery/keycard_auth name = "Keycard Authentication Device" @@ -104,6 +105,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/keycard_auth, 26) SEND_GLOBAL_SIGNAL(COMSIG_ON_DEPARTMENT_ACCESS, info["regions"]) balloon_alert(usr, "key access sent") return + //SKYRAT EDIT START + if("pin_unrestrict") + if(!event_source) + sendEvent(KEYCARD_PIN_UNRESTRICT) + . = TRUE + //SKYRAT EDIT END /obj/machinery/keycard_auth/update_appearance(updates) . = ..() @@ -157,6 +164,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/keycard_auth, 26) make_maint_all_access() if(KEYCARD_BSA_UNLOCK) toggle_bluespace_artillery() + //SKYRAT EDIT START + if(KEYCARD_PIN_UNRESTRICT) + toggle_permit_pins() + //SKYRAT EDIT END GLOBAL_VAR_INIT(emergency_access, FALSE) /proc/make_maint_all_access() @@ -188,3 +199,4 @@ GLOBAL_VAR_INIT(emergency_access, FALSE) #undef KEYCARD_RED_ALERT #undef KEYCARD_EMERGENCY_MAINTENANCE_ACCESS #undef KEYCARD_BSA_UNLOCK +#undef KEYCARD_PIN_UNRESTRICT //SKYRAT EDIT diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 683bdc2d647c..6243f73ee26e 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -166,6 +166,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( SSshuttle.order_history += spawning_order QDEL_NULL(spawning_order.applied_coupon) + spawning_order.on_spawn() //SKYRAT EDIT if(!spawning_order.pack.goody) //we handle goody crates below spawning_order.generate(pick_n_take(empty_turfs)) diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 412f8ab51cbc..43135d828be0 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -136,9 +136,9 @@ purchasable_from = UPLINK_NUKE_OPS /datum/uplink_item/dangerous/machinegun - name = "L6 Squad Automatic Weapon" - desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \ - This deadly weapon has a massive 50-round magazine of devastating 7.12x82mm ammunition." + name = "L6 Machine Gun" + desc = "A fully-loaded Scarborough Arms belt-fed machine gun. \ + This deadly weapon has a 50-round box chambered for 7.12x82mm ammunition." //SKYRAT EDIT - AUSSEC TO SCARBOROUGH item = /obj/item/gun/ballistic/automatic/l6_saw cost = 18 surplus = 10 //monkestation edit: from 0 to 10 diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index faa70d81cee9..3b0ccae187bd 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -231,4 +231,8 @@ h1.alert, h2.alert {color: #000000;} } // MONKESTATION ADDITION END +.brown {color: #3d2009;} +.orange {color: #b8761a;} +.yellow {color: #c7b72c;} +.cyan {color: #0ea1e6;} "} diff --git a/modular_skyrat/master_files/code/modules/projectiles/guns/ballistic/automatic.dm b/modular_skyrat/master_files/code/modules/projectiles/guns/ballistic/automatic.dm new file mode 100644 index 000000000000..57c296f9cc37 --- /dev/null +++ b/modular_skyrat/master_files/code/modules/projectiles/guns/ballistic/automatic.dm @@ -0,0 +1,346 @@ +/obj/item/gun/ballistic/automatic + w_class = WEIGHT_CLASS_NORMAL + can_suppress = TRUE + burst_size = 3 + fire_delay = 2 + semi_auto = TRUE + fire_sound = 'sound/weapons/gun/smg/shot.ogg' + fire_sound_volume = 90 + vary_fire_sound = FALSE + rack_sound = 'sound/weapons/gun/smg/smgrack.ogg' + suppressed_sound = 'sound/weapons/gun/smg/shot_suppressed.ogg' + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_BURST_SHOT, SELECT_FULLY_AUTOMATIC) + +/obj/item/gun/ballistic/automatic/proto + name = "\improper Nanotrasen Saber SMG" + desc = "A prototype three-round burst 9mm submachine gun, designated 'SABR'. Has a threaded barrel for suppressors." + icon_state = "saber" + selector_switch_icon = TRUE + mag_display = TRUE + empty_indicator = TRUE + mag_type = /obj/item/ammo_box/magazine/smgm9mm + pin = null + bolt_type = BOLT_TYPE_LOCKING + show_bolt_icon = FALSE + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/ballistic/automatic/proto/unrestricted + pin = /obj/item/firing_pin + +/obj/item/gun/ballistic/automatic/c20r + name = "\improper C-20r SMG" + desc = "A bullpup three-round burst .45 SMG, designated 'C-20r'." + icon_state = "c20r" + inhand_icon_state = "c20r" + selector_switch_icon = TRUE + mag_type = /obj/item/ammo_box/magazine/smgm45 + fire_delay = 2 + burst_size = 3 + pin = /obj/item/firing_pin/implant/pindicate + can_bayonet = TRUE + knife_x_offset = 26 + knife_y_offset = 12 + mag_display = TRUE + mag_display_ammo = TRUE + empty_indicator = TRUE + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/automatic/c20r/update_overlays() + . = ..() + if(!chambered && empty_indicator) + . += "[icon_state]_empty" + +/obj/item/gun/ballistic/automatic/c20r/unrestricted + pin = /obj/item/firing_pin + +/obj/item/gun/ballistic/automatic/c20r/Initialize() + . = ..() + update_appearance() + +/obj/item/gun/ballistic/automatic/wt550 + name = "security auto rifle" + desc = "An outdated personal defence weapon. Uses 4.6x30mm rounds and is designated the WT-550 Automatic Rifle." + icon_state = "wt550" + w_class = WEIGHT_CLASS_BULKY + inhand_icon_state = "arg" + mag_type = /obj/item/ammo_box/magazine/wt550m9 + fire_delay = 2 + can_suppress = FALSE + burst_size = 1 + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_FULLY_AUTOMATIC) + can_bayonet = TRUE + knife_x_offset = 25 + knife_y_offset = 12 + mag_display = TRUE + mag_display_ammo = TRUE + empty_indicator = TRUE + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/ballistic/automatic/plastikov + name = "\improper PP-95 SMG" + desc = "An ancient 9mm submachine gun pattern updated and simplified to lower costs, though perhaps simplified too much." + icon_state = "plastikov" + inhand_icon_state = "plastikov" + mag_type = /obj/item/ammo_box/magazine/plastikov9mm + burst_size = 5 + spread = 25 + can_suppress = FALSE + projectile_damage_multiplier = 0.35 //It's like 10.5 damage per bullet, it's close enough to 10 shots + mag_display = TRUE + empty_indicator = TRUE + fire_sound = 'sound/weapons/gun/smg/shot_alt.ogg' + company_flag = COMPANY_IZHEVSK + dirt_modifier = 0.75 + +/obj/item/gun/ballistic/automatic/mini_uzi + name = "\improper type U3 uzi" + desc = "A lightweight, burst-fire submachine gun, for when you really want someone dead. Uses 9mm rounds." + icon_state = "miniuzi" + mag_type = /obj/item/ammo_box/magazine/uzim9mm + burst_size = 2 + bolt_type = BOLT_TYPE_OPEN + show_bolt_icon = FALSE + mag_display = TRUE + rack_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + company_flag = COMPANY_OLDARMS + +/obj/item/gun/ballistic/automatic/m90 + name = "\improper M-90gl carbine" + desc = "A three-round burst 5.56 toploading carbine, designated 'M-90gl'. Has an attached underbarrel grenade launcher which can be fired using right click." + icon_state = "m90" + w_class = WEIGHT_CLASS_BULKY + inhand_icon_state = "m90" + selector_switch_icon = TRUE + mag_type = /obj/item/ammo_box/magazine/m556 + can_suppress = FALSE + var/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel + burst_size = 3 + fire_delay = 2 + spread = 5 + pin = /obj/item/firing_pin/implant/pindicate + mag_display = TRUE + empty_indicator = TRUE + fire_sound = 'sound/weapons/gun/smg/shot_alt.ogg' + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/automatic/m90/Initialize() + . = ..() + underbarrel = new /obj/item/gun/ballistic/revolver/grenadelauncher(src) + update_appearance() + +/obj/item/gun/ballistic/automatic/m90/unrestricted + pin = /obj/item/firing_pin + +/obj/item/gun/ballistic/automatic/m90/unrestricted/Initialize() + . = ..() + underbarrel = new /obj/item/gun/ballistic/revolver/grenadelauncher/unrestricted(src) + update_appearance() + +/obj/item/gun/ballistic/automatic/m90/afterattack_secondary(atom/target, mob/living/user, flag, params) + underbarrel.afterattack(target, user, flag, params) + return SECONDARY_ATTACK_CONTINUE_CHAIN + +/obj/item/gun/ballistic/automatic/m90/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/ammo_casing)) + if(istype(attacking_item, underbarrel.magazine.ammo_type)) + underbarrel.attack_self(user) + underbarrel.attackby(attacking_item, user, params) + else + ..() + +/obj/item/gun/ballistic/automatic/tommygun + name = "\improper Thompson SMG" + desc = "Based on the classic 'Chicago Typewriter'." + icon_state = "tommygun" + inhand_icon_state = "shotgun" + selector_switch_icon = TRUE + w_class = WEIGHT_CLASS_BULKY + slot_flags = 0 + mag_type = /obj/item/ammo_box/magazine/tommygunm45 + can_suppress = FALSE + burst_size = 1 + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_FULLY_AUTOMATIC) + fire_delay = 1 + bolt_type = BOLT_TYPE_OPEN + empty_indicator = TRUE + show_bolt_icon = FALSE + company_flag = COMPANY_OLDARMS + +/obj/item/gun/ballistic/automatic/tommygun/therealtommy + name = "Tommy gun" + desc = "The classic 'Chicago Typewriter'." + company_flag = null //This is the real deal, you hear? + +/obj/item/gun/ballistic/automatic/ar + name = "\improper NT-ARG 'Boarder'" + desc = "A robust assault rifle used by Nanotrasen fighting forces." + icon_state = "arg" + inhand_icon_state = "arg" + slot_flags = 0 + mag_type = /obj/item/ammo_box/magazine/m556 + can_suppress = FALSE + burst_size = 3 + fire_delay = 1 + company_flag = COMPANY_NANOTRASEN + + +// L6 SAW // + +/obj/item/gun/ballistic/automatic/l6_saw + name = "\improper L6 SAW" + desc = "A large light machine gun chambered for the 7.12x82mm cartridge." + icon_state = "l6" + inhand_icon_state = "l6" + base_icon_state = "l6" + w_class = WEIGHT_CLASS_HUGE + slot_flags = 0 + mag_type = /obj/item/ammo_box/magazine/mm712x82 + weapon_weight = WEAPON_HEAVY + burst_size = 1 + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_FULLY_AUTOMATIC) + can_suppress = FALSE + spread = 7 + pin = /obj/item/firing_pin/implant/pindicate + bolt_type = BOLT_TYPE_OPEN + show_bolt_icon = FALSE + mag_display = TRUE + mag_display_ammo = TRUE + tac_reloads = FALSE + fire_sound = 'sound/weapons/gun/l6/shot.ogg' + rack_sound = 'sound/weapons/gun/l6/l6_rack.ogg' + suppressed_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' + var/cover_open = FALSE + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/automatic/l6_saw/unrestricted + pin = /obj/item/firing_pin + +/obj/item/gun/ballistic/automatic/l6_saw/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/gun/ballistic/automatic/l6_saw/examine(mob/user) + . = ..() + . += "alt + click to [cover_open ? "close" : "open"] the dust cover." + if(cover_open && magazine) + . += span_notice("It seems like you could use an empty hand to remove the magazine.") + + +/obj/item/gun/ballistic/automatic/l6_saw/AltClick(mob/user) + if(!user.canUseTopic(src)) + return + cover_open = !cover_open + to_chat(user, span_notice("You [cover_open ? "open" : "close"] [src]'s cover.")) + playsound(src, 'sound/weapons/gun/l6/l6_door.ogg', 60, TRUE) + update_appearance() + +/obj/item/gun/ballistic/automatic/l6_saw/update_icon_state() + . = ..() + inhand_icon_state = "[base_icon_state][cover_open ? "open" : "closed"][magazine ? "mag":"nomag"]" + +/obj/item/gun/ballistic/automatic/l6_saw/update_overlays() + . = ..() + . += "l6_door_[cover_open ? "open" : "closed"]" + + +/obj/item/gun/ballistic/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) + if(cover_open) + to_chat(user, span_warning("[src]'s cover is open! Close it before firing!")) + return + else + . = ..() + update_appearance() + +//ATTACK HAND IGNORING PARENT RETURN VALUE +/obj/item/gun/ballistic/automatic/l6_saw/attack_hand(mob/user, list/modifiers) + if (loc != user) + ..() + return + if (!cover_open) + to_chat(user, span_warning("[src]'s cover is closed! Open it before trying to remove the magazine!")) + return + ..() + +/obj/item/gun/ballistic/automatic/l6_saw/attackby(obj/item/attacking_item, mob/user, params) + if(!cover_open && istype(attacking_item, mag_type)) + to_chat(user, span_warning("[src]'s dust cover prevents a magazine from being fit.")) + return + ..() + +// SNIPER // + +/obj/item/gun/ballistic/automatic/sniper_rifle + name = "sniper rifle" + desc = "A long ranged weapon that does significant damage. No, you can't quickscope." + icon_state = "sniper" + w_class = WEIGHT_CLASS_BULKY + inhand_icon_state = "sniper" + worn_icon_state = null + fire_sound = 'sound/weapons/gun/sniper/shot.ogg' + fire_sound_volume = 90 + vary_fire_sound = FALSE + load_sound = 'sound/weapons/gun/sniper/mag_insert.ogg' + rack_sound = 'sound/weapons/gun/sniper/rack.ogg' + suppressed_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' + recoil = 2 + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/sniper_rounds + fire_delay = 40 + burst_size = 1 + w_class = WEIGHT_CLASS_NORMAL + zoomable = TRUE + zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you. + zoom_out_amt = 5 + slot_flags = ITEM_SLOT_BACK + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + mag_display = TRUE + suppressor_x_offset = 3 + suppressor_y_offset = 3 + +/obj/item/gun/ballistic/automatic/sniper_rifle/syndicate + name = "syndicate sniper rifle" + desc = "An illegally modified .50 cal sniper rifle with suppression compatibility. Quickscoping still doesn't work." + can_suppress = TRUE + can_unsuppress = TRUE + pin = /obj/item/firing_pin/implant/pindicate + company_flag = COMPANY_SCARBOROUGH + +// Old Semi-Auto Rifle // + +/obj/item/gun/ballistic/automatic/surplus + name = "surplus rifle" + desc = "One of countless obsolete ballistic rifles that still sees use as a cheap deterrent. Uses 10mm Magnum ammo and its bulky frame prevents one-hand firing." + icon_state = "surplus" + inhand_icon_state = "moistnugget" + worn_icon_state = null + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/m10mm/rifle + fire_delay = 30 + burst_size = 1 + can_unsuppress = TRUE + can_suppress = TRUE + w_class = WEIGHT_CLASS_HUGE + slot_flags = ITEM_SLOT_BACK + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + mag_display = TRUE + company_flag = COMPANY_IZHEVSK + dirt_modifier = 0.75 + +// Laser rifle (rechargeable magazine) // + +/obj/item/gun/ballistic/automatic/laser + name = "laser rifle" + desc = "Though sometimes mocked for the relatively weak firepower of their energy weapons, the logistic miracle of rechargeable ammunition has given Nanotrasen a decisive edge over many a foe." + icon_state = "oldrifle" + w_class = WEIGHT_CLASS_BULKY + inhand_icon_state = "arg" + mag_type = /obj/item/ammo_box/magazine/recharge + mag_display_ammo = TRUE + fire_delay = 2 + can_suppress = FALSE + burst_size = 0 + //actions_types = list() SKYRAT EDIT REMOVAL + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + fire_sound = 'sound/weapons/laser.ogg' + casing_ejector = FALSE + company_flag = COMPANY_NANOTRASEN diff --git a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm index 0623ae88fcfd..a3829894754f 100644 --- a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm +++ b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm @@ -95,6 +95,8 @@ var/list/fire_select_modes = list(SELECT_SEMI_AUTOMATIC) ///if i`1t has an icon for a selector switch indicating current firemode. var/selector_switch_icon = FALSE + /// Bitflags for the company that produces the gun, do not give more than one company. + var/company_flag /datum/action/item_action/toggle_safety name = "Toggle Safety" @@ -585,6 +587,9 @@ return remove_gun_attachment(user, tool, bayonet, "unfix") else if(pin && user.is_holding(src)) + if(!pin.can_remove) + to_chat(user, span_warning("You can't remove this firing pin!")) + return user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [tool]."), span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3) if(tool.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, volume = 50)) @@ -599,6 +604,9 @@ . = ..() if(.) return + if(!pin.can_remove) + to_chat(user, span_warning("You can't remove this firing pin!")) + return if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return if(pin && user.is_holding(src)) @@ -618,6 +626,9 @@ return if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return + if(!pin.can_remove) + to_chat(user, span_warning("You can't remove this firing pin!")) + return if(pin && user.is_holding(src)) user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [tool]."), span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3) @@ -797,6 +808,30 @@ /obj/item/gun/proc/before_firing(atom/target, mob/user) return +/obj/item/gun/examine_more(mob/user) + . = ..() + switch(company_flag) + if(COMPANY_CANTALAN) + . += "
It has [span_purple("Cantalan Federal Arms")] etched into the grip." + if(COMPANY_ARMADYNE) + . += "
It has [span_red("Armadyne Corporation")] etched into the barrel." + if(COMPANY_SCARBOROUGH) + . += "
It has [span_orange("Scarborough Arms")] stamped onto the grip." + if(COMPANY_BOLT) + . += "
It has [span_yellow("Bolt Fabrications")] stamped onto the reciever." + if(COMPANY_OLDARMS) + . += "
It has [span_red("Armadyne Oldarms")] etched into the barrel." + if(COMPANY_IZHEVSK) + . += "
It has [span_brown("Izhevsk Coalition")] cut in above the magwell." + if(COMPANY_NANOTRASEN) + . += "
It has [span_blue("Nanotrasen Armories")] etched into the reciever." + if(COMPANY_ALLSTAR) + . += "
It has [span_red("Allstar Lasers Inc.")] stamped on the front grip." + if(COMPANY_MICRON) + . += "
It has [span_cyan("Micron Control Sys.")] cut in above the cell slot." + if(COMPANY_INTERDYNE) + . += "
It has [span_cyan("Interdyne Pharmaceuticals")] stamped onto the barrel." + ///////////// // ZOOMING // ///////////// @@ -858,5 +893,13 @@ azoom = new() azoom.gun = src +/obj/item/gun/emag_act(mob/user, obj/item/card/emag/emag_card) + . = ..() + if(!pin.can_remove) + to_chat(user, span_notice("You short out the gun's firing pin, allowing it to be removed!")) + pin.can_remove = TRUE + if(!(pin.obj_flags & EMAGGED)) + pin.obj_flags |= EMAGGED + #undef FIRING_PIN_REMOVAL_DELAY #undef DUALWIELD_PENALTY_EXTRA_MULTIPLIER diff --git a/modular_skyrat/master_files/icons/mob/huds/hud.dmi b/modular_skyrat/master_files/icons/mob/huds/hud.dmi new file mode 100644 index 0000000000000000000000000000000000000000..0056f8d115092a13f3d2c8f979dc77a18e16d401 GIT binary patch literal 12766 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 B!(IRY literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/ERT_Factions/FTU/code/items.dm b/modular_skyrat/modules/ERT_Factions/FTU/code/items.dm new file mode 100644 index 000000000000..94147d22130e --- /dev/null +++ b/modular_skyrat/modules/ERT_Factions/FTU/code/items.dm @@ -0,0 +1,139 @@ +/obj/item/melee/energy/ignis + name = "\improper FTU 'Ignis' plasma sword" + desc = "An expensive FTU design, the Ignis is one of many prototypes at making an energy sword out of plasma, rather than hardlight. This one has the FTU flag imprinted on its high-quality wooden hilt, and unlike earlier models, can sustain several hits without exhausting its battery. " + icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/serviceguns.dmi' + icon_state = "ignis" + lefthand_file = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/lefthand.dmi' + righthand_file = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/righthand.dmi' + force = 3 + active_force = 48 + block_chance = 65 + sharpness = SHARP_EDGED + throwforce = 5 + active_throwforce = 40 + wound_bonus = 50 + hitsound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/ignis_hit.ogg' + throw_speed = 4 + throw_range = 10 + w_class = WEIGHT_CLASS_SMALL + active_w_class = WEIGHT_CLASS_HUGE + armour_penetration = 90 + attack_verb_continuous = list("rips", "evaporates", "penetrates", "tears", "lacerates", "impales", "masterfully brutalizes") + attack_verb_simple = list("rip", "evaporate", "penetrate", "tear", "lacerate", "impale", "masterfully brutalize") + resistance_flags = FIRE_PROOF + damtype = BURN + enable_sound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/ignis_toggle.ogg' + disable_sound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/ignis_toggle.ogg' + +/obj/item/melee/energy/ignis/make_transformable() + AddComponent(/datum/component/transforming, \ + force_on = active_force, \ + throwforce_on = active_throwforce, \ + throw_speed_on = throw_speed, \ + sharpness_on = sharpness, \ + w_class_on = active_w_class) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +///////40x32 R37 PULSE RIFLE +/obj/item/gun/ballistic/automatic/pitbull/pulse/r37 + name = "\improper Xan-Jing R37 'Killer Hornet' pulse rifle" + desc = "A Xan-Jing Armories pulse rifle, nicknamed 'Killer Hornet' by FTU Mercenaries and Expeditioners. This one has an integrated computer that displays an objective compass, ammo counter and comes with a HUD link for easy targetting." + icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/serviceguns.dmi' + righthand_file = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/lefthand.dmi' + lefthand_file = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/lefthand.dmi' + inhand_icon_state = "killerhornet_lefthand" + icon_state = "killerhornet" + worn_icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/serviceguns.dmi' + worn_icon_state = "killerhornet_worn" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + mag_type = /obj/item/ammo_box/magazine/pulse/r37 + fire_delay = 4 + can_suppress = FALSE + burst_size = 5 + spread = 3 + mag_display = TRUE + mag_display_ammo = TRUE + realistic = TRUE + fire_sound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/r37.ogg' + emp_damageable = FALSE + can_bayonet = FALSE + can_flashlight = TRUE + mag_type = /obj/item/ammo_box/magazine/pulse/r37 + company_flag = null + +/obj/item/ammo_box/magazine/pulse/r37 + name = "6.5mm XJP box magazine" + icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/mags.dmi' + icon_state = "hornet" + ammo_type = /obj/item/ammo_casing/pulse/mm65 + caliber = "6.5mm" + max_ammo = 36 + + +///////40x32 R40 MACHINE GUN +/obj/item/gun/ballistic/automatic/pitbull/pulse/r40 + name = "\improper Xan-Jing R40 'Enforcer' pulse MMG" + desc = "A Xan-Jing Armories medium machine gun, nicknamed 'Enforcer' by FTU Mercenaries and Private Militaries. This one has a custom wood furnishing and its batteries power up the sights." + icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/serviceguns.dmi' + righthand_file = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/righthand.dmi' + inhand_icon_state = "enforcer_righthand" + icon_state = "enforcer" + worn_icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/serviceguns.dmi' + worn_icon_state = "killerhornet_worn" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK + mag_type = /obj/item/ammo_box/magazine/pulse/r40 + fire_delay = 1 + can_suppress = FALSE + burst_size = 8 + spread = 5 + mag_display = TRUE + mag_display_ammo = FALSE + realistic = TRUE + fire_sound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/r40.ogg' + emp_damageable = FALSE + can_bayonet = FALSE + can_flashlight = TRUE + mag_type = /obj/item/ammo_box/magazine/pulse/r40 + company_flag = null + +/obj/item/ammo_box/magazine/pulse/r40 + name = "7.2mm XJP belted box" + icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/mags.dmi' + icon_state = "enforcer" + ammo_type = /obj/item/ammo_casing/pulse/mm72 + caliber = "7.2mm" + max_ammo = 140 + +//////////12.7 SAPHE GOLDEN EAGLE +/obj/item/gun/ballistic/automatic/pistol/pdh/pulse/golden_eagle + name = "\improper FTU PDH-6G 'Sea Serpent' magnum" + desc = "A custom-made high-power combat pistol seen in the hands of high ranking FTU Mercenaries and important executives, with a custom 24-karat gold finish and green laser sight. It has a chinese dragon engraved along its slide." + icon = 'modular_skyrat/modules/ERT_Factions/FTU/icons/weapons/serviceguns.dmi' + icon_state = "eagle" + can_suppress = FALSE + mag_display = TRUE + fire_sound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/serpent_fire.ogg' + fire_sound_volume = 100 + rack_sound = 'modular_skyrat/modules/ERT_Factions/FTU/sound/magnum_slide.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/pulse/mm12/saphe + can_suppress = FALSE + fire_delay = 25 //Mind your wrists. + fire_sound_volume = 110 + rack_sound_volume = 110 + spread = 1 + realistic = TRUE + can_flashlight = FALSE + emp_damageable = FALSE + +/obj/item/ammo_box/magazine/pulse/mm12/saphe + name = "12.7x35mm SAP-HE magnum magazine" + icon_state = "50ae" + ammo_type = /obj/item/ammo_casing/pulse/mm12 + caliber = "12mm SAP-HE" + max_ammo = 12 diff --git a/modular_skyrat/modules/aesthetics/guns/code/guns.dm b/modular_skyrat/modules/aesthetics/guns/code/guns.dm new file mode 100644 index 000000000000..c1a80c6fee49 --- /dev/null +++ b/modular_skyrat/modules/aesthetics/guns/code/guns.dm @@ -0,0 +1,329 @@ +/obj/item/gun/energy/e_gun + icon = 'modular_skyrat/modules/aesthetics/guns/icons/energy.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi' + worn_icon_state = "energy" + ammo_x_offset = 2 + +/obj/item/gun/energy/e_gun/advtaser + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/e_gun/cfa_phalanx + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/e_gun/mini + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/e_gun/stun + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/e_gun/old + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/e_gun/hos + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/e_gun/dragnet + worn_icon = null + worn_icon_state = "gun" + +/obj/item/gun/energy/ionrifle + icon = 'modular_skyrat/modules/aesthetics/guns/icons/energy.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + +/obj/item/gun/energy/laser + icon = 'modular_skyrat/modules/aesthetics/guns/icons/energy.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + +/obj/item/gun/energy/e_gun/stun + charge_sections = 5 + ammo_x_offset = 2 + +/obj/item/gun/ballistic/shotgun/riot + name = "\improper Peacekeeper shotgun" + desc = "A Nanotrasen-made riot control shotgun fitted with an extended tube and a fixed tactical stock." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + inhand_icon_state = "riot_shotgun" + inhand_x_dimension = 32 + inhand_y_dimension = 32 + can_suppress = TRUE + suppressed_sound = 'modular_skyrat/modules/aesthetics/guns/sound/suppressed_shotgun.ogg' + suppressed_volume = 100 + vary_fire_sound = TRUE + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/shotgun_light.ogg' + +/obj/item/gun/ballistic/shotgun/automatic/combat + name = "\improper Peacekeeper combat shotgun" + desc = "A semi-automatic Nanotrasen Peacekeeper shotgun with tactical furnishing and heavier internals meant for sustained fire. Lacks a threaded barrel." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + inhand_icon_state = "shotgun_combat" + inhand_x_dimension = 32 + inhand_y_dimension = 32 + +/obj/item/gun/grenadelauncher + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + +/obj/item/gun/ballistic/automatic/pistol/m1911 + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + inhand_icon_state = "colt" + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + +/obj/item/gun/ballistic/revolver/mateba + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/ballistic/automatic/c20r + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/ballistic/automatic/m90 + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' +/obj/item/gun/ballistic/revolver/detective + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/ballistic/automatic/pistol/aps + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/ballistic/automatic/pistol + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/energy/e_gun/nuclear + icon = 'modular_skyrat/modules/aesthetics/guns/icons/nucgun.dmi' + ammo_x_offset = 2 + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + worn_icon_state = "gun" + worn_icon = null + +/obj/item/gun/energy/laser/thermal + icon = 'icons/obj/guns/energy.dmi' + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + +/obj/item/gun/energy/lasercannon + icon = 'modular_skyrat/modules/aesthetics/guns/icons/energy.dmi' + fire_sound_volume = 100 + ammo_x_offset = 2 + charge_sections = 5 + inhand_icon_state = "" + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + +/obj/item/gun/energy/e_gun/nuclear/rainbow + name = "fantastic energy gun" + desc = "An energy gun with an experimental miniaturized nuclear reactor that automatically charges the internal power cell. This one seems quite fancy!" + ammo_type = list(/obj/item/ammo_casing/energy/laser/rainbow, /obj/item/ammo_casing/energy/disabler/rainbow) + +/obj/item/ammo_casing/energy/laser/rainbow + icon = 'modular_skyrat/modules/aesthetics/guns/icons/nucgun.dmi' + select_name = "kill" + projectile_type = /obj/projectile/beam/laser/rainbow + +/obj/projectile/beam/laser/rainbow + icon = 'modular_skyrat/modules/aesthetics/guns/icons/nucgun.dmi' + icon_state = "laser" + +/obj/item/ammo_casing/energy/disabler/rainbow + icon = 'modular_skyrat/modules/aesthetics/guns/icons/nucgun.dmi' + select_name = "disable" + projectile_type = /obj/projectile/beam/disabler/rainbow + +/obj/projectile/beam/disabler/rainbow + icon = 'modular_skyrat/modules/aesthetics/guns/icons/nucgun.dmi' + icon_state = "laser" + +/obj/item/gun/energy/e_gun/nuclear/emag_act(mob/user, obj/item/card/emag/E) + . = ..() + if(pin) + to_chat(user, span_warning("You probably want to do this on a new gun!")) + return FALSE + to_chat(user, "The gun suddenly feels quite fantastic!") + new /obj/item/gun/energy/e_gun/nuclear/rainbow(get_turf(user)) + qdel(src) + +/obj/item/gun/energy/e_gun/nuclear/rainbow/update_overlays() + . = ..() + . += "[icon_state]_emagged" + +/obj/item/gun/energy/e_gun/nuclear/rainbow/emag_act(mob/user, obj/item/card/emag/E) + return FALSE + +//BEAM SOUNDS +/obj/item/ammo_casing/energy + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/laser.ogg' + +/obj/item/ammo_casing/energy/laser/pulse + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/pulse.ogg' + +/obj/item/gun/energy/xray + fire_sound_volume = 100 + +/obj/item/ammo_casing/energy/xray + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/xray_laser.ogg' + +/obj/item/ammo_casing/energy/laser/accelerator + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/laser_cannon_fire.ogg' + +/obj/item/gun/ballistic/automatic/sniper_rifle + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_gubman2.dmi' + icon_state = "sniper" + fire_delay = 60 + +/obj/item/gun/ballistic/automatic/sniper_rifle/syndicate + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_gubman2.dmi' + icon_state = "sniper2" + fire_delay = 55 + +/obj/item/gun/ballistic/automatic/sniper_rifle/modular + name = "AUS-107 anti-materiel rifle" + desc = "A devastating Aussec Armory heavy sniper rifle, fitted with a modern scope." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_gubman2.dmi' + icon_state = "sniper" + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/sniperrifle.ogg' + suppressed_sound = 'modular_skyrat/modules/aesthetics/guns/sound/sniperrifle_s.ogg' + w_class = WEIGHT_CLASS_BULKY + can_suppress = FALSE + +/obj/item/gun/ballistic/automatic/sniper_rifle/modular/syndicate + name = "'Caracal' anti-materiel rifle" //we flop out + desc = "A sleek, light bullpup .50 BMG sniper rifle with a reciprocating barrel, nicknamed 'Caracal' by Scarborough Arms. Its compact folding parts make it able to fit into a backpack, and its modular barrel can have a suppressor installed within it rather than as a muzzle extension. Its advanced scope accounts for all ballistic inaccuracies of a reciprocating barrel." + icon_state = "sysniper" + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/sniperrifle.ogg' + suppressed_sound = 'modular_skyrat/modules/aesthetics/guns/sound/sniperrifle_s.ogg' + fire_delay = 40 //Delay reduced thanks to recoil absorption + burst_size = 0.5 + recoil = 1 + can_suppress = TRUE + can_unsuppress = TRUE + weapon_weight = WEAPON_LIGHT + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/automatic/sniper_rifle/modular/blackmarket //Normal sniper but epic + name = "SA-107 anti-materiel rifle" + desc = "An illegal Scarborough Arms rendition of an Aussec Armory sniper rifle. This one has been fitted with a heavier duty scope, a sturdier stock, and has a removable muzzle brake that allows easy attachment of suppressors." + icon_state = "sniper2" + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/sniperrifle.ogg' + suppressed_sound = 'modular_skyrat/modules/aesthetics/guns/sound/sniperrifle_s.ogg' + fire_sound_volume = 90 + vary_fire_sound = FALSE + load_sound = 'sound/weapons/gun/sniper/mag_insert.ogg' + rack_sound = 'sound/weapons/gun/sniper/rack.ogg' + w_class = WEIGHT_CLASS_NORMAL + can_suppress = TRUE + can_unsuppress = TRUE + recoil = 1.8 + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/sniper_rounds + fire_delay = 55 //Slightly smaller than standard sniper + burst_size = 1 + zoomable = TRUE + zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you. + zoom_out_amt = 5 + slot_flags = ITEM_SLOT_BACK + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) //SKYRAT EDIT CHANGE + mag_display = TRUE + +/obj/item/gun/ballistic/automatic/ar/modular + name = "NT ARG-63" + desc = "Nanotrasen's prime ballistic option based on the Stoner design, fitted with a light polymer frame and other tactical furniture - nicknamed 'Boarder' by Special Operations teams." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_gubman2.dmi' + icon_state = "arg" + inhand_icon_state = "arg" + can_suppress = FALSE + +/obj/item/gun/ballistic/automatic/ar/modular/solrifle + name = "MCRS-5B ICWS" + desc = "State of the art expensive combat rifle used by the SFMC. This one is a lighter model that fires 5.56, designed for use by pilots. Do it for her." + icon_state = "mcrs" + inhand_icon_state = "arg" + selector_switch_icon = TRUE + mag_type = /obj/item/ammo_box/magazine/m556 + can_suppress = FALSE + burst_size = 5 + fire_delay = 0.4 + spread = 1 + w_class = WEIGHT_CLASS_NORMAL + can_suppress = FALSE + weapon_weight = WEAPON_HEAVY + +/obj/item/gun/energy/kinetic_accelerator + icon = 'modular_skyrat/modules/aesthetics/guns/icons/energy.dmi' + +/obj/item/gun/ballistic/rifle/boltaction + name = "\improper Mosin Nagant 91-30" + desc = "This piece of junk looks like something that could have been used 700 years ago. It feels slightly moist." + sawn_desc = "An extremely sawn-off Mosin Nagant, popularly known as an \"obrez\". There was probably a reason it wasn't manufactured this short to begin with." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/ballistic/rifle/boltaction/brand_new + name = "\improper Mosin Nagant M39" + desc = "A freshly-produced Mosin Nagant variant issued by Nanotrasen for their interns. You would rather not damage it." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/ballistic/rifle/boltaction/brand_new/quartermaster + name = "\improper FTU 'Archangel' Mosin" + desc = "A very... Modernized MN91-30 rifle, the frame even feels a little flimsy. This thing was probably built with a conversion kit from spaceBay." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + icon_state = "bubba" + worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi' + worn_icon_state = "bubba" + mag_type = /obj/item/ammo_box/magazine/internal/boltaction/bubba + can_be_sawn_off = FALSE + realistic = TRUE + company_flag = null //Cargonia's own + +/obj/item/ammo_box/magazine/internal/boltaction/bubba + name = "mosin nagant extended internal magazine" + desc = "How did you get it out?" + ammo_type = /obj/item/ammo_casing/a762 + caliber = CALIBER_A762 + max_ammo = 8 + multiload = TRUE + +/obj/item/gun/ballistic/automatic/surplus + name = "\improper Type-69 surplus rifle" + desc = "One of countless obsolete ballistic rifles that still sees use as a cheap deterrent. Uses 10mm ammo and its bulky frame prevents one-hand firing." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + +/obj/item/gun/ballistic/automatic/c20r/unrestricted/cmg1 + name = "\improper NT CMG-1" + desc = "A bullpup three-round burst .45 PDW with an eerily familiar design. It has a foldable stock and a dot sight." + icon_state = "cmg1" + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/ballistic/automatic/ar/modular/model75 + name = "\improper NT ARG-75" + desc = "A contemporary rifle that just exited its prototype phase and has started production, a rare sight for now. It's equipped with a heavy duty integrally suppressed barrel, 1.4 times scope and a topmounted laser sight." + icon_state = "arg75" + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + fire_sound = 'sound/weapons/gun/pistol/shot_suppressed.ogg' + fire_delay = 5 + fire_sound_volume = 90 + mag_type = /obj/item/ammo_box/magazine/multi_sprite/ostwind/arg75 + company_flag = COMPANY_NANOTRASEN + +/obj/item/ammo_box/magazine/multi_sprite/ostwind/arg75 + name = "7.62mm straight magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pcr" + ammo_type = /obj/item/ammo_casing/a762 + caliber = CALIBER_A762 + max_ammo = 20 diff --git a/modular_skyrat/modules/armaments/code/armament_component.dm b/modular_skyrat/modules/armaments/code/armament_component.dm new file mode 100644 index 000000000000..8dff81ab4c3a --- /dev/null +++ b/modular_skyrat/modules/armaments/code/armament_component.dm @@ -0,0 +1,275 @@ +/** + * This is the component that runs the armaments vendor. + * + * It's intended to be used with the armament vendor, or other atoms that otherwise aren't vending machines. + */ + +/datum/component/armament + /// The types of armament datums we wish to add to this component. + var/list/products + /// What access do we require to use this machine? + var/list/required_access + /// Our parent machine. + var/atom/parent_atom + /// The points card that is currently inserted into the parent. + var/obj/item/armament_points_card/inserted_card + /// Used to keep track of what categories have been used. + var/list/used_categories = list() + /// Used to keep track of what items have been purchased. + var/list/purchased_items = list() + +/datum/component/armament/Initialize(list/required_products, list/needed_access) + if(!required_products) + stack_trace("No products specified for armament") + return COMPONENT_INCOMPATIBLE + + parent_atom = parent + + products = required_products + + required_access = needed_access + + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby) + +/datum/component/armament/Destroy(force, silent) + if(inserted_card) + inserted_card.forceMove(parent_atom.drop_location()) + inserted_card = null + return ..() + +/datum/component/armament/proc/on_attackby(atom/target, obj/item, mob/user) + SIGNAL_HANDLER + + if(!user || !item) + return + + if(!user.can_interact_with(parent_atom)) + return + + if(!istype(item, /obj/item/armament_points_card) || inserted_card) + return + + item.forceMove(parent_atom) + inserted_card = item + +/datum/component/armament/proc/on_attack_hand(datum/source, mob/living/user) + SIGNAL_HANDLER + + if(!user) + return + + if(!user.can_interact_with(parent_atom)) + return + + if(!check_access(user)) + to_chat(user, span_warning("You don't have the required access!")) + return + + INVOKE_ASYNC(src, .proc/ui_interact, user) + +/datum/component/armament/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ArmamentStation") + ui.open() + +/datum/component/armament/ui_data(mob/user) + var/list/data = list() + + data["card_inserted"] = inserted_card ? TRUE : FALSE + data["card_name"] = "unknown" + data["card_points"] = 0 + if(inserted_card) + data["card_points"] = inserted_card.points + data["card_name"] = inserted_card.name + + data["armaments_list"] = list() + for(var/armament_category as anything in GLOB.armament_entries) + var/list/armament_subcategories = list() + for(var/subcategory as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY]) + var/list/subcategory_items = list() + for(var/datum/armament_entry/armament_entry as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY][subcategory]) + if(products && !(armament_entry.type in products)) + continue + subcategory_items += list(list( + "ref" = REF(armament_entry), + "icon" = armament_entry.cached_base64, + "name" = armament_entry.name, + "cost" = armament_entry.cost, + "buyable_ammo" = armament_entry.magazine ? TRUE : FALSE, + "magazine_cost" = armament_entry.magazine_cost, + "quantity" = armament_entry.max_purchase, + "purchased" = purchased_items[armament_entry] ? purchased_items[armament_entry] : 0, + "description" = armament_entry.description, + "armament_category" = armament_entry.category, + "equipment_subcategory" = armament_entry.subcategory, + )) + if(!LAZYLEN(subcategory_items)) + continue + armament_subcategories += list(list( + "subcategory" = subcategory, + "items" = subcategory_items, + )) + if(!LAZYLEN(armament_subcategories)) + continue + data["armaments_list"] += list(list( + "category" = armament_category, + "category_limit" = GLOB.armament_entries[armament_category][CATEGORY_LIMIT], + "category_uses" = used_categories[armament_category], + "subcategories" = armament_subcategories, + )) + + return data + +/datum/component/armament/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("equip_item") + var/check = check_item(params["armament_ref"]) + if(!check) + return + select_armament(usr, check) + if("buy_ammo") + var/check = check_item(params["armament_ref"]) + if(!check) + return + buy_ammo(usr, check, params["quantity"]) + if("eject_card") + eject_card(usr) + +/datum/component/armament/proc/buy_ammo(mob/user, datum/armament_entry/armament_entry, quantity = 1) + if(!armament_entry.magazine) + return + if(!inserted_card) + to_chat(user, span_warning("No card inserted!")) + return + var/quantity_cost = armament_entry.magazine_cost * quantity + if(!inserted_card.use_points(quantity_cost)) + to_chat(user, span_warning("Not enough points!")) + return + for(var/i in 1 to quantity) + new armament_entry.magazine(parent_atom.drop_location()) + +/datum/component/armament/proc/check_item(reference) + var/datum/armament_entry/armament_entry + for(var/category in GLOB.armament_entries) + for(var/subcategory in GLOB.armament_entries[category][CATEGORY_ENTRY]) + armament_entry = locate(reference) in GLOB.armament_entries[category][CATEGORY_ENTRY][subcategory] + if(armament_entry) + break + if(armament_entry) + break + if(!armament_entry) + return FALSE + if(products && !(armament_entry.type in products)) + return FALSE + return armament_entry + +/datum/component/armament/proc/eject_card(mob/user) + if(!inserted_card) + to_chat(user, span_warning("No card inserted!")) + return + inserted_card.forceMove(parent_atom.drop_location()) + user.put_in_hands(inserted_card) + inserted_card = null + to_chat(user, span_notice("Card ejected!")) + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 70) + +/datum/component/armament/proc/select_armament(mob/user, datum/armament_entry/armament_entry) + if(!inserted_card) + to_chat(user, span_warning("No card inserted!")) + return + if(used_categories[armament_entry.category] >= GLOB.armament_entries[armament_entry.category][CATEGORY_LIMIT]) + to_chat(user, span_warning("Category limit reached!")) + return + if(purchased_items[armament_entry] >= armament_entry.max_purchase) + to_chat(user, span_warning("Item limit reached!")) + return + if(!ishuman(user)) + return + if(!inserted_card.use_points(armament_entry.cost)) + to_chat(user, span_warning("Not enough points!")) + return + + var/mob/living/carbon/human/human_to_equip = user + + var/obj/item/new_item = new armament_entry.item_type(parent_atom.drop_location()) + + used_categories[armament_entry.category]++ + purchased_items[armament_entry]++ + + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + + if(armament_entry.equip_to_human(human_to_equip, new_item)) + to_chat(user, span_notice("Equipped directly to your person.")) + playsound(src, 'sound/items/equip/toolbelt_equip.ogg', 100) + armament_entry.after_equip(parent_atom.drop_location(), new_item) + +/datum/component/armament/proc/check_access(mob/living/user) + if(!user) + return FALSE + + if(!required_access) + return TRUE + + if(issilicon(user)) + if(ispAI(user)) + return FALSE + return TRUE //AI can do whatever it wants + + if(isAdminGhostAI(user)) + return TRUE + + //If the mob has the simple_access component with the requried access, the check passes + else if(SEND_SIGNAL(user, COMSIG_MOB_TRIED_ACCESS, src) & ACCESS_ALLOWED) + return TRUE + + //If the mob is holding a valid ID, they pass the access check + else if(check_access_obj(user.get_active_held_item())) + return TRUE + + //if they are wearing a card that has access and are human, that works + else if(ishuman(user)) + var/mob/living/carbon/human/human_user = user + if(check_access_obj(human_user.wear_id)) + return TRUE + + //if they're strange and have a hacky ID card as an animal + else if(isanimal(user)) + var/mob/living/simple_animal/animal = user + if(check_access_obj(animal.access_card)) + return TRUE + +/datum/component/armament/proc/check_access_obj(obj/item/id) + return check_access_list(id ? id.GetAccess() : null) + +/datum/component/armament/proc/check_access_list(list/access_list) + if(!islist(required_access)) //something's very wrong + return TRUE + + if(!length(required_access)) + return TRUE + + if(!length(access_list) || !islist(access_list)) + return FALSE + + for(var/req in required_access) + if(!(req in access_list)) //doesn't have this access + return FALSE + + return TRUE + +/datum/component/armament/proc/text2access(access_text) + . = list() + if(!access_text) + return + var/list/split = splittext(access_text,";") + for(var/split_text in split) + var/num_text = text2num(split_text) + if(!num_text) + continue + . += num_text diff --git a/modular_skyrat/modules/assault_operatives/code/armaments/_armament_primary.dm b/modular_skyrat/modules/assault_operatives/code/armaments/_armament_primary.dm new file mode 100644 index 000000000000..7b835713d32f --- /dev/null +++ b/modular_skyrat/modules/assault_operatives/code/armaments/_armament_primary.dm @@ -0,0 +1,72 @@ +/datum/armament_entry/assault_operatives/primary + category = ARMAMENT_CATEGORY_PRIMARY + category_item_limit = ARMAMENT_CATEGORY_PRIMARY_LIMIT + slot_to_equip = ITEM_SLOT_SUITSTORE + cost = 10 + +/datum/armament_entry/assault_operatives/primary/submachinegun + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + mags_to_spawn = 4 + +/datum/armament_entry/assault_operatives/primary/submachinegun/p90 + item_type = /obj/item/gun/ballistic/automatic/p90 + +/datum/armament_entry/assault_operatives/primary/submachinegun/wildcat + item_type = /obj/item/gun/ballistic/automatic/cfa_wildcat + cost = 5 + +/datum/armament_entry/assault_operatives/primary/submachinegun/lynx + item_type = /obj/item/gun/ballistic/automatic/cfa_lynx + +/datum/armament_entry/assault_operatives/primary/submachinegun/mp40 + item_type = /obj/item/gun/ballistic/automatic/mp40 + mags_to_spawn = 3 + +/datum/armament_entry/assault_operatives/primary/submachinegun/ppsh + item_type = /obj/item/gun/ballistic/automatic/ppsh + +/datum/armament_entry/assault_operatives/primary/submachinegun/c20r + item_type = /obj/item/gun/ballistic/automatic/c20r + +/datum/armament_entry/assault_operatives/primary/assaultrifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + +/datum/armament_entry/assault_operatives/primary/assaultrifle/akm + item_type = /obj/item/gun/ballistic/automatic/akm + +/datum/armament_entry/assault_operatives/primary/assaultrifle/m16 + item_type = /obj/item/gun/ballistic/automatic/m16 + +/datum/armament_entry/assault_operatives/primary/assaultrifle/stg + item_type = /obj/item/gun/ballistic/automatic/stg + cost = 12 + +/datum/armament_entry/assault_operatives/primary/assaultrifle/fg42 + item_type = /obj/item/gun/ballistic/automatic/fg42 + +/datum/armament_entry/assault_operatives/primary/special + subcategory = ARMAMENT_SUBCATEGORY_SPECIAL + +/datum/armament_entry/assault_operatives/primary/special/l6saw + item_type = /obj/item/gun/ballistic/automatic/l6_saw + cost = 15 + mags_to_spawn = 2 + +/datum/armament_entry/assault_operatives/primary/special/mg9 + item_type = /obj/item/gun/ballistic/automatic/mg34/mg42 + cost = 15 + mags_to_spawn = 2 + +/datum/armament_entry/assault_operatives/primary/special/smartgun + item_type = /obj/item/gun/ballistic/automatic/smartgun + cost = 12 + +/datum/armament_entry/assault_operatives/primary/special/rocket_launcher + item_type = /obj/item/gun/ballistic/rocketlauncher/unrestricted + cost = 15 + +/datum/armament_entry/assault_operatives/primary/special/rocket_launcher/after_equip(turf/safe_drop_location, obj/item/item_to_equip) + var/obj/item/storage/box/ammo_box/spawned_box = new(safe_drop_location) + spawned_box.name = "ROCKETS - [item_to_equip.name]" + for(var/i in 1 to 5) + new /obj/item/ammo_casing/caseless/rocket(spawned_box) diff --git a/modular_skyrat/modules/assault_operatives/code/armaments/_armaments_secondary.dm b/modular_skyrat/modules/assault_operatives/code/armaments/_armaments_secondary.dm new file mode 100644 index 000000000000..566898a46a25 --- /dev/null +++ b/modular_skyrat/modules/assault_operatives/code/armaments/_armaments_secondary.dm @@ -0,0 +1,62 @@ +// SECONDARY WEAPONS +/datum/armament_entry/assault_operatives/secondary + category = ARMAMENT_CATEGORY_SECONDARY + category_item_limit = ARMAMENT_CATEGORY_SECONDARY_LIMIT + cost = 5 + mags_to_spawn = 2 + +/datum/armament_entry/assault_operatives/secondary/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/assault_operatives/secondary/pistol/m1911 + item_type = /obj/item/gun/ballistic/automatic/pistol/m1911 + +/datum/armament_entry/assault_operatives/secondary/pistol/aps + item_type = /obj/item/gun/ballistic/automatic/pistol/aps + cost = 7 + +/datum/armament_entry/assault_operatives/secondary/pistol/luger + item_type = /obj/item/gun/ballistic/automatic/pistol/luger + +/datum/armament_entry/assault_operatives/secondary/pistol/syndicate + item_type = /obj/item/gun/ballistic/automatic/pistol + +/datum/armament_entry/assault_operatives/secondary/pistol/deagle + item_type = /obj/item/gun/ballistic/automatic/pistol/deagle + cost = 9 + +/datum/armament_entry/assault_operatives/secondary/pistol/deagle_gold + item_type = /obj/item/gun/ballistic/automatic/pistol/deagle/gold + cost = 9 + +/datum/armament_entry/assault_operatives/secondary/pistol/deagle_camo + item_type = /obj/item/gun/ballistic/automatic/pistol/deagle/camo + cost = 9 + +/datum/armament_entry/assault_operatives/secondary/pistol/robohand + item_type = /obj/item/gun/ballistic/automatic/pistol/robohand + cost = 10 + +/datum/armament_entry/assault_operatives/secondary/pistol/automag + item_type = /obj/item/gun/ballistic/automatic/pistol/automag + cost = 8 + +/datum/armament_entry/assault_operatives/secondary/pistol/energy_gun + item_type = /obj/item/gun/energy/e_gun + +/datum/armament_entry/assault_operatives/secondary/pistol/taser + item_type = /obj/item/gun/energy/e_gun/advtaser + +/datum/armament_entry/assault_operatives/secondary/pistol/pepperball + item_type = /obj/item/gun/ballistic/automatic/pistol/pepperball + cost = 4 + +/datum/armament_entry/assault_operatives/secondary/kravmaga + item_type = /obj/item/clothing/gloves/krav_maga/combatglovesplus + cost = 5 + +/datum/armament_entry/assault_operatives/secondary/cqc + name = "CQC Manual" + item_type = /obj/item/book/granter/martial/cqc + cost = 10 + diff --git a/modular_skyrat/modules/assault_operatives/code/armaments/armament_headgear.dm b/modular_skyrat/modules/assault_operatives/code/armaments/armament_headgear.dm new file mode 100644 index 000000000000..78d01b987895 --- /dev/null +++ b/modular_skyrat/modules/assault_operatives/code/armaments/armament_headgear.dm @@ -0,0 +1,29 @@ +// HELMETS + +/datum/armament_entry/assault_operatives/headgear + category = ARMAMENT_CATEGORY_ARMOR_HEAD + category_item_limit = ARMAMENT_CATEGORY_ARMOR_HEAD_LIMIT + slot_to_equip = ITEM_SLOT_HEAD + +/datum/armament_entry/assault_operatives/headgear/helmet + subcategory = ARMAMENT_SUBCATEGORY_HELMET + +/datum/armament_entry/assault_operatives/headgear/helmet/normal + item_type = /obj/item/clothing/head/helmet + cost = 3 + +/datum/armament_entry/assault_operatives/headgear/helmet/bulletproof + item_type = /obj/item/clothing/head/helmet/alt + cost = 5 + +/datum/armament_entry/assault_operatives/headgear/helmet/syndicate + item_type = /obj/item/clothing/head/helmet/swat + cost = 7 + +/datum/armament_entry/assault_operatives/headgear/helmet/syndicate + item_type = /obj/item/clothing/head/helmet/swat + cost = 7 + +/datum/armament_entry/assault_operatives/headgear/helmet/syndicate_beret + item_type = /obj/item/clothing/head/hos/beret/syndicate + cost = 6 diff --git a/modular_skyrat/modules/assault_operatives/code/armaments/armament_medical.dm b/modular_skyrat/modules/assault_operatives/code/armaments/armament_medical.dm new file mode 100644 index 000000000000..46a98f47678f --- /dev/null +++ b/modular_skyrat/modules/assault_operatives/code/armaments/armament_medical.dm @@ -0,0 +1,73 @@ +/datum/armament_entry/assault_operatives/medical + category = ARMAMENT_CATEGORY_MEDICAL + category_item_limit = ARMAMENT_CATEGORY_MEDICAL_LIMIT + +/datum/armament_entry/assault_operatives/medical/medkit + subcategory = ARMAMENT_SUBCATEGORY_MEDKIT + +/datum/armament_entry/assault_operatives/medical/medkit/basic + item_type = /obj/item/storage/medkit/regular + cost = 1 + +/datum/armament_entry/assault_operatives/medical/medkit/brute + item_type = /obj/item/storage/medkit/brute + cost = 1 + +/datum/armament_entry/assault_operatives/medical/medkit/toxin + item_type = /obj/item/storage/medkit/toxin + cost = 1 + +/datum/armament_entry/assault_operatives/medical/medkit/fire + item_type = /obj/item/storage/medkit/fire + cost = 1 + +/datum/armament_entry/assault_operatives/medical/medkit/o2 + item_type = /obj/item/storage/medkit/o2 + cost = 1 + +/datum/armament_entry/assault_operatives/medical/medkit/tactical + item_type = /obj/item/storage/medkit/tactical + cost = 5 + +/datum/armament_entry/assault_operatives/medical/surgery_bag + item_type = /obj/item/storage/backpack/duffelbag/syndie/surgery + cost = 2 + +/datum/armament_entry/assault_operatives/medical/injector + subcategory = ARMAMENT_SUBCATEGORY_INJECTOR + +/datum/armament_entry/assault_operatives/medical/injector/bloodloss + item_type = /obj/item/reagent_containers/hypospray/medipen/blood_loss + cost = 2 + +/datum/armament_entry/assault_operatives/medical/injector/atropine + item_type = /obj/item/reagent_containers/hypospray/medipen/atropine + cost = 2 + +/datum/armament_entry/assault_operatives/medical/injector/salacid + item_type = /obj/item/reagent_containers/hypospray/medipen/salacid + cost = 1 + +/datum/armament_entry/assault_operatives/medical/injector/oxandrolone + item_type = /obj/item/reagent_containers/hypospray/medipen/oxandrolone + cost = 1 + +/datum/armament_entry/assault_operatives/medical/injector/oxandrolone + item_type = /obj/item/reagent_containers/hypospray/medipen/oxandrolone + cost = 1 + +/datum/armament_entry/assault_operatives/medical/injector/stimulant + item_type = /obj/item/reagent_containers/hypospray/medipen/stimulants + cost = 3 + +/datum/armament_entry/assault_operatives/medical/injector/bag + item_type = /obj/item/storage/bag/medpens + cost = 6 + +/datum/armament_entry/assault_operatives/medical/beamgun + item_type = /obj/item/gun/medbeam + cost = 5 + +/datum/armament_entry/assault_operatives/medical/defib + item_type = /obj/item/defibrillator/compact/loaded + cost = 3 diff --git a/modular_skyrat/modules/assault_operatives/code/armaments/armament_melee.dm b/modular_skyrat/modules/assault_operatives/code/armaments/armament_melee.dm new file mode 100644 index 000000000000..71ec971833e1 --- /dev/null +++ b/modular_skyrat/modules/assault_operatives/code/armaments/armament_melee.dm @@ -0,0 +1,33 @@ + +// MELEE WEAPONS + +/datum/armament_entry/assault_operatives/melee + category = ARMAMENT_CATEGORY_MELEE + category_item_limit = ARMAMENT_CATEGORY_MELEE_LIMIT + +/datum/armament_entry/assault_operatives/melee/lethal + subcategory = ARMAMENT_SUBCATEGORY_MELEE_LETHAL + +/datum/armament_entry/assault_operatives/melee/lethal/survival_knife + item_type = /obj/item/knife/combat/survival + cost = 5 + +/datum/armament_entry/assault_operatives/melee/lethal/combat_knife + item_type = /obj/item/knife/combat + cost = 6 + +/datum/armament_entry/assault_operatives/melee/lethal/energy + item_type = /obj/item/melee/energy/sword/saber + cost = 10 + +/datum/armament_entry/assault_operatives/melee/nonlethal + subcategory = ARMAMENT_SUBCATEGORY_MELEE_NONLETHAL + +/datum/armament_entry/assault_operatives/melee/nonlethal/baton + item_type = /obj/item/melee/baton/security/loaded + cost = 3 + +/datum/armament_entry/assault_operatives/melee/nonlethal/baton_telescopic + item_type = /obj/item/melee/baton/telescopic + cost = 5 + diff --git a/modular_skyrat/modules/black_mesa/code/armaments/_armament_primary.dm b/modular_skyrat/modules/black_mesa/code/armaments/_armament_primary.dm new file mode 100644 index 000000000000..310989009902 --- /dev/null +++ b/modular_skyrat/modules/black_mesa/code/armaments/_armament_primary.dm @@ -0,0 +1,75 @@ +/datum/armament_entry/hecu/primary + category = ARMAMENT_CATEGORY_PRIMARY + category_item_limit = 4 + slot_to_equip = ITEM_SLOT_SUITSTORE + cost = 10 + +/datum/armament_entry/hecu/primary/submachinegun + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + mags_to_spawn = 4 + +/datum/armament_entry/hecu/primary/submachinegun/p90 + item_type = /obj/item/gun/ballistic/automatic/p90 + max_purchase = 4 + cost = 7 + +/datum/armament_entry/hecu/primary/submachinegun/mp5 + item_type = /obj/item/gun/ballistic/automatic/mp5 + max_purchase = 2 + cost = 10 + +/datum/armament_entry/hecu/primary/assaultrifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + mags_to_spawn = 3 + +/datum/armament_entry/hecu/primary/assaultrifle/m16 + item_type = /obj/item/gun/ballistic/automatic/m16 + max_purchase = 1 + cost = 14 + magazine = /obj/item/ammo_box/magazine/m16 + +/datum/armament_entry/hecu/primary/shotgun + subcategory = ARMAMENT_SUBCATEGORY_SHOTGUN + mags_to_spawn = 1 + +/datum/armament_entry/hecu/primary/shotgun/shotgun_highcap + item_type = /obj/item/gun/ballistic/shotgun/m23 + max_purchase = 2 + cost = 5 + magazine = /obj/item/storage/box/ammo_box/shotgun_12g + magazine_cost = 4 + +/datum/armament_entry/hecu/primary/shotgun/autoshotgun_pump + item_type = /obj/item/gun/ballistic/shotgun/automatic/as2 + max_purchase = 1 + cost = 7 + magazine = /obj/item/storage/box/ammo_box/shotgun_12g + magazine_cost = 4 + +/datum/armament_entry/hecu/primary/special + subcategory = ARMAMENT_SUBCATEGORY_SPECIAL + mags_to_spawn = 2 + +/datum/armament_entry/hecu/primary/special/sniper_rifle + item_type = /obj/item/gun/ballistic/automatic/cfa_rifle + max_purchase = 1 + cost = 18 + +/datum/armament_entry/hecu/primary/special/hmg + item_type = /obj/item/mounted_machine_gun_folded + max_purchase = 1 + cost = 22 + magazine = /obj/item/ammo_box/magazine/mmg_box + mags_to_spawn = 1 + magazine_cost = 2 + +/obj/item/storage/box/ammo_box/shotgun_12g + +/obj/item/storage/box/ammo_box/shotgun_12g/PopulateContents() + new /obj/item/ammo_box/magazine/m12g(src) + new /obj/item/ammo_box/magazine/m12g(src) + new /obj/item/ammo_box/magazine/m12g(src) + new /obj/item/ammo_box/magazine/m12g/slug(src) + new /obj/item/ammo_box/magazine/m12g/slug(src) + new /obj/item/ammo_box/magazine/m12g/slug(src) + new /obj/item/ammo_box/magazine/m12g/dragon(src) diff --git a/modular_skyrat/modules/blueshield/code/blueshield.dm b/modular_skyrat/modules/blueshield/code/blueshield.dm new file mode 100644 index 000000000000..5243c5d97717 --- /dev/null +++ b/modular_skyrat/modules/blueshield/code/blueshield.dm @@ -0,0 +1,107 @@ +/datum/job/blueshield + title = JOB_BLUESHIELD + description = "Protect heads of staff, get your fancy gun stolen, cry as the captain touches the supermatter." + auto_deadmin_role_flags = DEADMIN_POSITION_SECURITY + department_head = list(JOB_NT_REP) + faction = FACTION_STATION + total_positions = 1 + spawn_positions = 1 + supervisors = "Central Command and the Nanotrasen Consultant" + selection_color = "#c6ffe0" + minimal_player_age = 7 + exp_requirements = 2400 + exp_required_type = EXP_TYPE_CREW + exp_required_type_department = EXP_TYPE_COMMAND + exp_granted_type = EXP_TYPE_CREW + + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_CMD + + outfit = /datum/outfit/job/blueshield + plasmaman_outfit = /datum/outfit/plasmaman/blueshield + display_order = JOB_DISPLAY_ORDER_BLUESHIELD + bounty_types = CIV_JOB_SEC + + department_for_prefs = /datum/job_department/captain + + departments_list = list( + /datum/job_department/central_command, + /datum/job_department/command, + ) + liver_traits = list(TRAIT_PRETENDER_ROYAL_METABOLISM) + + family_heirlooms = list(/obj/item/bedsheet/captain, /obj/item/clothing/head/beret/blueshield) + + mail_goodies = list( + /obj/item/storage/fancy/cigarettes/cigars/havana = 10, + /obj/item/stack/spacecash/c500 = 3, + /obj/item/disk/nuclear/fake/obvious = 2, + /obj/item/clothing/head/collectable/captain = 4, + /obj/projectile/bullet/b460 = 1 + ) + + veteran_only = TRUE + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS + +/datum/outfit/job/blueshield + name = "Blueshield" + jobtype = /datum/job/blueshield + uniform = /obj/item/clothing/under/rank/security/blueshield + suit = /obj/item/clothing/suit/armor/vest/blueshield + gloves = /obj/item/clothing/gloves/tackler/combat/insulated + id = /obj/item/card/id/advanced/centcom + shoes = /obj/item/clothing/shoes/jackboots + ears = /obj/item/radio/headset/headset_bs/alt + glasses = /obj/item/clothing/glasses/hud/security/sunglasses + backpack_contents = list( + /obj/item/storage/box/gunset/blueshield = 1, + /obj/item/melee/baton/security/loaded = 1,) + implants = list(/obj/item/implant/mindshield) + backpack = /obj/item/storage/backpack/blueshield + satchel = /obj/item/storage/backpack/satchel/blueshield + duffelbag = /obj/item/storage/backpack/duffel/blueshield + head = /obj/item/clothing/head/beret/blueshield + box = /obj/item/storage/box/survival/security + belt = /obj/item/modular_computer/tablet/pda/security + + id_trim = /datum/id_trim/job/blueshield + +/datum/outfit/plasmaman/blueshield + name = "Blueshield Plasmaman" + + head = /obj/item/clothing/head/helmet/space/plasmaman/blueshield + uniform = /obj/item/clothing/under/plasmaman/blueshield + +/obj/item/storage/box/gunset/blueshield + name = "CMG-1 Gunset" + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/gun/ballistic/automatic/cmg/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/blueshield/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/cmg/nomag(src) + new /obj/item/ammo_box/magazine/cmgm45(src) + new /obj/item/ammo_box/magazine/cmgm45(src) + new /obj/item/ammo_box/magazine/cmgm45/lethal(src) + new /obj/item/ammo_box/magazine/cmgm45/lethal(src) + new /obj/item/suppressor(src) + +/obj/item/ammo_casing/energy/laser/hellfire/bs + projectile_type = /obj/projectile/beam/laser/hellfire + e_cost = 83 //Lets it squeeze out a few more shots + select_name = "maim" + +/obj/item/gun/energy/laser/hellgun/blueshield + name = "\improper Allstar SC-3 PDW 'Hellfire'" + desc = "A prototype energy carbine, despite NT's ban on hellfire weaponry due to negative press. \ + Allstar continued to work on it, compacting it into a small form-factor for personal defense. \ + As part of the Asset Retention Program created by Nanotrasen, Allstar's prototype began to be put into use." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + icon_state = "hellfirepdw" + ammo_type = list(/obj/item/ammo_casing/energy/laser/hellfire/bs) + company_flag = COMPANY_ALLSTAR diff --git a/modular_skyrat/modules/cargo/code/goodies.dm b/modular_skyrat/modules/cargo/code/goodies.dm new file mode 100644 index 000000000000..0eeba4a6e456 --- /dev/null +++ b/modular_skyrat/modules/cargo/code/goodies.dm @@ -0,0 +1,107 @@ +////////////////////////////////////////////////////////////////////////////// +//////////////////////// Emergency Race Stuff //////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/goody/airsuppliesnitrogen + name = "Emergency Air Supplies (Nitrogen)" + desc = "A vox breathing mask and nitrogen tank." + cost = PAYCHECK_MEDIUM + contains = list(/obj/item/tank/internals/nitrogen/belt, + /obj/item/clothing/mask/breath/vox) + +/datum/supply_pack/goody/airsuppliesoxygen + name = "Emergency Air Supplies (Oxygen)" + desc = "A breathing mask and emergency oxygen tank." + cost = PAYCHECK_MEDIUM + contains = list(/obj/item/tank/internals/emergency_oxygen, + /obj/item/clothing/mask/breath) + +/datum/supply_pack/goody/airsuppliesplasma + name = "Emergency Air Supplies (Plasma)" + desc = "A breathing mask and plasmaman plasma tank." + cost = PAYCHECK_MEDIUM + contains = list(/obj/item/tank/internals/plasmaman/belt, + /obj/item/clothing/mask/breath) + +////////////////////////////////////////////////////////////////////////////// +///////////////////////////// Misc Stuff ///////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/goody/crayons + name = "Box of Crayons" + desc = "Colorful!" + cost = PAYCHECK_MEDIUM * 2 + contains = list(/obj/item/storage/crayons) + +/datum/supply_pack/goody/diamondring + name = "Diamond Ring" + desc = "Show them your love is like a diamond: unbreakable and everlasting. No refunds." + cost = PAYCHECK_MEDIUM * 50 + contains = list(/obj/item/storage/fancy/ringbox/diamond) + crate_name = "diamond ring crate" + +/datum/supply_pack/goody/paperbin + name = "Paper Bin" + desc = "Pushing paperwork is always easier when you have paper to push!" + cost = PAYCHECK_MEDIUM * 4 + contains = list(/obj/item/paper_bin) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Weapons or Ammo ///////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/goody/gunmaint + name = "Gun Maintenance Kits" + desc = "Keep your pa's rifle in best condition, with two sets of cleaning supplies. Or your standard issue pistol if you're an itchy trigger, we're not here to judge." + cost = PAYCHECK_MEDIUM * 3 + contains = list(/obj/item/gun_maintenance_supplies, + /obj/item/gun_maintenance_supplies) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Carpet Packs //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/goody/carpet + name = "Classic Carpet Single-Pack" + desc = "Plasteel floor tiles getting on your nerves? This 50 units stack of extra soft carpet will tie any room together." + cost = PAYCHECK_MEDIUM * 3 + contains = list(/obj/item/stack/tile/carpet/fifty) + +/datum/supply_pack/goody/carpet/black + name = "Black Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/black/fifty) + +/datum/supply_pack/goody/carpet/premium + name = "Royal Black Carpet Single-Pack" + desc = "Exotic carpets for all your decorating needs. This 50 unit stack of extra soft carpet will tie any room together." + cost = PAYCHECK_MEDIUM * 3.5 + contains = list(/obj/item/stack/tile/carpet/royalblack/fifty) + +/datum/supply_pack/goody/carpet/premium/royalblue + name = "Royal Blue Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/royalblue/fifty) + +/datum/supply_pack/goody/carpet/premium/red + name = "Red Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/red/fifty) + +/datum/supply_pack/goody/carpet/premium/purple + name = "Purple Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/purple/fifty) + +/datum/supply_pack/goody/carpet/premium/orange + name = "Orange Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/orange/fifty) + +/datum/supply_pack/goody/carpet/premium/green + name = "Green Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/green/fifty) + +/datum/supply_pack/goody/carpet/premium/cyan + name = "Cyan Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/cyan/fifty) + +/datum/supply_pack/goody/carpet/premium/blue + name = "Blue Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/blue/fifty) + diff --git a/modular_skyrat/modules/cargo/code/packs.dm b/modular_skyrat/modules/cargo/code/packs.dm new file mode 100644 index 000000000000..b32039aa8828 --- /dev/null +++ b/modular_skyrat/modules/cargo/code/packs.dm @@ -0,0 +1,598 @@ +/// Cost of the crate. DO NOT GO ANY LOWER THAN X1.4 the "CARGO_CRATE_VALUE" value if using regular crates, or infinite profit will be possible! + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////////// Livestock /////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/critter/doublecrab + name = "Crab Crate" + desc = "Contains two crabs. Get your crab on!" + cost = CARGO_CRATE_VALUE * 4 + contains = list(/mob/living/simple_animal/crab, + /mob/living/simple_animal/crab) + crate_name = "look sir free crabs" + +/datum/supply_pack/critter/mouse + name = "Mouse Crate" + desc = "Good for snakes and lizards of all ages. Contains six feeder mice." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/mob/living/simple_animal/mouse,) + crate_name = "mouse crate" + +/datum/supply_pack/critter/mouse/generate() + . = ..() + for(var/i in 1 to 5) + new /mob/living/simple_animal/mouse(.) + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////////// Medical ///////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/medical/anesthetics + name = "Anesthetics Crate" + desc = "Contains two of the following: Morphine bottles, syringes, breath masks, and anesthetic tanks. Requires Medical Access to open." + access = ACCESS_MEDICAL + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/reagent_containers/glass/bottle/morphine, + /obj/item/reagent_containers/glass/bottle/morphine, + /obj/item/reagent_containers/syringe, + /obj/item/reagent_containers/syringe, + /obj/item/clothing/mask/breath, + /obj/item/clothing/mask/breath, + /obj/item/tank/internals/anesthetic, + /obj/item/tank/internals/anesthetic,) + crate_name = "anesthetics crate" + +/datum/supply_pack/medical/bodybags + name = "Bodybags" + desc = "For when the bodies hit the floor. Contains 4 boxes of bodybags." + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/box/bodybags, + /obj/item/storage/box/bodybags, + /obj/item/storage/box/bodybags, + /obj/item/storage/box/bodybags,) + crate_name = "bodybag crate" + +/datum/supply_pack/medical/firstaidmixed + name = "Mixed Medical Kits" + desc = "Contains one of each medical kits for dealing with a variety of injured crewmembers." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/storage/medkit/toxin, + /obj/item/storage/medkit/o2, + /obj/item/storage/medkit/brute, + /obj/item/storage/medkit/fire, + /obj/item/storage/medkit/regular) + crate_name = "medical kit crate" + +/datum/supply_pack/medical/medipens + name = "Epinephrine Medipens" + desc = "Contains two boxes of epinephrine medipens. Each box contains seven pens." + cost = CARGO_CRATE_VALUE * 4.5 + contains = list(/obj/item/storage/box/medipens, + /obj/item/storage/box/medipens) + crate_name = "medipen crate" + +/datum/supply_pack/medical/modsuit_medical + name = "Medical MODsuit Crate" + desc = "Contains a single MODsuit, built to standard medical specifications." + cost = CARGO_CRATE_VALUE * 13 + access = ACCESS_MEDICAL + contains = list(/obj/item/mod/control/pre_equipped/medical) + crate_name = "medical MODsuit crate" + crate_type = /obj/structure/closet/crate/secure //No medical varient with security locks. + +/datum/supply_pack/medical/compact_defib + name = "Compact Defibrillator Crate" + desc = "Contains a single compact defibrillator. Capable of being worn as a belt." + cost = CARGO_CRATE_VALUE * 5 + access = ACCESS_MEDICAL + contains = list(/obj/item/defibrillator/compact) + crate_name = "compact defibrillator crate" + +/datum/supply_pack/medical/medigun + name = "CWM-479 Medigun" + desc = "Contains a single VeyMedical CWM-479 model medical gun; cells not included." + cost = CARGO_CRATE_VALUE * 30 + access = ACCESS_MEDICAL + contains = list(/obj/item/storage/briefcase/medicalgunset/standard) + crate_name = "CWM-479 medigun crate" + +/datum/supply_pack/medical/medicells + name = "Medicell Replacement Crate" + desc = "Contains the tier I Medigun cells." + cost = CARGO_CRATE_VALUE * 5 + access = ACCESS_MEDICAL + contains = list(/obj/item/weaponcell/medical/brute, + /obj/item/weaponcell/medical/burn, + /obj/item/weaponcell/medical/toxin) + crate_name = "medicell replacement crate" + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Security //////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/security/MODsuit_security + name = "Security MODsuit Crate" + desc = "Contains a single armored up MODsuit, built to standard security specifications." + cost = CARGO_CRATE_VALUE * 16 + access_view = ACCESS_SECURITY + contains = list(/obj/item/mod/control/pre_equipped/security) + crate_name = "security MODsuit crate" + +/datum/supply_pack/security/armor + name = "Armor Crate" + desc = "Three vests of well-rounded, decently-protective armor. Requires Security access to open." + cost = CARGO_CRATE_VALUE * 2 + access_view = ACCESS_SECURITY + contains = list(/obj/item/clothing/suit/armor/vest/alt, + /obj/item/clothing/suit/armor/vest/alt, + /obj/item/clothing/suit/armor/vest/alt) + crate_name = "armor crate" + +/datum/supply_pack/security/deployablebarricades + name = "C.U.C.K.S Deployable Barricades" + desc = "Two cases of deployable barricades, for all your fortification needs." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/storage/barricade, + /obj/item/storage/barricade,) + crate_name = "C.U.C.K.S Crate" + + +////////////////////////////////////////////////////////////////////////////// +///////////////////////////// Engineering //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/engineering/industrial_rcd + name = "Industrial RCD Crate" + desc = "Manufactured at a high-tech NT production facility, this pack contains 2 industrial RCDs with expanded matter reserves and upgraded deconstructors. Requires CE Access to open." + access = ACCESS_CE //These contain all upgrades and ~2.5x as much matter. The least we can do is lock it behind CE. + contains = list(/obj/item/construction/rcd/combat, + /obj/item/construction/rcd/combat) + cost = CARGO_CRATE_VALUE * 40 + crate_name = "industrial RCD crate" + crate_type = /obj/structure/closet/crate/secure/engineering + +/datum/supply_pack/engineering/material_pouches + name = "Material Pouches Crate" + desc = "Contains three material pouches." + access_view = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/storage/bag/material, + /obj/item/storage/bag/material, + /obj/item/storage/bag/material) + cost = CARGO_CRATE_VALUE * 15 + crate_name = "material pouches crate" + +/datum/supply_pack/engineering/doublecap_tanks + name = "Double Extended Emergency Tank Crate" + desc = "Contains four double extended-capacity emergency tanks." + access_view = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/tank/internals/emergency_oxygen/double, + /obj/item/tank/internals/emergency_oxygen/double, + /obj/item/tank/internals/emergency_oxygen/double, + /obj/item/tank/internals/emergency_oxygen/double) + cost = CARGO_CRATE_VALUE * 15 + crate_name = "double extended emergency tank crate" + +/datum/supply_pack/engineering/advanced_extinguisher + name = "Advanced Foam Extinguisher Crate" + desc = "Contains advanced fire extinguishers which use foam as extinguishing agent." + access_view = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/extinguisher/advanced, + /obj/item/extinguisher/advanced, + /obj/item/extinguisher/advanced) + cost = CARGO_CRATE_VALUE * 18 + crate_name = "advanced extinguisher crate" + +/datum/supply_pack/engineering/modsuit_engineering + name = "Engineering MODsuit Crate" + desc = "Contains a single MODsuit, built to standard engineering specifications." + access = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/mod/control/pre_equipped/engineering) + cost = CARGO_CRATE_VALUE * 13 + crate_name = "engineering MODsuit crate" + crate_type = /obj/structure/closet/crate/secure/engineering + +/datum/supply_pack/engineering/modsuit_atmospherics + name = "Atmospherics MODsuit Crate" + desc = "Contains a single MODsuit, built to standard atmospherics specifications." + access = ACCESS_ENGINE_EQUIP + contains = list(/obj/item/mod/control/pre_equipped/atmospheric) + cost = CARGO_CRATE_VALUE * 16 + crate_name = "atmospherics MODsuit crate" + crate_type = /obj/structure/closet/crate/secure/engineering + +/datum/supply_pack/engineering/engi_inducers + name = "NT-150 Industrial Power Inducers Crate" + desc = "An improved model over the NT-75 EPI, the NT-150 charges at double the rate and contains an improved powercell. Contains two engineering-spec Inducers." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/inducer, + /obj/item/inducer) + crate_name = "engineering inducer crate" + crate_type = /obj/structure/closet/crate/engineering/electrical + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Misc Crates ///////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/misc/medibeam //Moved to Misc so Medical can't order them for free through department consoles and break the economy. + name = "Medical Beam Gun" + desc = "Nanotrasen offers you, for an exorbatant fee, the ability to lease one of their ERTs favorite gadgets, the Medical Beam Gun" + cost = 1000000 //Special case, we don't want to make this in terms of crates because having bikes be a million credits is the whole meme. + contains = list(/obj/item/gun/medbeam) + crate_name = "medical beamgun crate" + +/datum/supply_pack/misc/painting + name = "Advanced Art Supplies" + desc = "Bring out your artistic spirit with these advanced art supplies. Contains coloring supplies, cloth for canvas, and two easels to work with!" + cost = CARGO_CRATE_VALUE * 2.2 + contains = list(/obj/structure/easel, + /obj/structure/easel, + /obj/item/toy/crayon/spraycan, + /obj/item/toy/crayon/spraycan, + /obj/item/storage/crayons, + /obj/item/storage/crayons, + /obj/item/toy/crayon/white, + /obj/item/toy/crayon/white, + /obj/item/toy/crayon/rainbow, + /obj/item/toy/crayon/rainbow, + /obj/item/stack/sheet/cloth/ten, + /obj/item/stack/sheet/cloth/ten) + crate_name = "advanced art supplies" + +/datum/supply_pack/service/paintcan + name = "Adaptive Paintcan" + desc = "Give things a splash of color with this experimental color-changing can of paint! Sellers note: We are not responsible for lynchings carried out by angry janitors, security officers, or any other crewmembers as a result of you using this." + cost = CARGO_CRATE_VALUE * 15 + contains = list(/obj/item/paint/anycolor) + +/datum/supply_pack/misc/coloredsheets + name = "Bedsheet Crate" + desc = "Give your night life a splash of color with this crate filled with bedsheets! Contains a total of nine different-colored sheets." + cost = CARGO_CRATE_VALUE * 2.5 + contains = list(/obj/item/bedsheet/blue, + /obj/item/bedsheet/green, + /obj/item/bedsheet/orange, + /obj/item/bedsheet/purple, + /obj/item/bedsheet/red, + /obj/item/bedsheet/yellow, + /obj/item/bedsheet/brown, + /obj/item/bedsheet/black, + /obj/item/bedsheet/rainbow) + crate_name = "colored bedsheet crate" + +/datum/supply_pack/misc/candles + name = "Candle Crate" + desc = "Set up a romantic dinner or host a séance with these extra candles and crayons." + cost = CARGO_CRATE_VALUE * 1.5 + contains = list(/obj/item/storage/fancy/candle_box, + /obj/item/storage/fancy/candle_box, + /obj/item/storage/box/matches) + crate_name = "candle crate" + +/* +/datum/supply_pack/misc/jukebox + name = "Jukebox Crate" + desc = "Contains a regular old jukebox. It can play music!" + cost = CARGO_CRATE_VALUE * 20 + contains = list(/obj/machinery/jukebox) + crate_name = "jukebox crate" + +/datum/supply_pack/misc/jukebox_disco + name = "Radiant Dance Machine Crate" + desc = "Contains the new and improved Radiant Dance Machine Mark IV! Capable of playing a large selections of music, while projecting a fabulous lightshow." + cost = CARGO_CRATE_VALUE * 50 + contains = list(/obj/machinery/jukebox/disco) + crate_name = "dance machine crate" +*/ + + +/datum/supply_pack/service/snowmobile + name = "Snowmobile kit" + desc = "trapped on a frigid wasteland? need to get around fast? purchase a refurbished snowmobile, with a FREE 10 microsecond warranty!" + cost = 1500 // 1000 points cheaper than ATV + contains = list(/obj/vehicle/ridden/atv/snowmobile = 1, + /obj/item/key/atv = 1, + /obj/item/clothing/mask/gas/explorer = 1) + crate_name = "snowmobile kit" + crate_type = /obj/structure/closet/crate/large + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Food Stuff ////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/organic/combomeal + name = "Burger Combo Crate" + desc = "We value our customers at the Greasy Griddle, so much so that we're willing to deliver -just for you.- Contains two combo meals, consisting of a Burger, Fries, and pack of chicken nuggets!" + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/food/burger/cheese, + /obj/item/food/burger/cheese, + /obj/item/food/fries, + /obj/item/food/fries, + /obj/item/storage/fancy/nugget_box, + /obj/item/storage/fancy/nugget_box) + crate_name = "burger-n-nuggs combo meal" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/organic/fiestatortilla + name = "Fiesta Crate" + desc = "Spice up the kitchen with this fiesta themed food order! Contains 8 tortilla based food items and some hot-sauce." + cost = CARGO_CRATE_VALUE * 4.5 + contains = list(/obj/item/food/taco, + /obj/item/food/taco, + /obj/item/food/taco/plain, + /obj/item/food/taco/plain, + /obj/item/food/enchiladas, + /obj/item/food/enchiladas, + /obj/item/food/carneburrito, + /obj/item/food/cheesyburrito, + /obj/item/reagent_containers/glass/bottle/capsaicin) + crate_name = "fiesta crate" + +/datum/supply_pack/organic/fakemeat + name = "Meat Crate 'Synthetic'" + desc = "Run outta meat already? Keep the lizards content with this freezer filled with cruelty-free and chemically compounded meat! Contains 12 slabs of meat product, and 4 slabs of *carp*." + cost = CARGO_CRATE_VALUE * 2.25 + contains = list(/obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/meat/slab/meatproduct, + /obj/item/food/fishmeat/carp/imitation, + /obj/item/food/fishmeat/carp/imitation, + /obj/item/food/fishmeat/carp/imitation, + /obj/item/food/fishmeat/carp/imitation) + crate_name = "meaty crate" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/mixedboxes + name = "Mixed Ingredient Boxes" + desc = "Get overwhelmed with inspiration by ordering these boxes of surprise ingredients! Get four boxes filled with an assortment of products!" + cost = CARGO_CRATE_VALUE * 2 + contains = list(/obj/item/storage/box/ingredients/wildcard, + /obj/item/storage/box/ingredients/wildcard, + /obj/item/storage/box/ingredients/wildcard, + /obj/item/storage/box/ingredients/wildcard) + crate_name = "wildcard food crate" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/fcsurplus + name = "Fine Cuisine Assortment Value Pack" + desc = "Chef slop boring? Have high-maintenance crewmembers that with wings? Maybe you just want to revel in the sinful delight that are Cheese Curds? The Finest of our trade union has made the pack for you, containing a mix of fine oils, vinegar, and exceptionally rare ingredients." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/food/canned/tomatoes, + /obj/item/food/canned/tomatoes, + /obj/item/food/canned/pine_nuts, + /obj/item/food/canned/pine_nuts, + /obj/item/food/canned_jellyfish, + /obj/item/food/desert_snails, + /obj/item/food/larvae, + /obj/item/food/moonfish_eggs) + crate_name = "fine cuisine assortment pack" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/qualityoilbulk + name = "Quality Oil Bulk Pack" + desc = "Normal cooking oil not cutting it? Chef throw all the quality stuff in the frier because they thought it was funny? Well, We got you covered, Introducing a bulk pack of Ten (10) bottles of our finest oils, blended for the perfect taste in cold recipes, and a resistance for going acrid when cooking." + cost = CARGO_CRATE_VALUE * 9 + contains = list(/obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil, + /obj/item/reagent_containers/food/condiment/quality_oil) + crate_name = "bulk quality oil pack" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/vinegarbulk + name = "Vinegar Bulk Pack" + desc = "Mothic Cuisine night? The winged fellows in port? Well, We'll have you cooking in no time. Refined from several rich wines and cultivated for just the right bite, This pack Ten (10) Bottles of vinegar for the perfect dressings and sauces." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar, + /obj/item/reagent_containers/food/condiment/vinegar) + crate_name = "bulk vinegar pack" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/bulkcanmoff + name = "Bulk Mothic Canned Goods" + desc = "Trying your hand at pestos and sauces? Cant just grow the stuff and can it yourself? Well, No matters, No worries, We here have you covered with Five (5) cans of tomatoes and pine nuts to help care for your winged friends." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/food/canned/tomatoes, + /obj/item/food/canned/tomatoes, + /obj/item/food/canned/tomatoes, + /obj/item/food/canned/tomatoes, + /obj/item/food/canned/tomatoes, + /obj/item/food/canned/pine_nuts, + /obj/item/food/canned/pine_nuts, + /obj/item/food/canned/pine_nuts, + /obj/item/food/canned/pine_nuts, + /obj/item/food/canned/pine_nuts) + crate_name = "bulk moffic pack" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/bulkcanliz + name = "Bulk Lizard Goods" + desc = "Having some devious tastes? One of your scalie friends wanting something that isn't fried mystery meat? Well you're just one order away from from the perfect pleaser. Containing Three (3) Cans of our finest-sourced canned jellyfish, snails and bee larvae, An addition of Three (3) packs of cruelty free Moonfish eggs might get their hearts." + cost = CARGO_CRATE_VALUE * 3.5 + contains = list(/obj/item/food/canned_jellyfish, + /obj/item/food/canned_jellyfish, + /obj/item/food/canned_jellyfish, + /obj/item/food/desert_snails, + /obj/item/food/desert_snails, + /obj/item/food/desert_snails, + /obj/item/food/moonfish_eggs, + /obj/item/food/moonfish_eggs, + /obj/item/food/moonfish_eggs, + /obj/item/food/larvae, + /obj/item/food/larvae, + /obj/item/food/larvae) + crate_name = "bulk lizard pack" + crate_type = /obj/structure/closet/crate/freezer + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Pack Type /////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/service/buildabar + name = "Build a Bar Crate" + desc = "Looking to set up your own little safe haven? Get a jump-start on it with this handy kit. Contains circuitboards for bar equipment, some parts, and some basic bartending supplies. (Glass not included)" + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/storage/box/drinkingglasses, + /obj/item/storage/box/drinkingglasses, + /obj/item/storage/part_replacer/cargo, + /obj/item/stack/sheet/iron/ten, + /obj/item/stack/sheet/iron/five, + /obj/item/stock_parts/cell/high, + /obj/item/stock_parts/cell/high, + /obj/item/stack/cable_coil, + /obj/item/book/manual/wiki/barman_recipes, + /obj/item/reagent_containers/food/drinks/shaker, + /obj/item/circuitboard/machine/chem_dispenser/drinks/beer, + /obj/item/circuitboard/machine/chem_dispenser/drinks, + /obj/item/circuitboard/machine/dish_drive) + crate_name = "build a bar crate" + +/datum/supply_pack/service/hydrohelper + name = "Hydro-Helper Circuit Pack" + desc = "Botany being lazy with something? Being refused circuit boards? grow your only little garden with these three boards. (seeds and parts not included)" + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/circuitboard/machine/hydroponics, + /obj/item/circuitboard/machine/hydroponics, + /obj/item/circuitboard/machine/hydroponics) + crate_name = "garden crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/service/janitor/janpimp + name = "Custodial Cruiser" + desc = "Clown steal your ride? Assistant lock it in the dorms? Order a new one and get back to cleaning in style!" + cost = CARGO_CRATE_VALUE * 4 + access = ACCESS_JANITOR + contains = list(/obj/vehicle/ridden/janicart, + /obj/item/key/janitor) + crate_name = "janitor ride crate" + crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/service/janitor/janpimpkey + name = "Cruiser Keys" + desc = "Replacement Keys for the Custodial Cruiser." + cost = CARGO_CRATE_VALUE * 1.5 + access = ACCESS_JANITOR + contains = list(/obj/item/key/janitor) + crate_name = "key crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/service/janitor/janpremium + name = "Janitor Supplies (Premium)" + desc = "For when the mess is too big for a mop to handle. Contains, several cleaning grenades, some spare bottles of ammonia, two bars of soap, and an MCE (or Massive Cleaning Explosive)." + cost = CARGO_CRATE_VALUE * 6 + contains = list(/obj/item/soap/nanotrasen, + /obj/item/soap/nanotrasen, + /obj/item/grenade/clusterbuster/cleaner, + /obj/item/grenade/chem_grenade/cleaner, + /obj/item/grenade/chem_grenade/cleaner, + /obj/item/grenade/chem_grenade/cleaner, + /obj/item/reagent_containers/glass/bottle/ammonia, + /obj/item/reagent_containers/glass/bottle/ammonia, + /obj/item/reagent_containers/glass/bottle/ammonia) + crate_name = "premium janitorial crate" + +/datum/supply_pack/service/lamplight + name = "Lamp Light Crate" + desc = "Dealing with brownouts? Lights out across the station? Brighten things up with a pack of four lamps and flashlights." + cost = CARGO_CRATE_VALUE * 1.75 + contains = list(/obj/item/flashlight/lamp, + /obj/item/flashlight/lamp, + /obj/item/flashlight/lamp/green, + /obj/item/flashlight/lamp/green, + /obj/item/flashlight, + /obj/item/flashlight, + /obj/item/flashlight, + /obj/item/flashlight,) + crate_name = "lamp light crate" + +/datum/supply_pack/service/medieval + name = "Authentic Renaissance Faire Crate" + desc = "Contains two authentic suits of armor, swords, and two bows and cuirass' for the cowards hiding in the back." + cost = CARGO_CRATE_VALUE * 30 + contraband = TRUE + contains = list(/obj/item/clothing/suit/armor/riot/knight/larp/red, + /obj/item/clothing/gloves/plate/larp/red, + /obj/item/clothing/head/helmet/knight/red, + /obj/item/clothing/shoes/plate/larp/red, + /obj/item/claymore/weak/weaker, + /obj/item/clothing/shoes/plate/larp/blue, + /obj/item/clothing/suit/armor/riot/knight/larp/blue, + /obj/item/clothing/gloves/plate/larp/blue, + /obj/item/clothing/head/helmet/knight/blue, + /obj/item/claymore/weak/weaker, + /obj/item/clothing/suit/armor/vest/cuirass/larp, + /obj/item/clothing/suit/armor/vest/cuirass/larp, + /obj/item/gun/ballistic/bow, + /obj/item/gun/ballistic/bow, + /obj/item/storage/bag/quiver, + /obj/item/storage/bag/quiver, + /obj/item/clothing/head/helmet/knight/red, + /obj/item/clothing/head/helmet/knight/blue, + /obj/item/food/bread/plain) + crate_name = "vintage crate" + +/datum/supply_pack/organic/lavalandsamples + name = "Planetary Flora Samples" + desc = "A box of samples taken from the surface of Lavaland. Requires Hydroponics access to open." + cost = CARGO_CRATE_VALUE * 2 + access_view = ACCESS_HYDROPONICS + contains = list(/obj/item/seeds/lavaland/polypore, + /obj/item/seeds/lavaland/porcini, + /obj/item/seeds/lavaland/inocybe, + /obj/item/seeds/lavaland/ember, + /obj/item/seeds/lavaland/seraka, + /obj/item/seeds/star_cactus, + /obj/item/seeds/star_cactus) + crate_name = "planetary seeds crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/service/MODsuit_cargo + name = "Cargo Loader MODsuit Crate" + desc = "Contains a single quad-armed MODsuit, built to standard cargo specifications." + cost = CARGO_CRATE_VALUE * 13 + access_view = ACCESS_CARGO + contains = list(/obj/item/mod/control/pre_equipped/loader) + crate_name = "cargo MODsuit crate" + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Materials & Sheets ////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/materials/rawlumber + name = "20 Towercap Logs" + desc = "Set up a cookout or a classy beachside bonfire with these terrific towercaps!" + cost = CARGO_CRATE_VALUE * 3.5 + contains = list(/obj/item/grown/log) + crate_name = "lumber crate" + +/datum/supply_pack/materials/rawlumber/generate() + . = ..() + for(var/i in 1 to 19) + new /obj/item/grown/log(.) diff --git a/modular_skyrat/modules/goofsec/code/department_guards.dm b/modular_skyrat/modules/goofsec/code/department_guards.dm new file mode 100644 index 000000000000..01276a4da367 --- /dev/null +++ b/modular_skyrat/modules/goofsec/code/department_guards.dm @@ -0,0 +1,498 @@ +// /obj/item/clothing/under/rank/security/officer/blueshirt + +/obj/item/clothing/under/rank/security/officer/blueshirt/skyrat + icon_state = "barney_uniform" + worn_icon_state = "barney_uniform" + icon = 'modular_skyrat/master_files/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/uniform.dmi' + unique_reskin = null + +/obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/orderly + name = "orderly uniform" + icon_state = "orderly_uniform" + worn_icon_state = "orderly_uniform" + +/obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/engineering_guard + name = "engineering guard uniform" + icon_state = "engineering_guard_uniform" + worn_icon_state = "engineering_guard_uniform" + +/obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/customs_agent + name = "customs agent uniform" + icon_state = "customs_uniform" + worn_icon_state = "customs_uniform" + +/obj/item/clothing/suit/armor/vest/blueshirt/skyrat + icon_state = "barney_armor" + worn_icon_state = "barney_armor" + icon = 'modular_skyrat/master_files/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi' + unique_reskin = null + +/obj/item/clothing/suit/armor/vest/blueshirt/skyrat/guard + icon_state = "guard_armor" + worn_icon_state = "guard_armor" + +/obj/item/clothing/suit/armor/vest/blueshirt/skyrat/orderly + name = "armored orderly coat" + desc = "An armored coat, to keep you safe from unruly patients." + icon_state = "medical_coat" + worn_icon_state = "medical_coat" + +/obj/item/clothing/suit/armor/vest/blueshirt/skyrat/engineering_guard + name = "armored engineering guard coat" + desc = "An armored coat, to keep you safe from unruly patients." + icon_state = "engineering_coat" + worn_icon_state = "engineering_coat" + +/obj/item/clothing/suit/armor/vest/blueshirt/skyrat/customs_agent + name = "armored customs agent coat" + desc = "An armored coat, to keep you safe from unruly customers." + icon_state = "customs_coat" + worn_icon_state = "customs_coat" + +/obj/item/clothing/head/helmet/blueshirt/skyrat + icon_state = "barney_helm" + worn_icon_state = "barney_helm" + icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' + unique_reskin = null + +/obj/item/clothing/head/helmet/blueshirt/skyrat/guard + icon_state = "mallcop_helm" + worn_icon_state = "mallcop_helm" + +/obj/effect/landmark/start/orderly + name = "Orderly" + icon_state = "Orderly" + icon = 'modular_skyrat/master_files/icons/mob/landmarks.dmi' + +/datum/job/orderly + title = JOB_ORDERLY + description = "Defend the medical department, hold down idiots who refuse the vaccine, flex your muscles at people who fuck with medical." + department_head = list(JOB_CHIEF_MEDICAL_OFFICER) + faction = FACTION_STATION + total_positions = 2 + spawn_positions = 2 + supervisors = "the chief medical officer, NOT SECURITY" + selection_color = "#ffeeee" + exp_granted_type = EXP_TYPE_CREW + + outfit = /datum/outfit/job/orderly + plasmaman_outfit = /datum/outfit/plasmaman/medical + + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_MED + + display_order = JOB_DISPLAY_ORDER_ORDERLY + bounty_types = CIV_JOB_MED + departments_list = list( + /datum/job_department/medical, + ) + + family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law, /obj/item/clothing/head/beret/sec) + + mail_goodies = list( + /obj/item/food/donut/caramel = 10, + /obj/item/food/donut/matcha = 10, + /obj/item/food/donut/blumpkin = 5, + /obj/item/clothing/mask/whistle = 5, + /obj/item/melee/baton/security/boomerang/loaded = 1 + ) + + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + +/datum/outfit/job/orderly + name = "Orderly" // You forgot your vaccine *flexes muscles* + jobtype = /datum/job/orderly + + belt = /obj/item/modular_computer/tablet/pda/medical + ears = /obj/item/radio/headset/headset_med + uniform = /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/orderly + shoes = /obj/item/clothing/shoes/sneakers/white + head = /obj/item/clothing/head/helmet/blueshirt/skyrat/guard + suit = /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/orderly + + backpack = /obj/item/storage/backpack/medic + satchel = /obj/item/storage/backpack/satchel/med + duffelbag = /obj/item/storage/backpack/duffelbag/med + box = /obj/item/storage/box/survival/medical + + id_trim = /datum/id_trim/job/orderly + +/datum/id_trim/job/orderly + assignment = "Orderly" + trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi' + trim_state = "trim_orderly" + sechud_icon_state = SECHUD_ORDERLY + extra_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_PHARMACY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM, ACCESS_WEAPONS) + minimal_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_PHARMACY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM, ACCESS_WEAPONS) + config_job = "orderly" + template_access = list(ACCESS_CAPTAIN, ACCESS_CMO, ACCESS_CHANGE_IDS) + job = /datum/job/orderly + +/obj/effect/landmark/start/science_guard + name = "Science Guard" + icon_state = "Science Guard" + icon = 'modular_skyrat/master_files/icons/mob/landmarks.dmi' + +/datum/job/science_guard + title = JOB_SCIENCE_GUARD // I'm a little busy here, Calhoun. + description = "Figure out why the emails aren't working, keep an eye on those eggheads, keep them safe from their mistakes." + department_head = list(JOB_RESEARCH_DIRECTOR) + faction = FACTION_STATION + total_positions = 2 + spawn_positions = 2 + supervisors = "the research director, NOT SECURITY" + selection_color = "#ffeeee" + exp_granted_type = EXP_TYPE_CREW + + outfit = /datum/outfit/job/science_guard + plasmaman_outfit = /datum/outfit/plasmaman/science + + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_SCI + + display_order = JOB_DISPLAY_ORDER_SCIENCE_GUARD + bounty_types = CIV_JOB_SCI + departments_list = list( + /datum/job_department/science, + ) + + family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law, /obj/item/clothing/head/beret/sec) + + mail_goodies = list( + /obj/item/food/donut/caramel = 10, + /obj/item/food/donut/matcha = 10, + /obj/item/food/donut/blumpkin = 5, + /obj/item/clothing/mask/whistle = 5, + /obj/item/melee/baton/security/boomerang/loaded = 1 + ) + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + +/datum/outfit/job/science_guard + name = "Science Guard" + jobtype = /datum/job/science_guard + + belt = /obj/item/modular_computer/tablet/pda/science + ears = /obj/item/radio/headset/headset_sci + uniform = /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat + shoes = /obj/item/clothing/shoes/sneakers/black + head = /obj/item/clothing/head/helmet/blueshirt/skyrat + suit = /obj/item/clothing/suit/armor/vest/blueshirt/skyrat + + backpack = /obj/item/storage/backpack/science + satchel = /obj/item/storage/backpack/satchel/science + duffelbag = /obj/item/storage/backpack/duffelbag/science + box = /obj/item/storage/box/survival/medical + + id_trim = /datum/id_trim/job/science_guard + +/datum/id_trim/job/science_guard + assignment = "Science Guard" + trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi' + trim_state = "trim_calhoun" + sechud_icon_state = SECHUD_SCIENCE_GUARD + extra_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_ROBOTICS, ACCESS_RND, ACCESS_ORDNANCE, ACCESS_ORDNANCE_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, + ACCESS_MECH_SCIENCE, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS, ACCESS_AUX_BASE, ACCESS_WEAPONS) + minimal_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_ROBOTICS, ACCESS_RND, ACCESS_ORDNANCE, ACCESS_ORDNANCE_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, + ACCESS_MECH_SCIENCE, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS, ACCESS_AUX_BASE, ACCESS_WEAPONS) + config_job = "science_guard" + template_access = list(ACCESS_CAPTAIN, ACCESS_RD, ACCESS_CHANGE_IDS) + job = /datum/job/science_guard + +/obj/effect/landmark/start/bouncer + name = "Bouncer" + icon_state = "Bouncer" + icon = 'modular_skyrat/master_files/icons/mob/landmarks.dmi' + +/datum/job/bouncer + title = JOB_BOUNCER + description = "Tell people they aren't on the list. Check people's IDs. Tell them to fuck off and get real ID." + department_head = list(JOB_HEAD_OF_PERSONNEL) + faction = FACTION_STATION + total_positions = 2 + spawn_positions = 2 + supervisors = "the head of personnel, NOT SECURITY" + selection_color = "#ffeeee" + exp_granted_type = EXP_TYPE_CREW + + outfit = /datum/outfit/job/bouncer + plasmaman_outfit = /datum/outfit/plasmaman/party_bouncer + + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_SRV + + display_order = JOB_DISPLAY_ORDER_BOUNCER + bounty_types = CIV_JOB_DRINK + departments_list = list( + /datum/job_department/service, + ) + + family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law, /obj/item/clothing/head/beret/sec) + + mail_goodies = list( + /obj/item/food/donut/caramel = 10, + /obj/item/food/donut/matcha = 10, + /obj/item/food/donut/blumpkin = 5, + /obj/item/clothing/mask/whistle = 5, + /obj/item/melee/baton/security/boomerang/loaded = 1 + ) + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + +/datum/outfit/job/bouncer + name = "Bouncer" // That ID looks a little suspect, pal. You ain't on the list, beat it. + jobtype = /datum/job/bouncer + + belt = /obj/item/modular_computer/tablet/pda/bar + ears = /obj/item/radio/headset/headset_srv + uniform = /obj/item/clothing/under/misc/bouncer + shoes = /obj/item/clothing/shoes/sneakers/black + head = /obj/item/clothing/head/helmet/blueshirt/skyrat/guard + suit = /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/guard + l_pocket = /obj/item/restraints/handcuffs + r_pocket = /obj/item/assembly/flash/handheld + backpack_contents = list( + /obj/item/melee/baton/security/loaded/departmental/service = 1, + ) + glasses = /obj/item/clothing/glasses/sunglasses + + backpack = /obj/item/storage/backpack + satchel = /obj/item/storage/backpack/satchel + duffelbag = /obj/item/storage/backpack/duffelbag + box = /obj/item/storage/box/survival + + id_trim = /datum/id_trim/job/bouncer + +/datum/id_trim/job/bouncer + assignment = "Bouncer" + trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi' + trim_state = "trim_bouncer" + sechud_icon_state = SECHUD_BOUNCER + extra_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM, ACCESS_THEATRE, ACCESS_WEAPONS) + minimal_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM, ACCESS_THEATRE, ACCESS_SERVICE, ACCESS_WEAPONS) + config_job = "bouncer" + template_access = list(ACCESS_CAPTAIN, ACCESS_HOP, ACCESS_CHANGE_IDS) + job = /datum/job/bouncer + +/obj/effect/landmark/start/customs_agent + name = "Customs Agent" + icon_state = "Customs Agent" + icon = 'modular_skyrat/master_files/icons/mob/landmarks.dmi' + +/datum/job/customs_agent + title = JOB_CUSTOMS_AGENT // No, you don't get to ship ten kilograms of cocaine to the Spinward Stellar Coalition. + description = "Inspect the packages coming to and from the station, protect the cargo department, beat the shit out of people trying to ship Cocaine to the Spinward Stellar Coalition." + department_head = list(JOB_QUARTERMASTER) + faction = FACTION_STATION + total_positions = 2 + spawn_positions = 2 + supervisors = "the quartermaster, NOT SECURITY" + selection_color = "#ffeeee" + exp_granted_type = EXP_TYPE_CREW + + outfit = /datum/outfit/job/customs_agent + plasmaman_outfit = /datum/outfit/plasmaman/cargo + + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_CAR + + display_order = JOB_DISPLAY_ORDER_CUSTOMS_AGENT + bounty_types = CIV_JOB_RANDOM + departments_list = list( + /datum/job_department/cargo, + ) + + family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law, /obj/item/clothing/head/beret/sec) + + mail_goodies = list( + /obj/item/food/donut/caramel = 10, + /obj/item/food/donut/matcha = 10, + /obj/item/food/donut/blumpkin = 5, + /obj/item/clothing/mask/whistle = 5, + /obj/item/melee/baton/security/boomerang/loaded = 1 + ) + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + +/datum/outfit/job/customs_agent + name = "Customs Agent" + jobtype = /datum/job/customs_agent + + belt = /obj/item/modular_computer/tablet/pda/cargo + ears = /obj/item/radio/headset/headset_cargo + shoes = /obj/item/clothing/shoes/sneakers/black + uniform = /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/customs_agent + head = /obj/item/clothing/head/helmet/blueshirt/skyrat/guard + suit = /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/customs_agent + + backpack = /obj/item/storage/backpack + satchel = /obj/item/storage/backpack/satchel + duffelbag = /obj/item/storage/backpack/duffelbag + box = /obj/item/storage/box/survival + + id_trim = /datum/id_trim/job/customs_agent + +/datum/id_trim/job/customs_agent + assignment = "Customs Agent" + trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi' + trim_state = "trim_customs" + sechud_icon_state = SECHUD_CUSTOMS_AGENT + extra_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MECH_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_WEAPONS) + minimal_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MECH_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_WEAPONS) + config_job = "customs_agent" + template_access = list(ACCESS_CAPTAIN, ACCESS_QM, ACCESS_CHANGE_IDS) + job = /datum/job/customs_agent + +/obj/effect/landmark/start/engineering_guard + name = "Engineering Guard" + icon_state = "Engineering Guard" + icon = 'modular_skyrat/master_files/icons/mob/landmarks.dmi' + +/datum/job/engineering_guard + title = JOB_ENGINEERING_GUARD // Listen here, this engine is a restricted area. Please leave if you aren't wearing a radioactive suit. + description = "Spy on the supermatter, keep an eye on atmospherics, fall asleep at your desk." + department_head = list(JOB_CHIEF_ENGINEER) + faction = FACTION_STATION + total_positions = 2 + spawn_positions = 2 + supervisors = "the chief engineer, NOT SECURITY" + selection_color = "#ffeeee" + exp_granted_type = EXP_TYPE_CREW + + outfit = /datum/outfit/job/engineering_guard + plasmaman_outfit = /datum/outfit/plasmaman/engineering + + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_ENG + + display_order = JOB_DISPLAY_ORDER_ENGINEER_GUARD + bounty_types = CIV_JOB_ENG + departments_list = list( + /datum/job_department/engineering, + ) + + family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law, /obj/item/clothing/head/beret/sec) + + mail_goodies = list( + /obj/item/food/donut/caramel = 10, + /obj/item/food/donut/matcha = 10, + /obj/item/food/donut/blumpkin = 5, + /obj/item/clothing/mask/whistle = 5, + /obj/item/melee/baton/security/boomerang/loaded = 1 + ) + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + +/datum/outfit/job/engineering_guard + name = "Engineering Guard" + jobtype = /datum/job/engineering_guard + + belt = /obj/item/modular_computer/tablet/pda/engineering + ears = /obj/item/radio/headset/headset_eng + shoes = /obj/item/clothing/shoes/workboots + uniform = /obj/item/clothing/under/rank/security/officer/blueshirt/skyrat/engineering_guard + head = /obj/item/clothing/head/helmet/blueshirt/skyrat/guard + suit = /obj/item/clothing/suit/armor/vest/blueshirt/skyrat/engineering_guard + + backpack = /obj/item/storage/backpack/industrial + satchel = /obj/item/storage/backpack/satchel/eng + duffelbag = /obj/item/storage/backpack/duffelbag/engineering + box = /obj/item/storage/box/survival/engineer + + id_trim = /datum/id_trim/job/engineering_guard + +/datum/id_trim/job/engineering_guard + assignment = "Engineering Guard" + trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi' + trim_state = "trim_engiguard" + sechud_icon_state = SECHUD_ENGINEERING_GUARD + extra_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_MECH_ENGINE, ACCESS_AUX_BASE, + ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM, ACCESS_WEAPONS) + minimal_access = list(ACCESS_BRIG_ENTRANCE, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_MECH_ENGINE, ACCESS_AUX_BASE, + ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM, ACCESS_WEAPONS) + config_job = "engineering_guard" + template_access = list(ACCESS_CAPTAIN, ACCESS_CE, ACCESS_CHANGE_IDS) + job = /datum/job/engineering_guard + +/obj/item/melee/baton/security/loaded/departmental + name = "departmental stun baton" + desc = "A stun baton fitted with a departmental area-lock, based off the station's blueprint layout - outside of its department, it only has three uses." + icon = 'modular_skyrat/modules/goofsec/icons/departmental_batons.dmi' + var/list/valid_areas = list() + var/emagged = FALSE + var/non_departmental_uses_left = 4 + +/obj/item/melee/baton/security/loaded/departmental/baton_attack(mob/living/target, mob/living/user, modifiers) + if(active && !emagged && cooldown_check <= world.time) + var/area/current_area = get_area(user) + if(!is_type_in_list(current_area, valid_areas)) + if(non_departmental_uses_left) + non_departmental_uses_left-- + if(non_departmental_uses_left) + say("[non_departmental_uses_left] non-departmental uses left!") + else + say("[src] is out of non-departmental uses! Return to your department and reactivate the baton to refresh it!") + else + target.visible_message(span_warning("[user] prods [target] with [src]. Luckily, it shut off due to being in the wrong area."), \ + span_warning("[user] prods you with [src]. Luckily, it shut off due to being in the wrong area.")) + active = FALSE + balloon_alert(user, "wrong department") + playsound(src, SFX_SPARKS, 75, TRUE, -1) + update_appearance() + return BATON_ATTACK_DONE + . = ..() + +/obj/item/melee/baton/security/loaded/departmental/attack_self(mob/user) + . = ..() + if(active) // just turned on + var/area/current_area = get_area(user) + if(!is_type_in_list(current_area, valid_areas)) + return + if(non_departmental_uses_left < 4) + say("Non-departmental uses refreshed!") + non_departmental_uses_left = 4 + +/obj/item/melee/baton/security/loaded/departmental/emag_act(mob/user) + if(!emagged) + if(user) + user.visible_message(span_warning("Sparks fly from [src]!"), + span_warning("You scramble [src]'s departmental lock, allowing it to be used freely!"), + span_hear("You hear a faint electrical spark.")) + balloon_alert(user, "emagged") + playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + emagged = TRUE + +/obj/item/melee/baton/security/loaded/departmental/medical + name = "medical stun baton" + desc = "A stun baton that doesn't operate outside of the Medical department, based off the station's blueprint layout. Can be used outside of Medical up to three times before needing to return!" + icon_state = "medical_baton" + valid_areas = list(/area/medical, /area/maintenance/department/medical, /area/shuttle/escape) + +/obj/item/melee/baton/security/loaded/departmental/engineering + name = "engineering stun baton" + desc = "A stun baton that doesn't operate outside of the Engineering department, based off the station's blueprint layout. Can be used outside of Engineering up to three times before needing to return!" + icon_state = "engineering_baton" + valid_areas = list(/area/engineering, /area/maintenance/department/engine, /area/shuttle/escape) + +/obj/item/melee/baton/security/loaded/departmental/science + name = "science stun baton" + desc = "A stun baton that doesn't operate outside of the Science department, based off the station's blueprint layout. Can be used outside of Science up to three times before needing to return!" + icon_state = "science_baton" + valid_areas = list(/area/science, /area/maintenance/department/science, /area/shuttle/escape) + +/obj/item/melee/baton/security/loaded/departmental/cargo + name = "cargo stun baton" + desc = "A stun baton that doesn't operate outside of the Cargo department, based off the station's blueprint layout. Can be used outside of Cargo up to three times before needing to return!" + icon_state = "cargo_baton" + valid_areas = list(/area/cargo, /area/maintenance/department/cargo, /area/shuttle/escape) + +/obj/item/melee/baton/security/loaded/departmental/service + name = "service stun baton" + desc = "A stun baton that doesn't operate outside of the Service department, based off the station's blueprint layout. Can be used outside of Service up to three times before needing to return!" + icon_state = "service_baton" + valid_areas = list(/area/service, /area/maintenance/department/chapel, /area/maintenance/department/crew_quarters, /area/shuttle/escape) // love mapping + +/obj/item/melee/baton/security/loaded/departmental/prison + name = "prison stun baton" + desc = "A stun baton that doesn't operate outside of the Prison, based off the station's blueprint layout. Can be used outside of the Prison up to three times before needing to return!" + icon_state = "prison_baton" + valid_areas = list(/area/security/prison, /area/security/processing, /area/shuttle/escape) // love mapping diff --git a/modular_skyrat/modules/goofsec/code/projectiles.dm b/modular_skyrat/modules/goofsec/code/projectiles.dm index 5c6ff37f26d8..5cd8ab56b964 100644 --- a/modular_skyrat/modules/goofsec/code/projectiles.dm +++ b/modular_skyrat/modules/goofsec/code/projectiles.dm @@ -48,6 +48,7 @@ ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/vintorez) shaded_charge = TRUE cell_type = /obj/item/stock_parts/cell/super + company_flag = COMPANY_OLDARMS /obj/item/ammo_casing/energy/laser/hardlight_bullet/vintorez name = "hardlight bullet vintorez casing" @@ -84,6 +85,7 @@ fire_delay = 10 shaded_charge = TRUE cell_type = /obj/item/stock_parts/cell/super + company_flag = COMPANY_ARMADYNE /obj/item/ammo_casing/energy/laser/hardlight_bullet/norwind name = "hardlight bullet norwind casing" @@ -112,6 +114,8 @@ can_bayonet = TRUE ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/ostwind) cell_type = /obj/item/stock_parts/cell/super + company_flag = COMPANY_ARMADYNE + /obj/item/ammo_casing/energy/laser/hardlight_bullet/ostwind name = "hardlight bullet norostwindwind casing" projectile_type = /obj/projectile/beam/laser/hardlight_bullet/ostwind @@ -142,6 +146,7 @@ ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/pitbull) shaded_charge = TRUE cell_type = /obj/item/stock_parts/cell/super + company_flag = COMPANY_BOLT /obj/item/ammo_casing/energy/laser/hardlight_bullet/pitbull name = "hardlight bullet pitbull casing" @@ -170,6 +175,7 @@ ammo_type = list(/obj/item/ammo_casing/energy/laser/hardlight_bullet/pcr) shaded_charge = TRUE cell_type = /obj/item/stock_parts/cell/super + company_flag = COMPANY_BOLT /obj/item/ammo_casing/energy/laser/hardlight_bullet/pcr name = "hardlight bullet pcr casing" diff --git a/modular_skyrat/modules/gun_cargo/code/armament_component.dm b/modular_skyrat/modules/gun_cargo/code/armament_component.dm new file mode 100644 index 000000000000..4f59979a950b --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_component.dm @@ -0,0 +1,516 @@ +#define MAX_AMMO_AMOUNT 10 +#define CARGO_CONSOLE 1 +#define IRN_CONSOLE 2 + +/datum/component/armament/cargo_gun + /// Selected amount of ammo to purchase + var/ammo_purchase_num = 1 + /// Is this set to private order + var/self_paid = FALSE + /// Cooldown to announce a requested order + COOLDOWN_DECLARE(radio_cooldown) + /// To cut down on redundant istypes(), what this component is attached to + var/console_state = null + /// If this is a tablet, the parent budgetordering + var/datum/computer_file/program/budgetorders/parent_prog + +/datum/component/armament/cargo_gun/Initialize(list/required_products, list/needed_access) + . = ..() + if(istype(parent, /obj/machinery/computer/cargo)) + console_state = CARGO_CONSOLE + else if(istype(parent, /obj/item/modular_computer)) + console_state = IRN_CONSOLE + +/datum/component/armament/cargo_gun/Destroy(force, silent) + parent_prog = null + . = ..() + +/datum/component/armament/cargo_gun/on_attack_hand(datum/source, mob/living/user) + return + +/datum/component/armament/cargo_gun/on_attackby(atom/target, obj/item, mob/user) + return + +/datum/component/armament/cargo_gun/ui_data(mob/user) + var/list/data = list() + + var/mob/living/carbon/human/the_person = user + var/obj/item/card/id/id_card + var/datum/bank_account/buyer = SSeconomy.get_dep_account(ACCOUNT_CAR) + + if(console_state == IRN_CONSOLE) + var/obj/item/computer_hardware/card_slot/card_slot = parent_prog.computer.all_components[MC_CARD] + id_card = card_slot.GetID() + else + if(istype(the_person)) + id_card = the_person.get_idcard(TRUE) + + var/budget_name = "Cargo Budget" + + if(id_card?.registered_account && (console_state == IRN_CONSOLE)) + if((ACCESS_HEADS in id_card.access) || (ACCESS_QM in id_card.access)) + parent_prog.requestonly = FALSE + buyer = SSeconomy.get_dep_account(id_card.registered_account.account_job.paycheck_department) + parent_prog.can_approve_requests = TRUE + else + parent_prog.requestonly = TRUE + parent_prog.can_approve_requests = FALSE + else + parent_prog?.requestonly = TRUE + + if(id_card) + budget_name = self_paid ? id_card.name : buyer.account_holder + + data["budget_name"] = budget_name + + data["budget_points"] = self_paid ? id_card?.registered_account?.account_balance : buyer?.account_balance + data["ammo_amount"] = ammo_purchase_num + data["self_paid"] = !!self_paid + data["armaments_list"] = list() + + for(var/armament_category as anything in GLOB.armament_entries) + var/illegal_failure + + for(var/company as anything in SSgun_companies.companies) + if(company != armament_category) + continue + + var/datum/gun_company/selected_company = SSgun_companies.companies[company] + + if(!(console_state == CARGO_CONSOLE) && selected_company.illegal) + illegal_failure = TRUE + break + + var/obj/machinery/computer/cargo/cargo_comp = parent + if(selected_company.illegal && !cargo_comp.contraband) + illegal_failure = TRUE + break + + if(illegal_failure) + continue + + var/list/armament_subcategories = list() + + for(var/subcategory as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY]) + var/list/subcategory_items = list() + for(var/datum/armament_entry/armament_entry as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY][subcategory]) + if(products && !(armament_entry.type in products)) + continue + + var/datum/armament_entry/cargo_gun/gun_entry = armament_entry + + if(gun_entry.contraband) + if(!(console_state == CARGO_CONSOLE)) + continue + var/obj/machinery/computer/cargo/parent_console = parent + if(!parent_console.contraband) + continue + + var/cant_purchase = FALSE + + if(gun_entry.interest_required) + for(var/company_interested as anything in SSgun_companies.companies) + if(company_interested != armament_category) + continue + var/datum/gun_company/company_datum = SSgun_companies.companies[company_interested] + if(company_datum.interest < gun_entry.interest_required) + cant_purchase = TRUE + + subcategory_items += list(list( + "ref" = REF(armament_entry), + "icon" = armament_entry.cached_base64, + "name" = armament_entry.name, + "cost" = armament_entry.cost, + "buyable_ammo" = armament_entry.magazine ? TRUE : FALSE, + "magazine_cost" = armament_entry.magazine_cost, + "quantity" = gun_entry.stock, + "purchased" = purchased_items[armament_entry] ? purchased_items[armament_entry] : 0, + "description" = armament_entry.description, + "armament_category" = armament_entry.category, + "equipment_subcategory" = armament_entry.subcategory, + "cant_purchase" = !!cant_purchase, + )) + + if(!LAZYLEN(subcategory_items)) + continue + + armament_subcategories += list(list( + "subcategory" = subcategory, + "items" = subcategory_items, + )) + + if(!LAZYLEN(armament_subcategories)) + continue + + var/purchased_company = FALSE + var/company_cost = 0 + var/handout_company = FALSE + + for(var/company as anything in SSgun_companies.companies) + if(company != armament_category) + continue + + if(company in SSgun_companies.purchased_companies) + purchased_company = TRUE + + var/datum/gun_company/company_datum = SSgun_companies.companies[company] + + if((company_datum in SSgun_companies.chosen_handouts) && !SSgun_companies.handout_picked) + handout_company = TRUE + + company_cost = company_datum.cost + + + data["armaments_list"] += list(list( + "category" = armament_category, + "category_purchased" = !!purchased_company, + "category_uses" = used_categories[armament_category], + "subcategories" = armament_subcategories, + "cost" = company_cost, + "handout" = !!handout_company, + )) + + return data + +/datum/component/armament/cargo_gun/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CargoGunConsole") + ui.open() + +/datum/component/armament/cargo_gun/select_armament(mob/user, datum/armament_entry/cargo_gun/armament_entry) + var/datum/bank_account/buyer = SSeconomy.get_dep_account(ACCOUNT_CAR) + var/obj/item/modular_computer/possible_downloader + var/obj/machinery/computer/cargo/possible_console + + if(console_state == CARGO_CONSOLE) + possible_console = parent + + else if(console_state == IRN_CONSOLE) + possible_downloader = parent + + if(!istype(armament_entry)) + return + + var/mob/living/carbon/human/the_person = user + + if(!istype(the_person)) + return + + var/obj/item/card/id/id_card + + if(console_state == IRN_CONSOLE) + var/obj/item/computer_hardware/card_slot/card_slot = parent_prog.computer.all_components[MC_CARD] + id_card = card_slot.GetID() + else + id_card = the_person.get_idcard(TRUE) + + if(id_card?.registered_account && (console_state == IRN_CONSOLE)) + if((ACCESS_HEADS in id_card.access) || (ACCESS_QM in id_card.access)) + parent_prog.requestonly = FALSE + buyer = SSeconomy.get_dep_account(id_card.registered_account.account_job.paycheck_department) + parent_prog.can_approve_requests = TRUE + else + parent_prog.requestonly = TRUE + parent_prog.can_approve_requests = FALSE + else + parent_prog?.requestonly = TRUE + + if(self_paid) + if(!istype(id_card)) + to_chat(user, span_warning("No ID card detected.")) + return + + if(istype(id_card, /obj/item/card/id/departmental_budget)) + to_chat(user, span_warning("[id_card] cannot be used to make purchases.")) + return + + var/datum/bank_account/account = id_card.registered_account + + if(!istype(account)) + to_chat(user, span_warning("Invalid bank account.")) + return + + buyer = account + + if(!buyer) + to_chat(user, span_warning("No budget found!")) + return + + if(!armament_entry.stock) + to_chat(user, span_warning("No stock of this item left!")) + return + + if(!ishuman(user)) + return + + if(!buyer.has_money(armament_entry.cost)) //so you can't "stash" guns for later merchant cycles + to_chat(user, span_warning("Not enough money!")) + return + + var/name = the_person.get_authentification_name() + var/reason = "" + + if(possible_console) + if(possible_console.requestonly && !self_paid) + reason = tgui_input_text(user, "Reason", name) + if(isnull(reason)) + return + + else if(possible_downloader) + var/datum/computer_file/program/budgetorders/parent_file = parent_prog + var/obj/item/computer_hardware/card_slot/card_slot = possible_downloader.all_components[MC_CARD] + if((parent_file.requestonly && !self_paid) || !(card_slot?.GetID())) + reason = tgui_input_text(user, "Reason", name) + if(isnull(reason)) + return + + used_categories[armament_entry.category]++ + + purchased_items[armament_entry]++ + armament_entry.stock-- + + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + + var/datum/supply_pack/armament/created_pack = new + created_pack.name = initial(armament_entry.item_type.name) + created_pack.cost = cost_calculate(armament_entry.cost) //Paid for seperately + created_pack.contains = list(armament_entry.item_type) + var/rank = the_person.get_assignment(hand_first = TRUE) + var/ckey = the_person.ckey + var/datum/supply_order/armament/created_order + if(buyer != SSeconomy.get_dep_account(ACCOUNT_CAR)) + created_order = new(created_pack, name, rank, ckey, paying_account = buyer, reason = reason) + else + created_order = new(created_pack, name, rank, ckey, reason = reason) + created_order.interest_addition = armament_entry.interest_addition + created_order.selected_entry = armament_entry + created_order.used_component = src + if(console_state == CARGO_CONSOLE) + created_order.generateRequisition(get_turf(parent)) + if(possible_console.requestonly && !self_paid) + SSshuttle.request_list += created_order + else + SSshuttle.shopping_list += created_order + else if(console_state == IRN_CONSOLE) + var/datum/computer_file/program/budgetorders/comp_file = parent_prog + created_order.generateRequisition(get_turf(parent)) + if(comp_file.requestonly && !self_paid) + SSshuttle.request_list += created_order + else + SSshuttle.shopping_list += created_order + +/datum/component/armament/cargo_gun/buy_ammo(mob/user, datum/armament_entry/cargo_gun/armament_entry) + var/datum/bank_account/buyer = SSeconomy.get_dep_account(ACCOUNT_CAR) + var/obj/machinery/computer/cargo/possible_console + var/obj/item/modular_computer/possible_downloader + + if(console_state == CARGO_CONSOLE) + possible_console = parent + + else if(console_state == IRN_CONSOLE) + possible_downloader = parent + + var/mob/living/carbon/human/the_person = user + + if(!istype(the_person)) + return + + var/obj/item/card/id/id_card + + if(console_state == IRN_CONSOLE) + var/obj/item/computer_hardware/card_slot/card_slot = parent_prog.computer.all_components[MC_CARD] + id_card = card_slot.GetID() + else + id_card = the_person.get_idcard(TRUE) + + if(id_card?.registered_account && (console_state == IRN_CONSOLE)) + if((ACCESS_HEADS in id_card.access) || (ACCESS_QM in id_card.access)) + parent_prog.requestonly = FALSE + buyer = SSeconomy.get_dep_account(id_card.registered_account.account_job.paycheck_department) + parent_prog.can_approve_requests = TRUE + else + parent_prog.requestonly = TRUE + parent_prog.can_approve_requests = FALSE + else + parent_prog?.requestonly = TRUE + + if(self_paid) + if(!istype(id_card)) + to_chat(user, span_warning("No ID card detected.")) + return + + if(istype(id_card, /obj/item/card/id/departmental_budget)) + to_chat(user, span_warning("[id_card] cannot be used to make purchases.")) + return + + var/datum/bank_account/account = id_card.registered_account + + if(!istype(account)) + to_chat(user, span_warning("Invalid bank account.")) + return + + buyer = account + + if(!armament_entry.magazine) + return + + if(!buyer) + to_chat(user, span_warning("No budget found!")) + return + + var/quantity_cost = armament_entry.magazine_cost * ammo_purchase_num + + if(!buyer.has_money(quantity_cost)) + to_chat(user, span_warning("Not enough money!")) + return + + var/name = the_person.get_authentification_name() + var/reason = "" + + if(possible_console) + if(possible_console.requestonly && !self_paid) + reason = tgui_input_text(user, "Reason", name) + if(isnull(reason)) + return + + else if(possible_downloader) + var/datum/computer_file/program/budgetorders/parent_file = parent_prog + var/obj/item/computer_hardware/card_slot/card_slot = possible_downloader.all_components[MC_CARD] + if((parent_file.requestonly && !self_paid) || !(card_slot?.GetID())) + reason = tgui_input_text(user, "Reason", name) + if(isnull(reason)) + return + + + var/datum/supply_pack/created_pack = new + var/assembled_name = "[initial(armament_entry.item_type.name)] Ammunition (x[ammo_purchase_num])" + created_pack.name = assembled_name + created_pack.cost = cost_calculate(quantity_cost) + created_pack.contains = list() + for(var/i in 1 to ammo_purchase_num) + created_pack.contains += armament_entry.magazine + var/rank = the_person.get_assignment(hand_first = TRUE) + var/ckey = the_person.ckey + var/datum/supply_order/armament/created_order + if(buyer != SSeconomy.get_dep_account(ACCOUNT_CAR)) + created_order = new(created_pack, name, rank, ckey, paying_account = buyer, reason = reason) + else + created_order = new(created_pack, name, rank, ckey, reason = reason) + created_order.interest_addition = 1 * ammo_purchase_num + var/datum/computer_file/program/budgetorders/file_p = parent_prog + if(console_state == CARGO_CONSOLE) + created_order.generateRequisition(get_turf(parent)) + if(possible_console.requestonly && !self_paid) + SSshuttle.request_list += created_order + else + SSshuttle.shopping_list += created_order + else if(console_state == IRN_CONSOLE) + if(file_p.requestonly && !self_paid) + SSshuttle.request_list += created_order + else + SSshuttle.shopping_list += created_order + +/datum/component/armament/cargo_gun/proc/cost_calculate(cost) + . = cost + . *= SSeconomy.pack_price_modifier + +/datum/component/armament/cargo_gun/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("set_ammo_amount") + var/target = text2num(params["chosen_amount"]) + ammo_purchase_num = clamp(target, 1, MAX_AMMO_AMOUNT) + + if("buy_company") + var/target = params["selected_company"] + var/obj/machinery/computer/cargo/possible_console + + if(console_state == CARGO_CONSOLE) + possible_console = parent + if(possible_console.requestonly && !self_paid) + return + else if(console_state == IRN_CONSOLE) + if(parent_prog.requestonly && !self_paid) + return + + for(var/find_company in SSgun_companies.unpurchased_companies) + if(find_company != target) + continue + + var/datum/gun_company/found_company = SSgun_companies.unpurchased_companies[target] + var/datum/bank_account/buyer = SSeconomy.get_dep_account(ACCOUNT_CAR) + + var/mob/living/carbon/human/user = usr + + if(!istype(user)) + return + + var/obj/item/card/id/id_card = user.get_idcard(TRUE) + + if(id_card?.registered_account && (console_state == IRN_CONSOLE)) + if((ACCESS_HEADS in id_card.access) || (ACCESS_QM in id_card.access)) + parent_prog.requestonly = FALSE + buyer = SSeconomy.get_dep_account(id_card.registered_account.account_job.paycheck_department) + parent_prog.can_approve_requests = TRUE + else + parent_prog.requestonly = TRUE + parent_prog.can_approve_requests = FALSE + else + parent_prog?.requestonly = TRUE + + if(self_paid) + + if(!istype(id_card)) + to_chat(user, span_warning("No ID card detected.")) + return + + if(istype(id_card, /obj/item/card/id/departmental_budget)) + to_chat(user, span_warning("[id_card] cannot be used to make purchases.")) + return + + var/datum/bank_account/account = id_card.registered_account + + if(!istype(account)) + to_chat(user, span_warning("Invalid bank account.")) + return + + buyer = account + + var/assigned_cost = -found_company.cost + var/do_payment = TRUE + if(!SSgun_companies.handout_picked && (found_company in SSgun_companies.chosen_handouts)) + do_payment = FALSE + SSgun_companies.handout_picked = TRUE + if(do_payment) + if(!buyer.adjust_money(assigned_cost)) + return + + SSgun_companies.purchased_companies[find_company] = found_company + SSgun_companies.unpurchased_companies.Remove(find_company) + break + + if("toggleprivate") + var/obj/item/card/id/id_card + var/mob/living/carbon/human/the_person = usr + + if(!istype(the_person)) + return + + if(console_state == IRN_CONSOLE) + var/obj/item/computer_hardware/card_slot/card_slot = parent_prog.computer.all_components[MC_CARD] + id_card = card_slot.GetID() + else + id_card = the_person.get_idcard(TRUE) + + if(!id_card) + return + + self_paid = !self_paid + +#undef MAX_AMMO_AMOUNT +#undef CARGO_CONSOLE +#undef IRN_CONSOLE diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/allstar.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/allstar.dm new file mode 100644 index 000000000000..46586792e74a --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/allstar.dm @@ -0,0 +1,62 @@ +#define ARMAMENT_CATEGORY_ALLSTAR "Allstar Lasers" + +/datum/armament_entry/cargo_gun/allstar + category = ARMAMENT_CATEGORY_ALLSTAR + company_bitflag = COMPANY_ALLSTAR + +/datum/armament_entry/cargo_gun/allstar/laser + subcategory = ARMAMENT_SUBCATEGORY_LASER + +/datum/armament_entry/cargo_gun/allstar/laser/sc1 + item_type = /obj/item/gun/energy/laser + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/allstar/laser/sc2 + item_type = /obj/item/gun/energy/e_gun + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 8 + +/datum/armament_entry/cargo_gun/allstar/laser/sc3 + item_type = /obj/item/gun/energy/laser/hellgun/blueshield + lower_cost = CARGO_CRATE_VALUE * 7 + upper_cost = CARGO_CRATE_VALUE * 9 + +/datum/armament_entry/cargo_gun/allstar/laser/mini_egun + item_type = /obj/item/gun/energy/e_gun/mini + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 7 + +/datum/armament_entry/cargo_gun/allstar/laser/disabler + item_type = /obj/item/gun/energy/disabler + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/allstar/laser/dragnet + item_type = /obj/item/gun/energy/e_gun/dragnet + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/allstar/gunkit + subcategory = ARMAMENT_SUBCATEGORY_GUNPART + interest_addition = COMPANY_INTEREST_ATTACHMENT + +/datum/armament_entry/cargo_gun/allstar/gunkit/tempgun + item_type = /obj/item/weaponcrafting/gunkit/temperature + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/allstar/gunkit/adv_egun + item_type = /obj/item/weaponcrafting/gunkit/nuclear + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 9 + +/datum/armament_entry/cargo_gun/allstar/gunkit/ion + item_type = /obj/item/weaponcrafting/gunkit/ion + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 10 + +/datum/armament_entry/cargo_gun/allstar/gunkit/hellfire + item_type = /obj/item/weaponcrafting/gunkit/hellgun + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 8 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne.dm new file mode 100644 index 000000000000..f3fc790178ba --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne.dm @@ -0,0 +1,69 @@ +#define ARMAMENT_CATEGORY_ARMADYNE "Armadyne Corporation" + +/datum/armament_entry/cargo_gun/armadyne + category = ARMAMENT_CATEGORY_ARMADYNE + company_bitflag = COMPANY_ARMADYNE + +/datum/armament_entry/cargo_gun/armadyne/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/armadyne/pistol/osprey + item_type = /obj/item/gun/ballistic/automatic/pistol/pdh + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 14 + +/datum/armament_entry/cargo_gun/armadyne/pistol/ladon + item_type = /obj/item/gun/ballistic/automatic/pistol/ladon + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 13 + +/datum/armament_entry/cargo_gun/armadyne/pistol/firefly + item_type = /obj/item/gun/ballistic/automatic/pistol/firefly + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/armadyne/pistol/pdh6b + item_type = /obj/item/gun/ballistic/automatic/pistol/pdh/peacekeeper + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/armadyne/pistol/mk58 + item_type = /obj/item/gun/ballistic/automatic/pistol/mk58 + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 8 + +/datum/armament_entry/cargo_gun/armadyne/shotgun + subcategory = ARMAMENT_SUBCATEGORY_SHOTGUN + +/datum/armament_entry/cargo_gun/armadyne/shotgun/as2 + item_type = /obj/item/gun/ballistic/shotgun/automatic/as2 + lower_cost = CARGO_CRATE_VALUE * 7 + upper_cost = CARGO_CRATE_VALUE * 8 + +/datum/armament_entry/cargo_gun/armadyne/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/armadyne/smg/dozer + item_type = /obj/item/gun/ballistic/automatic/dozer + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 12 + +/datum/armament_entry/cargo_gun/armadyne/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/armadyne/rifle/ripper + item_type = /obj/item/gun/ballistic/automatic/dmr + lower_cost = CARGO_CRATE_VALUE * 24 + upper_cost = CARGO_CRATE_VALUE * 28 + +/datum/armament_entry/cargo_gun/armadyne/rifle/norwind + item_type = /obj/item/gun/energy/norwind + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 14 + +/datum/armament_entry/cargo_gun/armadyne/rifle/ostwind + item_type = /obj/item/gun/energy/ostwind + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 14 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne_oldarms.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne_oldarms.dm new file mode 100644 index 000000000000..eee554e41aeb --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/armadyne_oldarms.dm @@ -0,0 +1,58 @@ +#define ARMAMENT_CATEGORY_OLDARMS "Armadyne Oldarms" + +/datum/armament_entry/cargo_gun/oldarms + category = ARMAMENT_CATEGORY_OLDARMS + company_bitflag = COMPANY_OLDARMS + +/datum/armament_entry/cargo_gun/oldarms/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/oldarms/pistol/luger + item_type = /obj/item/gun/ballistic/automatic/pistol/luger + lower_cost = CARGO_CRATE_VALUE * 7 + upper_cost = CARGO_CRATE_VALUE * 9 + +/datum/armament_entry/cargo_gun/oldarms/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + +/datum/armament_entry/cargo_gun/oldarms/smg/mp40 + item_type = /obj/item/gun/ballistic/automatic/mp40 + lower_cost = CARGO_CRATE_VALUE * 20 + upper_cost = CARGO_CRATE_VALUE * 24 + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/oldarms/smg/uzi + item_type = /obj/item/gun/ballistic/automatic/mini_uzi + lower_cost = CARGO_CRATE_VALUE * 14 + upper_cost = CARGO_CRATE_VALUE * 18 + +/datum/armament_entry/cargo_gun/oldarms/smg/ppsh + item_type = /obj/item/gun/ballistic/automatic/ppsh + lower_cost = CARGO_CRATE_VALUE * 32 + upper_cost = CARGO_CRATE_VALUE * 38 + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/oldarms/smg/thompson + item_type = /obj/item/gun/ballistic/automatic/tommygun + lower_cost = CARGO_CRATE_VALUE * 30 + upper_cost = CARGO_CRATE_VALUE * 36 + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/oldarms/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/oldarms/rifle/vintorez + item_type = /obj/item/gun/energy/vintorez + lower_cost = CARGO_CRATE_VALUE * 12 + upper_cost = CARGO_CRATE_VALUE * 18 + +/datum/armament_entry/cargo_gun/oldarms/rifle/stg + item_type = /obj/item/gun/ballistic/automatic/stg + lower_cost = CARGO_CRATE_VALUE * 24 + upper_cost = CARGO_CRATE_VALUE * 28 + +/datum/armament_entry/cargo_gun/oldarms/rifle/g11 + item_type = /obj/item/gun/ballistic/automatic/g11 + lower_cost = CARGO_CRATE_VALUE * 30 + upper_cost = CARGO_CRATE_VALUE * 35 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/bolt.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/bolt.dm new file mode 100644 index 000000000000..c712b5383b7c --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/bolt.dm @@ -0,0 +1,60 @@ +#define ARMAMENT_CATEGORY_BOLT "Bolt Fabrications" + +/datum/armament_entry/cargo_gun/bolt + category = ARMAMENT_CATEGORY_BOLT + company_bitflag = COMPANY_BOLT + +/datum/armament_entry/cargo_gun/bolt/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/bolt/pistol/responder + item_type = /obj/item/gun/energy/disabler/bolt_disabler + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/bolt/pistol/m1911 + item_type = /obj/item/gun/ballistic/automatic/pistol/m1911 + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/bolt/pistol/pepperball + item_type = /obj/item/gun/ballistic/automatic/pistol/pepperball + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/bolt/pistol/spurchamber + item_type = /obj/item/gun/ballistic/revolver/zeta + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 7 + +/datum/armament_entry/cargo_gun/bolt/pistol/spurmaster + item_type = /obj/item/gun/ballistic/revolver/revolution + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 8 + +/datum/armament_entry/cargo_gun/bolt/shotgun + subcategory = ARMAMENT_SUBCATEGORY_SHOTGUN + +/datum/armament_entry/cargo_gun/bolt/m23 + item_type = /obj/item/gun/ballistic/shotgun/m23 + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 12 + +/datum/armament_entry/cargo_gun/bolt/generic_shotgun + item_type = /obj/item/gun/ballistic/shotgun + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 10 + +/datum/armament_entry/cargo_gun/bolt/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/bolt/smg/pcr + item_type = /obj/item/gun/energy/pcr + lower_cost = CARGO_CRATE_VALUE * 16 + upper_cost = CARGO_CRATE_VALUE * 20 + +/datum/armament_entry/cargo_gun/bolt/smg/pitbull + item_type = /obj/item/gun/energy/pitbull + lower_cost = CARGO_CRATE_VALUE * 16 + upper_cost = CARGO_CRATE_VALUE * 20 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/cantalan.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/cantalan.dm new file mode 100644 index 000000000000..b95970859838 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/cantalan.dm @@ -0,0 +1,81 @@ +#define ARMAMENT_CATEGORY_CANTALAN "Cantalan Federal Arms" + +/datum/armament_entry/cargo_gun/cantalan + category = ARMAMENT_CATEGORY_CANTALAN + company_bitflag = COMPANY_CANTALAN + +/datum/armament_entry/cargo_gun/cantalan/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/cantalan/pistol/glock17 + item_type = /obj/item/gun/ballistic/automatic/pistol/g17 + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 7 + +/datum/armament_entry/cargo_gun/cantalan/pistol/glock18 + item_type = /obj/item/gun/ballistic/automatic/pistol/g18 + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 12 + +/datum/armament_entry/cargo_gun/cantalan/pistol/snub + item_type = /obj/item/gun/ballistic/automatic/pistol/cfa_snub + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 9 + +/datum/armament_entry/cargo_gun/cantalan/pistol/ruby + item_type = /obj/item/gun/ballistic/automatic/pistol/cfa_ruby + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 9 + +/datum/armament_entry/cargo_gun/cantalan/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + +/datum/armament_entry/cargo_gun/cantalan/smg/lynx + item_type = /obj/item/gun/ballistic/automatic/cfa_lynx + lower_cost = CARGO_CRATE_VALUE * 12 + upper_cost = CARGO_CRATE_VALUE * 15 + +/datum/armament_entry/cargo_gun/cantalan/smg/wildcat + item_type = /obj/item/gun/ballistic/automatic/cfa_wildcat + lower_cost = CARGO_CRATE_VALUE * 9 + upper_cost = CARGO_CRATE_VALUE * 11 + +/datum/armament_entry/cargo_gun/cantalan/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/cantalan/rifle/catanheim + item_type = /obj/item/gun/ballistic/automatic/cfa_rifle + lower_cost = CARGO_CRATE_VALUE * 28 + upper_cost = CARGO_CRATE_VALUE * 32 + +/datum/armament_entry/cargo_gun/cantalan/ammo + subcategory = ARMAMENT_SUBCATEGORY_AMMO + stock_mult = 2 + interest_addition = COMPANY_INTEREST_AMMO + lower_cost = CARGO_CRATE_VALUE * 1 + upper_cost = CARGO_CRATE_VALUE * 2 + +/datum/armament_entry/cargo_gun/cantalan/ammo/c34 + item_type = /obj/item/ammo_box/c34 + +/datum/armament_entry/cargo_gun/cantalan/ammo/c34_ap + item_type = /obj/item/ammo_box/c34/ap + +/datum/armament_entry/cargo_gun/cantalan/ammo/c34_in + item_type = /obj/item/ammo_box/c34/fire + +/datum/armament_entry/cargo_gun/cantalan/ammo/c34_rub + item_type = /obj/item/ammo_box/c34/rubber + +/datum/armament_entry/cargo_gun/cantalan/ammo/c12mm + item_type = /obj/item/ammo_box/c12mm + +/datum/armament_entry/cargo_gun/cantalan/ammo/c12mm_ap + item_type = /obj/item/ammo_box/c12mm/ap + +/datum/armament_entry/cargo_gun/cantalan/ammo/c12mm_in + item_type = /obj/item/ammo_box/c12mm/fire + +/datum/armament_entry/cargo_gun/cantalan/ammo/c12mm_hp + item_type = /obj/item/ammo_box/c12mm/hp diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/dynamics.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/dynamics.dm new file mode 100644 index 000000000000..15e6fa9d4629 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/dynamics.dm @@ -0,0 +1,119 @@ +#define ARMAMENT_CATEGORY_DYNAMICS "Armament Dynamics Inc." + +/datum/armament_entry/cargo_gun/dynamics + category = ARMAMENT_CATEGORY_DYNAMICS + company_bitflag = COMPANY_DYNAMICS + stock_mult = 2 //To compensate for their interest being fairly low most of the time + +/datum/armament_entry/cargo_gun/dynamics/ammo + subcategory = ARMAMENT_SUBCATEGORY_AMMO + lower_cost = CARGO_CRATE_VALUE * 0.75 + upper_cost = CARGO_CRATE_VALUE * 1.25 + interest_addition = COMPANY_INTEREST_AMMO + +/datum/armament_entry/cargo_gun/dynamics/ammo/c9mm + item_type = /obj/item/ammo_box/c9mm + +/datum/armament_entry/cargo_gun/dynamics/ammo/c9mm_ap + item_type = /obj/item/ammo_box/c9mm/ap + +/datum/armament_entry/cargo_gun/dynamics/ammo/c9mm_hp + item_type = /obj/item/ammo_box/c9mm/hp + +/datum/armament_entry/cargo_gun/dynamics/ammo/c9mm_in + item_type = /obj/item/ammo_box/c9mm/fire + +/datum/armament_entry/cargo_gun/dynamics/ammo/c10mm + item_type = /obj/item/ammo_box/c10mm + +/datum/armament_entry/cargo_gun/dynamics/ammo/c10mm_ap + item_type = /obj/item/ammo_box/c10mm/ap + +/datum/armament_entry/cargo_gun/dynamics/ammo/c10mm_hp + item_type = /obj/item/ammo_box/c10mm/hp + +/datum/armament_entry/cargo_gun/dynamics/ammo/c10mm_in + item_type = /obj/item/ammo_box/c10mm/fire + +/datum/armament_entry/cargo_gun/dynamics/ammo/c12ga + item_type = /obj/item/storage/box/lethalshot + +/datum/armament_entry/cargo_gun/dynamics/ammo/c12ga_rub + item_type = /obj/item/storage/box/rubbershot + +/datum/armament_entry/cargo_gun/dynamics/ammo/c12ga_bean + item_type = /obj/item/storage/box/beanbag + +/datum/armament_entry/cargo_gun/dynamics/ammo/c12ga_tech + item_type = /obj/item/storage/box/techshell + +/datum/armament_entry/cargo_gun/dynamics/ammo/c46mm + item_type = /obj/item/ammo_box/c46x30mm + +/datum/armament_entry/cargo_gun/dynamics/ammo/c46mm_ap + item_type = /obj/item/ammo_box/c46x30mm/ap + +/datum/armament_entry/cargo_gun/dynamics/ammo/c46mm_rub + item_type = /obj/item/ammo_box/c46x30mm/rubber + +/datum/armament_entry/cargo_gun/dynamics/ammo/c32 + item_type = /obj/item/ammo_box/c32 + +/datum/armament_entry/cargo_gun/dynamics/ammo/c32_ap + item_type = /obj/item/ammo_box/c32/ap + +/datum/armament_entry/cargo_gun/dynamics/ammo/c32_in + item_type = /obj/item/ammo_box/c32/fire + +/datum/armament_entry/cargo_gun/dynamics/ammo/c32_rub + item_type = /obj/item/ammo_box/c32/rubber + +/datum/armament_entry/cargo_gun/dynamics/ammo/c38 + item_type = /obj/item/ammo_box/c38 + lower_cost = CARGO_CRATE_VALUE * 0.5 + upper_cost = CARGO_CRATE_VALUE * 1 + stock_mult = 3 + +/datum/armament_entry/cargo_gun/dynamics/ammo/c38/dum + item_type = /obj/item/ammo_box/c38/dumdum + +/datum/armament_entry/cargo_gun/dynamics/ammo/c38/hot + item_type = /obj/item/ammo_box/c38/hotshot + +/datum/armament_entry/cargo_gun/dynamics/ammo/c38/ice + item_type = /obj/item/ammo_box/c38/iceblox + +/datum/armament_entry/cargo_gun/dynamics/ammo/c38/mat + item_type = /obj/item/ammo_box/c38/match + +/datum/armament_entry/cargo_gun/dynamics/ammo/c38/trc + item_type = /obj/item/ammo_box/c38/trac + +/datum/armament_entry/cargo_gun/dynamics/ammo/b10mm + item_type = /obj/item/ammo_box/b10mm + +/datum/armament_entry/cargo_gun/dynamics/ammo/b10mm_hp + item_type = /obj/item/ammo_box/b10mm/hp + +/datum/armament_entry/cargo_gun/dynamics/ammo/b10mm_rub + item_type = /obj/item/ammo_box/b10mm/rubber + +/datum/armament_entry/cargo_gun/dynamics/misc + subcategory = ARMAMENT_SUBCATEGORY_SPECIAL + +/datum/armament_entry/cargo_gun/dynamics/misc/bandolier + item_type = /obj/item/storage/belt/bandolier + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/dynamics/misc/ammo_bench + item_type = /obj/item/circuitboard/machine/ammo_workbench + lower_cost = CARGO_CRATE_VALUE * 28 + upper_cost = CARGO_CRATE_VALUE * 33 + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/dynamics/misc/lethal_disk + item_type = /obj/item/disk/ammo_workbench/lethal + lower_cost = CARGO_CRATE_VALUE * 22 + upper_cost = CARGO_CRATE_VALUE * 27 + interest_required = HIGH_INTEREST diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/interdyne.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/interdyne.dm new file mode 100644 index 000000000000..f31611f5a216 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/interdyne.dm @@ -0,0 +1,64 @@ +#define ARMAMENT_CATEGORY_INTERDYNE "Interdyne Pharmaceuticals" + +/datum/armament_entry/cargo_gun/interdyne + category = ARMAMENT_CATEGORY_INTERDYNE + company_bitflag = COMPANY_INTERDYNE + +/datum/armament_entry/cargo_gun/interdyne/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/interdyne/pistol/honeybee + item_type = /obj/item/gun/ballistic/automatic/pistol/firefly/smartdart + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 6 + +/datum/armament_entry/cargo_gun/interdyne/special + subcategory = ARMAMENT_SUBCATEGORY_SPECIAL + +/datum/armament_entry/cargo_gun/interdyne/special/syringe_gun + item_type = /obj/item/gun/syringe + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 12 + +/datum/armament_entry/cargo_gun/interdyne/special/smartdart_gun + item_type = /obj/item/gun/syringe/smartdart + lower_cost = CARGO_CRATE_VALUE * 6 + upper_cost = CARGO_CRATE_VALUE * 8 + +/datum/armament_entry/cargo_gun/interdyne/special/rapid_syringe_gun + item_type = /obj/item/gun/syringe/rapidsyringe + lower_cost = CARGO_CRATE_VALUE * 16 + upper_cost = CARGO_CRATE_VALUE * 18 + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/interdyne/ammo + subcategory = ARMAMENT_SUBCATEGORY_AMMO + interest_addition = COMPANY_INTEREST_AMMO + +/datum/armament_entry/cargo_gun/interdyne/ammo/pierce_syringe + item_type = /obj/item/storage/box/syringes/piercing + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 8 + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/interdyne/ammo/bluespace_syringe + item_type = /obj/item/storage/box/syringes/bluespace + lower_cost = CARGO_CRATE_VALUE * 9 + upper_cost = CARGO_CRATE_VALUE * 12 + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/interdyne/chemical + subcategory = ARMAMENT_SUBCATEGORY_CHEMICAL + interest_addition = COMPANY_INTEREST_CHEMICAL + contraband = TRUE + +/datum/armament_entry/cargo_gun/interdyne/chemical/toxin + item_type = /obj/item/reagent_containers/glass/bottle/toxin + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/interdyne/chemical/cyanide + item_type = /obj/item/reagent_containers/glass/bottle/cyanide + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 6 + interest_required = PASSED_INTEREST diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/izhevsk.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/izhevsk.dm new file mode 100644 index 000000000000..55a225036502 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/izhevsk.dm @@ -0,0 +1,50 @@ +#define ARMAMENT_CATEGORY_IZHEVSK "Izhevsk Coalition" + +/datum/armament_entry/cargo_gun/izhevsk + category = ARMAMENT_CATEGORY_IZHEVSK + company_bitflag = COMPANY_IZHEVSK + +/datum/armament_entry/cargo_gun/izhevsk/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/izhevsk/pistol/makarov + item_type = /obj/item/gun/ballistic/automatic/pistol/makarov + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/izhevsk/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + +/datum/armament_entry/cargo_gun/izhevsk/smg/surplus + item_type = /obj/item/gun/ballistic/automatic/plastikov + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/izhevsk/smg/croon + item_type = /obj/item/gun/ballistic/automatic/croon + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 7 + +/datum/armament_entry/cargo_gun/izhevsk/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + +/datum/armament_entry/cargo_gun/izhevsk/rifle/akm + item_type = /obj/item/gun/ballistic/automatic/akm + lower_cost = CARGO_CRATE_VALUE * 40 + upper_cost = CARGO_CRATE_VALUE * 45 + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/izhevsk/rifle/surplus + item_type = /obj/item/gun/ballistic/automatic/surplus + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 6 + +/datum/armament_entry/cargo_gun/izhevsk/rifle/mosin + item_type = /obj/item/gun/ballistic/rifle/boltaction + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 6 + +/datum/armament_entry/cargo_gun/izhevsk/rifle/revrifle + item_type = /obj/item/gun/ballistic/revolver/rifle + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/micron.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/micron.dm new file mode 100644 index 000000000000..e9fd838e8e2f --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/micron.dm @@ -0,0 +1,142 @@ +#define ARMAMENT_CATEGORY_MICRON "Micron Control Systems" + +/datum/armament_entry/cargo_gun/micron + category = ARMAMENT_CATEGORY_MICRON + company_bitflag = COMPANY_MICRON + +/datum/armament_entry/cargo_gun/micron/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + +/datum/armament_entry/cargo_gun/micron/rifle/mcr + item_type = /obj/item/gun/microfusion/mcr01 + lower_cost = CARGO_CRATE_VALUE * 12 + upper_cost = CARGO_CRATE_VALUE * 16 + +/datum/armament_entry/cargo_gun/micron/ammo + subcategory = ARMAMENT_SUBCATEGORY_AMMO + interest_addition = COMPANY_INTEREST_AMMO + +/datum/armament_entry/cargo_gun/micron/ammo/cell + item_type = /obj/item/stock_parts/cell/microfusion + lower_cost = CARGO_CRATE_VALUE * 1 + upper_cost = CARGO_CRATE_VALUE * 1 + +/datum/armament_entry/cargo_gun/micron/ammo/cell_bulk + item_type = /obj/item/storage/box/ammo_box/microfusion/bagless + lower_cost = CARGO_CRATE_VALUE * 1 + upper_cost = CARGO_CRATE_VALUE * 2 + interest_addition = COMPANY_INTEREST_AMMO_BULK + +/datum/armament_entry/cargo_gun/micron/ammo/cell_adv + item_type = /obj/item/stock_parts/cell/microfusion/advanced + lower_cost = CARGO_CRATE_VALUE * 1 + upper_cost = CARGO_CRATE_VALUE * 2 + +/datum/armament_entry/cargo_gun/micron/ammo/cell_adv_bulk + item_type = /obj/item/storage/box/ammo_box/microfusion/advanced/bagless + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + interest_addition = COMPANY_INTEREST_AMMO_BULK + +/datum/armament_entry/cargo_gun/micron/ammo/cell_blue + item_type = /obj/item/stock_parts/cell/microfusion/bluespace + interest_required = HIGH_INTEREST + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/micron/ammo/cell_blue_bulk + item_type = /obj/item/storage/box/ammo_box/microfusion/bluespace/bagless + interest_required = HIGH_INTEREST + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + interest_addition = COMPANY_INTEREST_AMMO_BULK + +/datum/armament_entry/cargo_gun/micron/part + subcategory = ARMAMENT_SUBCATEGORY_GUNPART + interest_addition = COMPANY_INTEREST_ATTACHMENT + +/datum/armament_entry/cargo_gun/micron/part/grip + item_type = /obj/item/microfusion_gun_attachment/grip + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/micron/part/scatter + item_type = /obj/item/microfusion_gun_attachment/scatter + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/micron/part/scope + item_type = /obj/item/microfusion_gun_attachment/scope + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/micron/part/rail + item_type = /obj/item/microfusion_gun_attachment/rail + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/micron/part/heatsink + item_type = /obj/item/microfusion_gun_attachment/heatsink + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/micron/part/lance + item_type = /obj/item/microfusion_gun_attachment/lance + interest_required = PASSED_INTEREST + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/cargo_gun/micron/emitter + subcategory = ARMAMENT_SUBCATEGORY_EMITTER + interest_addition = COMPANY_INTEREST_ATTACHMENT + +/datum/armament_entry/cargo_gun/micron/emitter/enh_emitter + item_type = /obj/item/microfusion_phase_emitter/enhanced + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/micron/emitter/adv_emitter + item_type = /obj/item/microfusion_phase_emitter/advanced + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 7 + +/datum/armament_entry/cargo_gun/micron/emitter/blue_emitter + item_type = /obj/item/microfusion_phase_emitter/bluespace + interest_required = HIGH_INTEREST + lower_cost = CARGO_CRATE_VALUE * 7 + upper_cost = CARGO_CRATE_VALUE * 10 + +/datum/armament_entry/cargo_gun/micron/cell_upgrade + subcategory = ARMAMENT_SUBCATEGORY_CELL_UPGRADE + interest_addition = COMPANY_INTEREST_ATTACHMENT + +/datum/armament_entry/cargo_gun/micron/cell_upgrade/recharge + item_type = /obj/item/microfusion_cell_attachment/rechargeable + lower_cost = CARGO_CRATE_VALUE * 4 + upper_cost = CARGO_CRATE_VALUE * 6 + +/datum/armament_entry/cargo_gun/micron/cell_upgrade/stabilize + item_type = /obj/item/microfusion_cell_attachment/stabiliser + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/micron/cell_upgrade/overcapacity + item_type = /obj/item/microfusion_cell_attachment/overcapacity + lower_cost = CARGO_CRATE_VALUE * 3 + upper_cost = CARGO_CRATE_VALUE * 4 + +/datum/armament_entry/cargo_gun/micron/cell_upgrade/selfcharge + item_type = /obj/item/microfusion_cell_attachment/selfcharging + interest_required = HIGH_INTEREST + lower_cost = CARGO_CRATE_VALUE * 5 + upper_cost = CARGO_CRATE_VALUE * 6 + +/datum/armament_entry/cargo_gun/micron/cell_upgrade/tactical + item_type = /obj/item/microfusion_cell_attachment/tactical + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/cargo_gun/micron/cell_upgrade/reloader + item_type = /obj/item/microfusion_cell_attachment/reloader + lower_cost = CARGO_CRATE_VALUE * 2 + upper_cost = CARGO_CRATE_VALUE * 3 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/nanotrasen.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/nanotrasen.dm new file mode 100644 index 000000000000..2047e68f600a --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/nanotrasen.dm @@ -0,0 +1,55 @@ +#define ARMAMENT_CATEGORY_NANOTRASEN "Nanotrasen Armories" + +/datum/armament_entry/cargo_gun/nanotrasen + category = ARMAMENT_CATEGORY_NANOTRASEN + company_bitflag = COMPANY_NANOTRASEN + +/datum/armament_entry/cargo_gun/nanotrasen/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/nanotrasen/pistol/thermal_holster + item_type = /obj/item/storage/belt/holster/thermal + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 12 + +/datum/armament_entry/cargo_gun/nanotrasen/shotgun + subcategory = ARMAMENT_SUBCATEGORY_SHOTGUN + +/datum/armament_entry/cargo_gun/nanotrasen/shotgun/riot + item_type = /obj/item/gun/ballistic/shotgun/riot + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 12 + +/datum/armament_entry/cargo_gun/nanotrasen/shotgun/combat + item_type = /obj/item/gun/ballistic/shotgun/automatic/combat + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 14 + +/datum/armament_entry/cargo_gun/nanotrasen/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/nanotrasen/smg/saber + item_type = /obj/item/gun/ballistic/automatic/proto + lower_cost = CARGO_CRATE_VALUE * 12 + upper_cost = CARGO_CRATE_VALUE * 18 + +/datum/armament_entry/cargo_gun/nanotrasen/smg/cmg + item_type = /obj/item/gun/ballistic/automatic/cmg + lower_cost = CARGO_CRATE_VALUE * 8 + upper_cost = CARGO_CRATE_VALUE * 13 + +/datum/armament_entry/cargo_gun/nanotrasen/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/nanotrasen/rifle/wtrifle + item_type = /obj/item/gun/ballistic/automatic/wt550 + lower_cost = CARGO_CRATE_VALUE * 12 + upper_cost = CARGO_CRATE_VALUE * 16 + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/nanotrasen/rifle/boarder + item_type = /obj/item/gun/ballistic/automatic/ar + lower_cost = CARGO_CRATE_VALUE * 28 + upper_cost = CARGO_CRATE_VALUE * 32 diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/parent_armament.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/parent_armament.dm new file mode 100644 index 000000000000..e55c5b45d84e --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/parent_armament.dm @@ -0,0 +1,20 @@ +/datum/armament_entry/cargo_gun + max_purchase = 10 + category_item_limit = 10 + cost = 1 + /// Bitflag of the company + var/company_bitflag + /// How much stock of this item is left + var/stock = 10 + /// Lower bound of random pricing + var/lower_cost = 100 + /// Upper bound of random pricing + var/upper_cost = 200 + /// How much the stock is multiplied by + var/stock_mult = 1 + /// How much will be added to a company's reputation on-buy + var/interest_addition = COMPANY_INTEREST_GUN + /// What interest level is needed to purchase the armament, set to 0 for none + var/interest_required = 0 + /// If this requires a multitooled console to be visible + var/contraband = FALSE diff --git a/modular_skyrat/modules/gun_cargo/code/armament_datums/scarborough.dm b/modular_skyrat/modules/gun_cargo/code/armament_datums/scarborough.dm new file mode 100644 index 000000000000..a7eaff1b2e1f --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/armament_datums/scarborough.dm @@ -0,0 +1,64 @@ +#define ARMAMENT_CATEGORY_SCARBOROUGH "Scarborough Arms" + +/datum/armament_entry/cargo_gun/scarborough + category = ARMAMENT_CATEGORY_SCARBOROUGH + company_bitflag = COMPANY_SCARBOROUGH + +/datum/armament_entry/cargo_gun/scarborough/pistol + subcategory = ARMAMENT_SUBCATEGORY_PISTOL + +/datum/armament_entry/cargo_gun/scarborough/pistol/makarov + item_type = /obj/item/gun/ballistic/automatic/pistol + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 15 + +/datum/armament_entry/cargo_gun/scarborough/pistol/aps + item_type = /obj/item/gun/ballistic/automatic/pistol/aps + lower_cost = CARGO_CRATE_VALUE * 18 + upper_cost = CARGO_CRATE_VALUE * 22 + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/scarborough/shotgun + subcategory = ARMAMENT_SUBCATEGORY_SHOTGUN + +/datum/armament_entry/cargo_gun/scarborough/shotgun/bulldog + item_type = /obj/item/gun/ballistic/shotgun/bulldog/unrestricted + lower_cost = CARGO_CRATE_VALUE * 18 + upper_cost = CARGO_CRATE_VALUE * 20 + interest_required = PASSED_INTEREST + +/datum/armament_entry/cargo_gun/scarborough/smg + subcategory = ARMAMENT_SUBCATEGORY_SUBMACHINEGUN + +/datum/armament_entry/cargo_gun/scarborough/smg/c20r + item_type = /obj/item/gun/ballistic/automatic/c20r/unrestricted + lower_cost = CARGO_CRATE_VALUE * 20 + upper_cost = CARGO_CRATE_VALUE * 25 + +/datum/armament_entry/cargo_gun/scarborough/rifle + subcategory = ARMAMENT_SUBCATEGORY_ASSAULTRIFLE + +/datum/armament_entry/cargo_gun/scarborough/rifle/m90gl // Fucking expensive as hell. + item_type = /obj/item/gun/ballistic/automatic/m90/unrestricted + lower_cost = CARGO_CRATE_VALUE * 42 + upper_cost = CARGO_CRATE_VALUE * 47 + interest_required = HIGH_INTEREST + +/datum/armament_entry/cargo_gun/scarborough/part + subcategory = ARMAMENT_SUBCATEGORY_GUNPART + interest_addition = COMPANY_INTEREST_ATTACHMENT + +/datum/armament_entry/cargo_gun/scarborough/part/suppressor + item_type = /obj/item/suppressor + lower_cost = CARGO_CRATE_VALUE * 10 + upper_cost = CARGO_CRATE_VALUE * 15 + +/datum/armament_entry/cargo_gun/scarborough/ammo + subcategory = ARMAMENT_SUBCATEGORY_AMMO + interest_addition = COMPANY_INTEREST_AMMO + +/datum/armament_entry/cargo_gun/scarborough/ammo/grenade + item_type = /obj/item/ammo_casing/a40mm + lower_cost = CARGO_CRATE_VALUE * 15 + upper_cost = CARGO_CRATE_VALUE * 24 + interest_required = HIGH_INTEREST diff --git a/modular_skyrat/modules/gun_cargo/code/company_datums.dm b/modular_skyrat/modules/gun_cargo/code/company_datums.dm new file mode 100644 index 000000000000..b5e29d11b523 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/company_datums.dm @@ -0,0 +1,113 @@ +/datum/gun_company + /// Name of the company + var/name + /// UNUSED, description of the company + var/desc + /// Bitflag that should match what guns the company produces + var/company_flag + /// If the company needs a multitooled console to see + var/illegal = FALSE + /// Var for internal calculations, don't touch + var/base_cost = 0 + /// How much the company costs, can shift over time + var/cost = 0 + /// Multiplier added to the cost before showing the final price to the user + var/cost_mult = 1 + /// On a subsystem fire, will lower/raise company values by a random value between lower and upper + var/cost_change_lower = -100 + /// On a subsystem fire, will lower/raise company values by a random value between lower and upper + var/cost_change_upper = 100 + /// If this company can be picked to be a handout company to start + var/can_roundstart_pick = TRUE + /// The "interest" value of the company, to determine how much stock the company has, goes down passively and is raised by things being bought + var/interest = 0 + /// Multiplier for magazine costs + var/magazine_cost_mult = 1 + +/datum/gun_company/armadyne + name = "Armadyne Corporation" + can_roundstart_pick = FALSE + company_flag = COMPANY_ARMADYNE + cost = 7500 + cost_change_lower = -2500 + cost_change_upper = 8500 + +/datum/gun_company/cantalan + name = "Cantalan Federal Arms" + can_roundstart_pick = FALSE + company_flag = COMPANY_CANTALAN + magazine_cost_mult = 3 //RIP + cost = 4500 + cost_change_lower = -4000 + cost_change_upper = 7500 + +/datum/gun_company/scarborough + name = "Scarborough Arms" + illegal = TRUE + can_roundstart_pick = FALSE + company_flag = COMPANY_SCARBOROUGH + cost = 20000 + cost_change_lower = 0 //stonks never go down + cost_change_upper = 20000 + cost_mult = 1.1 + +/datum/gun_company/bolt + name = "Bolt Fabrications" + company_flag = COMPANY_BOLT + cost = 4500 + cost_change_lower = -4250 + cost_change_upper = 8500 + +/datum/gun_company/oldarms + name = "Armadyne Oldarms" + can_roundstart_pick = FALSE + company_flag = COMPANY_OLDARMS + cost_change_lower = -2000 + cost_change_upper = 15000 + cost = 10000 + magazine_cost_mult = 2.5 + +/datum/gun_company/izhevsk + name = "Izhevsk Coalition" + company_flag = COMPANY_IZHEVSK + cost_change_lower = -2500 //cheap as hell "company" is cheap as hell to buy + cost_change_upper = 4500 + cost = 3000 + cost_mult = 0.9 + +/datum/gun_company/nanotrasen + name = "Nanotrasen Armories" + company_flag = COMPANY_NANOTRASEN + cost_change_lower = -2000 + cost_change_upper = 10000 + cost = 7500 + +/datum/gun_company/allstar + name = "Allstar Lasers" + company_flag = COMPANY_ALLSTAR + cost_change_lower = -5000 + cost_change_upper = 8750 + cost = 6500 + +/datum/gun_company/micron + name = "Micron Control Systems" + can_roundstart_pick = FALSE + company_flag = COMPANY_MICRON + cost_change_lower = -2250 + cost_change_upper = 12500 //This is an alternative to R&D, so it's expensive as hell + cost = 10000 + +/datum/gun_company/interdyne + name = "Interdyne Pharmaceuticals" + company_flag = COMPANY_INTERDYNE + cost_change_lower = -4500 + cost_change_upper = 6500 + cost = 7500 + +/datum/gun_company/dynamics + name = "Armament Dynamics Inc." + can_roundstart_pick = FALSE + company_flag = COMPANY_DYNAMICS + cost_change_lower = -5000 + cost_change_upper = 8500 + cost = 4500 //subsidized or smth diff --git a/modular_skyrat/modules/gun_cargo/code/datums/cargo_order.dm b/modular_skyrat/modules/gun_cargo/code/datums/cargo_order.dm new file mode 100644 index 000000000000..23f0170bd4fe --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/datums/cargo_order.dm @@ -0,0 +1,29 @@ +/datum/supply_order/armament + /// The armament entry used to fill the supply order + var/datum/armament_entry/cargo_gun/selected_entry + /// The component used to create the order + var/datum/component/armament/cargo_gun/used_component + /// How much it'll add to a company's interest on-buy + var/interest_addition + +/datum/supply_order/armament/Destroy(force, ...) + selected_entry = null + used_component = null + . = ..() + +/datum/supply_order/armament/proc/reimburse_armament() + if(!selected_entry || !used_component) + return + used_component.purchased_items[selected_entry]-- + selected_entry.stock++ + +/// A proc to be overriden if you want custom code to happen when SSshuttle spawns the order +/datum/supply_order/proc/on_spawn() + return + +/datum/supply_order/armament/on_spawn() + for(var/company in SSgun_companies.companies) + var/datum/gun_company/comp_datum = SSgun_companies.companies[company] + if(comp_datum.company_flag == selected_entry?.company_bitflag) + comp_datum.interest += interest_addition + break diff --git a/modular_skyrat/modules/gun_cargo/code/datums/cargo_pack.dm b/modular_skyrat/modules/gun_cargo/code/datums/cargo_pack.dm new file mode 100644 index 000000000000..0cd6a87c562c --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/datums/cargo_pack.dm @@ -0,0 +1,13 @@ +/datum/supply_pack/armament + +/datum/supply_pack/armament/generate(atom/A, datum/bank_account/paying_account) + . = ..() + /* + var/obj/structure/container = . + for(var/obj/item/gun/gun_actually in container.contents) + if(gun_actually.company_flag & COMPANY_SCARBOROUGH) //illegal company doesn't care about pins + continue + QDEL_NULL(gun_actually.pin) + var/obj/item/firing_pin/permit_pin/new_pin = new(gun_actually) + gun_actually.pin = new_pin +*/ diff --git a/modular_skyrat/modules/gun_cargo/code/datums/hud.dm b/modular_skyrat/modules/gun_cargo/code/datums/hud.dm new file mode 100644 index 000000000000..e48060a363e6 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/datums/hud.dm @@ -0,0 +1,2 @@ +/datum/atom_hud/data/human/permit + hud_icons = list(PERMIT_HUD) diff --git a/modular_skyrat/modules/gun_cargo/code/gun_companies.dm b/modular_skyrat/modules/gun_cargo/code/gun_companies.dm new file mode 100644 index 000000000000..0a7fcb0f96b3 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/gun_companies.dm @@ -0,0 +1,39 @@ +/obj/item/gun/ballistic/automatic/pistol + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/automatic/pistol/m1911 + company_flag = COMPANY_BOLT + +/obj/item/gun/ballistic/automatic/pistol/aps + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/revolver + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/ballistic/revolver/nagant + company_flag = COMPANY_OLDARMS + +/obj/item/gun/ballistic/rifle/boltaction + company_flag = COMPANY_IZHEVSK + dirt_modifier = 0.75 + +/obj/item/gun/ballistic/shotgun/riot + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/ballistic/shotgun/bulldog + company_flag = COMPANY_SCARBOROUGH + +/obj/item/gun/energy/e_gun + company_flag = COMPANY_ALLSTAR + +/obj/item/gun/energy/laser + company_flag = COMPANY_ALLSTAR + +/obj/item/gun/energy/pulse + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/ballistic/shotgun/automatic/combat + company_flag = COMPANY_NANOTRASEN + +/obj/item/gun/syringe + company_flag = COMPANY_INTERDYNE diff --git a/modular_skyrat/modules/gun_cargo/code/gun_subsystem.dm b/modular_skyrat/modules/gun_cargo/code/gun_subsystem.dm new file mode 100644 index 000000000000..9a429a2bf4f6 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/gun_subsystem.dm @@ -0,0 +1,150 @@ +#define MAX_HANDOUT_CHOICES 3 +#define FAILED_INTEREST 1 +#define PASSED_INTEREST 2 +#define HIGH_INTEREST 3 +#define INTEREST_HIGH_MULT 10 +#define INTEREST_CAP 75 +#define INTEREST_LOWER_RAND 5 +#define INTEREST_HIGHER_RAND 25 +#define BASE_COST_MINIMUM 1000 +#define BASE_COST_MAXIMUM 75000 +#define INTEREST_LOW_MAG_COST 0.1 +#define INTEREST_MED_MAG_COST 0.11 +#define INTEREST_HIGH_MAG_COST 0.125 + +SUBSYSTEM_DEF(gun_companies) + name = "Gun Companies" + wait = 20 MINUTES + runlevels = RUNLEVEL_GAME + /// Assoc list of companies that the subsystem has initialized, `"NAME" = datum_reference` + var/list/companies = list() + /// Assoc list of unpurchased companies + var/list/unpurchased_companies = list() + /// Assoc list of purchased companies + var/list/purchased_companies = list() + /// List of chosen handout company datums, for the user to pick 1 + var/list/chosen_handouts = list() + /// Picked a free company yet? + var/handout_picked = FALSE + +/datum/controller/subsystem/gun_companies/Initialize(start_timeofday) + // Adds the company refs to the unchanging companies list and the changing unpurchased_companies list + for(var/datum/gun_company/company as anything in subtypesof(/datum/gun_company)) + var/datum/gun_company/new_company = new company + companies[new_company.name] = new_company + unpurchased_companies[new_company.name] = new_company + + // Cargo gets to pick one company from several for free + var/list/potential_handouts = list() + for(var/company_name in unpurchased_companies) + var/datum/gun_company/picked_company = unpurchased_companies[company_name] + if(!picked_company.can_roundstart_pick) + continue + potential_handouts += picked_company + for(var/i in 1 to MAX_HANDOUT_CHOICES) + chosen_handouts += pick_n_take(potential_handouts) + fire() //Gotta get the prices randomized to start + return ..() + +/datum/controller/subsystem/gun_companies/Destroy() + for(var/company in companies) + QDEL_NULL(company) + for(var/company_unbought in unpurchased_companies) + QDEL_NULL(unpurchased_companies) + for(var/company_bought in purchased_companies) + QDEL_NULL(purchased_companies) + . = ..() + +/datum/controller/subsystem/gun_companies/Recover() + companies = SSgun_companies.companies + unpurchased_companies = SSgun_companies.unpurchased_companies + purchased_companies = SSgun_companies.purchased_companies + +/datum/controller/subsystem/gun_companies/fire(resumed) + var/list/passed_interest_tier = list() + // Company handling + for(var/company in companies) + var/datum/gun_company/company_datum = companies[company] + + // Set the prices of the companies, is intended to slowly scale up over time + company_datum.base_cost += max(rand(company_datum.cost_change_lower, company_datum.cost_change_upper), 0) + company_datum.base_cost = clamp(company_datum.base_cost, BASE_COST_MINIMUM, BASE_COST_MAXIMUM) + company_datum.base_cost = company_datum.base_cost <= BASE_COST_MINIMUM ? BASE_COST_MINIMUM : company_datum.base_cost + company_datum.cost = round(company_datum.base_cost * company_datum.cost_mult) + // knocking down the interest of all companies + var/interest_threshold = rand(INTEREST_LOWER_RAND, INTEREST_HIGHER_RAND) + var/interest_knockdown = 0.5 * interest_threshold + + if(company_datum in unpurchased_companies) + interest_knockdown *= 0.5 + + company_datum.interest = max(company_datum.interest - interest_knockdown, 0) + + // determining what heirarchy of interest the company falls in + if(company_datum.interest < interest_threshold) + passed_interest_tier[company_datum] = FAILED_INTEREST + + else + var/non_zero_threshold = interest_threshold ? interest_threshold : 1 + var/calc_threshold = non_zero_threshold * INTEREST_HIGH_MULT + if(calc_threshold > INTEREST_CAP) + calc_threshold = INTEREST_CAP + if(company_datum.interest < calc_threshold) + passed_interest_tier[company_datum] = PASSED_INTEREST + + else + passed_interest_tier[company_datum] = HIGH_INTEREST + + + var/list/products = subtypesof(/datum/armament_entry/cargo_gun) + // Setting cost and stock of armament entries + for(var/armament_category as anything in GLOB.armament_entries) + for(var/subcategory as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY]) + for(var/datum/armament_entry/armament_entry as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY][subcategory]) + if(products && !(armament_entry.type in products)) + continue + + var/datum/armament_entry/cargo_gun/entry_typecast = armament_entry + + for(var/company_gun in companies) + var/datum/gun_company/the_datum = companies[company_gun] + + if(the_datum.company_flag != entry_typecast.company_bitflag) + continue + + switch(passed_interest_tier[the_datum]) + + if(FAILED_INTEREST) + var/stock_failed = rand(0, 2) + entry_typecast.stock = max((round(stock_failed * entry_typecast.stock_mult)), 0) + var/gun_cost_failed = rand(entry_typecast.lower_cost, entry_typecast.upper_cost) + var/compound_cost = round(entry_typecast.cost * 0.1) + entry_typecast.cost = max((round((gun_cost_failed + (compound_cost + CARGO_CRATE_VALUE)) - (0.25 * entry_typecast.lower_cost)) ), 0) + entry_typecast.magazine_cost = round((entry_typecast.cost * INTEREST_LOW_MAG_COST) * the_datum.magazine_cost_mult) + + if(PASSED_INTEREST) + var/stock_passed = rand(0, 4) + entry_typecast.stock = max((round(stock_passed * entry_typecast.stock_mult) + 1), 0) + var/gun_cost_passed = rand(entry_typecast.lower_cost, entry_typecast.upper_cost) + var/compound_cost = round(entry_typecast.cost * 0.1) + entry_typecast.cost = max((round(gun_cost_passed + compound_cost) + CARGO_CRATE_VALUE), 0) + entry_typecast.magazine_cost = round((entry_typecast.cost * INTEREST_MED_MAG_COST) * the_datum.magazine_cost_mult) + + if(HIGH_INTEREST) + var/stock_interested = rand(0, 6) + entry_typecast.stock = max((round(stock_interested * entry_typecast.stock_mult) + 2), 0) + var/gun_cost_high = rand(entry_typecast.lower_cost, entry_typecast.upper_cost) + var/compound_cost = round(entry_typecast.cost * 0.1) + entry_typecast.cost = max(round(gun_cost_high + (compound_cost + CARGO_CRATE_VALUE)) , 0) + entry_typecast.magazine_cost = round((entry_typecast.cost * INTEREST_HIGH_MAG_COST) * the_datum.magazine_cost_mult) + +#undef MAX_HANDOUT_CHOICES +#undef INTEREST_HIGH_MULT +#undef INTEREST_CAP +#undef INTEREST_LOWER_RAND +#undef INTEREST_HIGHER_RAND +#undef BASE_COST_MINIMUM +#undef BASE_COST_MAXIMUM +#undef INTEREST_LOW_MAG_COST +#undef INTEREST_MED_MAG_COST +#undef INTEREST_HIGH_MAG_COST diff --git a/modular_skyrat/modules/gun_cargo/code/objects/access.dm b/modular_skyrat/modules/gun_cargo/code/objects/access.dm new file mode 100644 index 000000000000..e7e33cbafd14 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/access.dm @@ -0,0 +1,8 @@ +/obj/item/proc/get_gun_permit_iconstate() + var/obj/item/card/id/id_card = GetID() + + if(!id_card) + return "hudfan_no" + if(ACCESS_WEAPONS in id_card.GetAccess()) + return "hud_permit" + return "hudfan_no" diff --git a/modular_skyrat/modules/gun_cargo/code/objects/ammo_boxes.dm b/modular_skyrat/modules/gun_cargo/code/objects/ammo_boxes.dm new file mode 100644 index 000000000000..78de9353ebdb --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/ammo_boxes.dm @@ -0,0 +1,130 @@ +/obj/item/ammo_box/c9mm/ap + name = "ammo box (9mm AP)" + ammo_type = /obj/item/ammo_casing/c9mm/ap + +/obj/item/ammo_box/c9mm/hp + name = "ammo box (9mm HP)" + ammo_type = /obj/item/ammo_casing/c9mm/hp + +/obj/item/ammo_box/c9mm/fire + name = "ammo box (9mm Incen)" + ammo_type = /obj/item/ammo_casing/c9mm/fire + +/obj/item/ammo_box/c10mm/ap + name = "ammo box (10mm AP)" + ammo_type = /obj/item/ammo_casing/c10mm/ap + max_ammo = 20 + +/obj/item/ammo_box/c10mm/hp + name = "ammo box (10mm HP)" + ammo_type = /obj/item/ammo_casing/c10mm/hp + max_ammo = 20 + +/obj/item/ammo_box/c10mm/fire + name = "ammo box (10mm Incen)" + ammo_type = /obj/item/ammo_casing/c10mm/fire + max_ammo = 20 + +/obj/item/ammo_box/c46x30mm + name = "ammo box (4.6x30mm)" + icon = 'modular_skyrat/modules/gun_cargo/icons/ammo.dmi' + icon_state = "ammo_46" + ammo_type = /obj/item/ammo_casing/c46x30mm + max_ammo = 20 + +/obj/item/ammo_box/c46x30mm/ap + name = "ammo box (4.6x30mm AP)" + ammo_type = /obj/item/ammo_casing/c46x30mm/ap + +/obj/item/ammo_box/c46x30mm/rubber + name = "ammo box (4.6x30mm Rubber)" + ammo_type = /obj/item/ammo_casing/c46x30mm/rubber + +/obj/item/ammo_box/c32 + name = "ammo box (.32)" + icon = 'modular_skyrat/modules/gun_cargo/icons/ammo.dmi' + icon_state = "ammo_32" + ammo_type = /obj/item/ammo_casing/c32 + max_ammo = 20 + +/obj/item/ammo_box/c32/ap + name = "ammo box (.32 AP)" + ammo_type = /obj/item/ammo_casing/c32/ap + +/obj/item/ammo_box/c32/rubber + name = "ammo box (.32 Rubber)" + ammo_type = /obj/item/ammo_casing/c32/rubber + +/obj/item/ammo_box/c32/fire + name = "ammo box (.32 Incen)" + ammo_type = /obj/item/ammo_casing/c32_incendiary + +/obj/item/ammo_box/c34 + name = "ammo box (.34)" + icon = 'modular_skyrat/modules/gun_cargo/icons/ammo.dmi' + icon_state = "ammo_34" + ammo_type = /obj/item/ammo_casing/c34 + max_ammo = 20 + +/obj/item/ammo_box/c34/ap + name = "ammo box (.34 AP)" + ammo_type = /obj/item/ammo_casing/c34/ap + +/obj/item/ammo_box/c34/rubber + name = "ammo box (.34 Rubber)" + ammo_type = /obj/item/ammo_casing/c34/rubber + +/obj/item/ammo_box/c34/fire + name = "ammo box (.34 Incen)" + ammo_type = /obj/item/ammo_casing/c34_incendiary + +/obj/item/ammo_box/c12mm + name = "ammo box (12mm)" + icon = 'modular_skyrat/modules/gun_cargo/icons/ammo.dmi' + icon_state = "ammo_12mm" + ammo_type = /obj/item/ammo_casing/c12mm + max_ammo = 20 + +/obj/item/ammo_box/c12mm/ap + name = "ammo box (12mm AP)" + ammo_type = /obj/item/ammo_casing/c12mm/ap + +/obj/item/ammo_box/c12mm/hp + name = "ammo box (12mm HP)" + ammo_type = /obj/item/ammo_casing/c12mm/hp + +/obj/item/ammo_box/c12mm/fire + name = "ammo box (12mm Incen)" + ammo_type = /obj/item/ammo_casing/c12mm/fire + +/obj/item/storage/box/ammo_box/microfusion/bluespace + name = "bluespace microfusion cell container" + desc = "A box filled with microfusion cells." + +/obj/item/storage/box/ammo_box/microfusion/bluespace/PopulateContents() + new /obj/item/storage/bag/ammo(src) + new /obj/item/stock_parts/cell/microfusion/bluespace(src) + new /obj/item/stock_parts/cell/microfusion/bluespace(src) + new /obj/item/stock_parts/cell/microfusion/bluespace(src) + +/obj/item/storage/box/ammo_box/microfusion/bluespace/bagless + +/obj/item/storage/box/ammo_box/microfusion/bluespace/bagless/PopulateContents() + new /obj/item/stock_parts/cell/microfusion/bluespace(src) + new /obj/item/stock_parts/cell/microfusion/bluespace(src) + new /obj/item/stock_parts/cell/microfusion/bluespace(src) + +/obj/item/ammo_box/b10mm + name = "ammo box (10mm Auto)" + ammo_type = /obj/item/ammo_casing/b10mm + max_ammo = 20 + +/obj/item/ammo_box/b10mm/hp + name = "ammo box (10mm Auto HP)" + ammo_type = /obj/item/ammo_casing/b10mm/hp + max_ammo = 20 + +/obj/item/ammo_box/b10mm/rubber + name = "ammo box (10mm Auto Rubber)" + ammo_type = /obj/item/ammo_casing/b10mm/rubber + max_ammo = 20 diff --git a/modular_skyrat/modules/gun_cargo/code/objects/box.dm b/modular_skyrat/modules/gun_cargo/code/objects/box.dm new file mode 100644 index 000000000000..3295b47feb68 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/box.dm @@ -0,0 +1,15 @@ +/obj/item/storage/box/syringes/piercing + name = "piercing syringe box" + desc = "A five-pack of piercing syringes." + +/obj/item/storage/box/syringes/piercing/PopulateContents() + for(var/i in 1 to 5) + new /obj/item/reagent_containers/syringe/piercing(src) + +/obj/item/storage/box/syringes/bluespace + name = "bluespace syringe box" + desc = "A three-pack of piercing syringes." + +/obj/item/storage/box/syringes/piercing/PopulateContents() + for(var/i in 1 to 3) + new /obj/item/reagent_containers/syringe/bluespace(src) diff --git a/modular_skyrat/modules/gun_cargo/code/objects/cargo_console.dm b/modular_skyrat/modules/gun_cargo/code/objects/cargo_console.dm new file mode 100644 index 000000000000..b9f1e33e3405 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/cargo_console.dm @@ -0,0 +1,3 @@ +/obj/machinery/computer/cargo/ComponentInitialize() + . = ..() + AddComponent(/datum/component/armament/cargo_gun, subtypesof(/datum/armament_entry/cargo_gun), 0) diff --git a/modular_skyrat/modules/gun_cargo/code/objects/firing_pin.dm b/modular_skyrat/modules/gun_cargo/code/objects/firing_pin.dm new file mode 100644 index 000000000000..3c15a7542961 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/firing_pin.dm @@ -0,0 +1,34 @@ +GLOBAL_VAR_INIT(permit_pin_unrestricted, FALSE) +// Firing pin that can be used off station freely, and requires a permit to use on-station +/obj/item/firing_pin/permit_pin + name = "permit-locked firing pin" + desc = "A firing pin for a station who can't trust their crew. Only allows you to fire the weapon off-station or with a firearms permit.." + icon_state = "firing_pin_explorer" + fail_message = "You must have a permit or be off-station to fire this!" + can_remove = TRUE + +// This checks that the user isn't on the station Z-level. +/obj/item/firing_pin/permit_pin/pin_auth(mob/living/user) + var/turf/station_check = get_turf(user) + + if(obj_flags & EMAGGED) + return TRUE + + if(GLOB.permit_pin_unrestricted) + return TRUE + + var/obj/item/card/id/the_id = user.get_idcard() + + if(!the_id && is_station_level(station_check.z)) + return FALSE + + if(!is_station_level(station_check.z) || (ACCESS_WEAPONS in the_id.GetAccess())) + return TRUE + + +/obj/item/firing_pin + var/can_remove = TRUE + +/obj/item/firing_pin/emag_act(mob/user) + . = ..() + can_remove = TRUE diff --git a/modular_skyrat/modules/gun_cargo/code/objects/guns/interdyne.dm b/modular_skyrat/modules/gun_cargo/code/objects/guns/interdyne.dm new file mode 100644 index 000000000000..963132e0a1dd --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/guns/interdyne.dm @@ -0,0 +1,28 @@ +/obj/item/gun/ballistic/automatic/pistol/firefly/smartdart + name = "\improper I-94 'Honeybee'" + desc = "A 9mm sidearm made by Armadyne and modified by Interdyne, it features a slightly modified paint job and sports a SmartDart underbarrel attachment which can be fired with right click." + company_flag = COMPANY_INTERDYNE + icon = 'modular_skyrat/modules/gun_cargo/icons/honeybee.dmi' + icon_state = "honeybee" + company_flag = COMPANY_INTERDYNE + var/obj/item/gun/syringe/smartdart/underbarrel/underbarrel + +/obj/item/gun/ballistic/automatic/pistol/firefly/smartdart/Initialize() + . = ..() + underbarrel = new(src) + update_appearance() + +/obj/item/gun/ballistic/automatic/pistol/firefly/smartdart/afterattack_secondary(atom/target, mob/living/user, flag, params) + underbarrel.afterattack(target, user, flag, params) + return SECONDARY_ATTACK_CONTINUE_CHAIN + +/obj/item/gun/ballistic/automatic/pistol/firefly/smartdart/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/reagent_containers/syringe/smartdart)) + underbarrel.attackby(attacking_item, user, params) + else + ..() + +/obj/item/gun/syringe/smartdart/underbarrel + name = "SmartDart underbarrel device" + desc = "An underbarrel attachment for a pistol that fits a SmartDart." + has_gun_safety = FALSE diff --git a/modular_skyrat/modules/gun_cargo/code/objects/hud_glasses.dm b/modular_skyrat/modules/gun_cargo/code/objects/hud_glasses.dm new file mode 100644 index 000000000000..7c9ffdaf0667 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/hud_glasses.dm @@ -0,0 +1,7 @@ +/obj/item/clothing/glasses/hud/gun_permit + name = "permit HUD" + desc = "A heads-up display that scans humanoids in view, and displays if their current ID possesses a firearms permit or not." + icon = 'modular_skyrat/modules/gun_cargo/icons/hud_goggles.dmi' + worn_icon = 'modular_skyrat/modules/gun_cargo/icons/hud_goggles_worn.dmi' + icon_state = "permithud" + hud_type = DATA_HUD_PERMIT diff --git a/modular_skyrat/modules/gun_cargo/code/objects/keycard_auth.dm b/modular_skyrat/modules/gun_cargo/code/objects/keycard_auth.dm new file mode 100644 index 000000000000..364d367830e4 --- /dev/null +++ b/modular_skyrat/modules/gun_cargo/code/objects/keycard_auth.dm @@ -0,0 +1,4 @@ +/proc/toggle_permit_pins() + GLOB.permit_pin_unrestricted = !GLOB.permit_pin_unrestricted + minor_announce("Permit-locked firing pins have now had their locks [GLOB.permit_pin_unrestricted ? "removed" : "reinstated"].", "Weapons Systems Update:") + SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("permit-locked pins", GLOB.permit_pin_unrestricted ? "unlocked" : "locked")) diff --git a/modular_skyrat/modules/gun_cargo/icons/ammo.dmi b/modular_skyrat/modules/gun_cargo/icons/ammo.dmi new file mode 100644 index 0000000000000000000000000000000000000000..77460d0fcac59e079c2cefefb0bdcbf8bfda1657 GIT binary patch literal 541 zcmV+&0^R9JLGWpiV4 zX>fFDZ*Bkpc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainGjE%TBGg33t zGfE(w;*!LYR3K9+F*i3q-o#9ai!&v&s2C_>$i4;332KSjdF8w zsZ>^Q^>YDx2>`KMJbYm^+oS*h0QN~lK~z|U?bShU!yo`e(WGEQ0}EwMQQ@P0hNgk|{|{!cIfSlKND>$=9~2*A4ld_}nd z?F<R0kCU_1BwPf)d0BnYW7Dj07{|X zb}0bVN_(vcZ1VnZ0PM2w4Didt0Pn{GlDz*3fGm4vfZu-xco%@LC^w*;fkYolA|TVA f33&EXe($~k?RZsr2=T!|00000NkvXXu0mjfWTe*3 literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/gun_cargo/icons/honeybee.dmi b/modular_skyrat/modules/gun_cargo/icons/honeybee.dmi new file mode 100644 index 0000000000000000000000000000000000000000..e59ef5c0461c740ce27bd74fe024dfd023fa53c6 GIT binary patch literal 595 zcmV-Z0<8UsP)Jx)Bk(#m68pFCZ{5XagcpWMPS) zpE@)&-{0Sqz})X)YO1QLR8&+#LPBO_WXZ|NV`F1nSy_L7e^6CqFf~TI$H&**-Y`Z* za}3tY00001bW%=J06^y0W&i*HgnCq1bVOxyV{&P5bZKvH004NLQ&wDl08A-I zrtPcm>Hq)%1xZ9fR9J=WmeFp*APhx`-IC2MWZBYgZ8loi|NrA`+P6mCfR|PBu@WVM zd$}T!j4_Jxuj#saE#PX6w!=y}BJ@wseUE*m0TIwA*P7rB=haPASt zD>(s`=y~5>v+^23HW7y+191S>^RjP~_q+Y@{&6Ud0N!|Gj?+Bv_VfJtRjMCHFHaDr zY!J!=fZoe002ovPDHLkV1oB=1yBG0 literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/gun_cargo/icons/hud_goggles.dmi b/modular_skyrat/modules/gun_cargo/icons/hud_goggles.dmi new file mode 100644 index 0000000000000000000000000000000000000000..c4121b3b3b7d76c8b6be2afb2509cbb0e1beb3f1 GIT binary patch literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvxd5LK*8>L*2nh+L85_?`Gd`1M z{6Edu-rincUtdK<#lyqnQhmP?P$gqYkY6x^!?PP{Ku&H|NJNQCYH@N=WKhlO#F@nvH#g*lHV z9hnrO5WG@htA_bzmBl8mo!!Q&n^#C^q@6fAGi=I?*<6X*+B<&jZ0KcUI1nLyS7brr zS)j$Po-U3d8WWQfBnlk@CNv6mJZuQO8R~FC#fL#LK}b*I%`7#J@FOqc^b~^P6b%{~ vmw7Cj(718&#Ky^ug3DMmlsgQPZZI$yFJ$++IVX54&_D)HS3j3^P6i literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/gun_cargo/icons/hud_goggles_worn.dmi b/modular_skyrat/modules/gun_cargo/icons/hud_goggles_worn.dmi new file mode 100644 index 0000000000000000000000000000000000000000..8ec8b7fe6024034e0ef4a3d6aa79634777cf6bc4 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJqNiMQ4l4+-9++i&RQR3p|EO6UrxzKNZ#Z%+=i!m2-r~O^CC0MzPD?5M5qt40=;`OS z!+&0!{G*cDcGzUnNgelV(^l;^l6iCVsmR&;DJNAlMfsR#hTrthd$+-be?RLl<^vJZ zcXQ@UnhUf&)6>NTa+CU1*HwOY zscgBnWz)8$w;35GY^j#cTDyHo(Xu70zo(x`E30_kI@A1&<$goAnUNBkt1sw0I3HEV d3^X1NelVQqm1YpX68sq?{yMbrApn literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/gunsgalore/code/guns/akm.dm b/modular_skyrat/modules/gunsgalore/code/guns/akm.dm new file mode 100644 index 000000000000..34e05065b258 --- /dev/null +++ b/modular_skyrat/modules/gunsgalore/code/guns/akm.dm @@ -0,0 +1,48 @@ +/obj/item/gun/ballistic/automatic/akm + name = "\improper AKM rifle" + desc = "A timeless Russian infantry rifle chambered in an extremely outdated round. This is one of over two hundred million copies produced - in and outside of Sol. A tool for a revolution, an insurgency, justice, or crime. This rifle and its variants truly have no bounds." + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_guns40x32.dmi' + icon_state = "akm" + lefthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_righthand.dmi' + inhand_icon_state = "akm" + slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK + w_class = WEIGHT_CLASS_BULKY + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/akm + can_suppress = FALSE + burst_size = 3 + fire_delay = 2 + worn_icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_back.dmi' + worn_icon_state = "akm" + fire_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/akm_fire.ogg' + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magout.ogg' + alt_icons = TRUE + dirt_modifier = 0.75 + company_flag = COMPANY_IZHEVSK + +/obj/item/ammo_box/magazine/akm + name = "\improper AKM magazine" + desc = "a banana-shaped double-stack magazine able to hold 30 rounds of 7.62x39mm Soviet ammunition. It's said that in the early days of SolFed's spread, Spanish colony rebels often referred to these as 'Goat Horns'." + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_items.dmi' + icon_state = "akm" + ammo_type = /obj/item/ammo_casing/realistic/a762x39 + caliber = "a762x39" + max_ammo = 30 + multiple_sprites = AMMO_BOX_FULL_EMPTY + +/obj/item/ammo_box/magazine/akm/banana + name = "\improper RPK magazine" + desc = "a banana-shaped double-stack magazine able to hold 45 rounds of 7.62x39mm Soviet ammunition. It's meant to be used on a light machine gun, but it's just a longer AK magazine." + max_ammo = 45 + +/obj/item/gun/ballistic/automatic/akm/modern + name = "\improper tactical AKMS" + desc = "a modernized version of the most iconic infantry rifle ever produced. This one has aftermarket parts and attachments, making it a better contender against its modern buddies. It still uses the same outdated rounds." + icon_state = "akm_modern" + inhand_icon_state = "akm" + worn_icon_state = "akm" + fire_delay = 1 diff --git a/modular_skyrat/modules/gunsgalore/code/guns/luger.dm b/modular_skyrat/modules/gunsgalore/code/guns/luger.dm new file mode 100644 index 000000000000..c3be38587c74 --- /dev/null +++ b/modular_skyrat/modules/gunsgalore/code/guns/luger.dm @@ -0,0 +1,17 @@ +/obj/item/gun/ballistic/automatic/pistol/luger + name = "\improper Armadyne P-09X" + desc = "A small, light-weight reproduction of the Luger P08 from the 20th century, manufactured by the Oldarms division of the Armadyne Corporation. Chambered in 9mm." + icon_state = "luger" + inhand_icon_state = "luger" + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_guns.dmi' + lefthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_righthand.dmi' + fire_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/luger_fire.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/luger_mag_insert.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/luger_mag_insert.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/luger_mag_release.ogg' + eject_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/luger_mag_release.ogg' + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/luger_rack.ogg' + fire_sound_volume = 100 + suppressor_x_offset = 14 + company_flag = COMPANY_OLDARMS diff --git a/modular_skyrat/modules/gunsgalore/code/guns/mp40.dm b/modular_skyrat/modules/gunsgalore/code/guns/mp40.dm new file mode 100644 index 000000000000..bfd9f1a9232a --- /dev/null +++ b/modular_skyrat/modules/gunsgalore/code/guns/mp40.dm @@ -0,0 +1,42 @@ +/obj/item/gun/ballistic/automatic/mp40 + name = "\improper MP-40" + desc = "The instantly recognizable 'kraut gun'. Extremely outdated SMG that has only seen service during Sol-3's second World War. This one's a poor, unlicensed reproduction." + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_guns40x32.dmi' + icon_state = "mp40" + lefthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_righthand.dmi' + inhand_icon_state = "mp40" + worn_icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_back.dmi' + worn_icon_state = "mp40" + slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK + mag_type = /obj/item/ammo_box/magazine/mp40 + can_suppress = FALSE + burst_size = 3 + fire_delay = 1.7 + fire_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/mp40_fire.ogg' + fire_sound_volume = 100 + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magout.ogg' + alt_icons = TRUE + realistic = TRUE + company_flag = COMPANY_OLDARMS + +/obj/item/ammo_box/magazine/mp40 + name = "mp40 magazine (9mmx19)" + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_items.dmi' + icon_state = "mp40" + ammo_type = /obj/item/ammo_casing/c9mm + caliber = CALIBER_9MM + max_ammo = 32 + multiple_sprites = AMMO_BOX_FULL_EMPTY + +/obj/item/gun/ballistic/automatic/mp40/modern + name = "\improper MP-40k" + desc = "An extremely outdated German SMG that has been modified extensively with aftermarket parts. It looks like it came straight out of the videogame Return to Fortress Dogenstein." + icon_state = "mp40_modern" + inhand_icon_state = "mp40" + worn_icon_state = "mp40" + burst_size = 4 + fire_delay = 1.5 diff --git a/modular_skyrat/modules/gunsgalore/code/guns/ppsh.dm b/modular_skyrat/modules/gunsgalore/code/guns/ppsh.dm new file mode 100644 index 000000000000..322514db3071 --- /dev/null +++ b/modular_skyrat/modules/gunsgalore/code/guns/ppsh.dm @@ -0,0 +1,45 @@ +/obj/item/gun/ballistic/automatic/ppsh + name = "\improper Asha 76" + desc = "A reproduction of a simple Soviet SMG chambered in 7.62x25 Tokarev rounds. Its heavy wooden stock and leather breech buffer help absorb the bolt’s heavy recoil, making it great for spraying and praying. Uraaaa!" + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_guns40x32.dmi' + icon_state = "ppsh" + lefthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_righthand.dmi' + inhand_icon_state = "ppsh" + worn_icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_back.dmi' + worn_icon_state = "ppsh" + slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK + w_class = WEIGHT_CLASS_BULKY + mag_type = /obj/item/ammo_box/magazine/ppsh + can_suppress = FALSE + spread = 20 + burst_size = 6 + fire_delay = 0.5 + fire_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/ppsh_fire.ogg' + fire_sound_volume = 80 + alt_icons = TRUE + realistic = TRUE + dirt_modifier = 0.3 + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/smg_magout.ogg' + company_flag = COMPANY_OLDARMS + +/obj/item/ammo_box/magazine/ppsh + name = "Asha 76 magazine (7.62x25mm)" + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_items.dmi' + icon_state = "ppsh" + ammo_type = /obj/item/ammo_casing/realistic/a762x25 + caliber = "a762x25" + max_ammo = 71 + multiple_sprites = AMMO_BOX_FULL_EMPTY + +/obj/item/gun/ballistic/automatic/ppsh/modern + name = "\improper PPsh-59" + desc = "A modernized reproduction of a simple Soviet SMG with aftermarket parts. Its heavy synthetic stock and composite breech buffer help absorb the bolt’s heavy recoil, a mix of two worlds that should not exist." + icon_state = "ppsh_modern" + worn_icon_state = "ppsh" + inhand_icon_state = "ppsh" + spread = 15 + burst_size = 5 diff --git a/modular_skyrat/modules/gunsgalore/code/guns/stg.dm b/modular_skyrat/modules/gunsgalore/code/guns/stg.dm new file mode 100644 index 000000000000..c96d426e172b --- /dev/null +++ b/modular_skyrat/modules/gunsgalore/code/guns/stg.dm @@ -0,0 +1,37 @@ +/obj/item/gun/ballistic/automatic/stg + name = "\improper StG-99" + desc = "A reproduction of the Sturmgewehr 44 German infantry rifle chambered in 7.92mm, manufactured by the Oldarms division of the Armadyne Corporation." + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_guns40x32.dmi' + icon_state = "stg" + lefthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_righthand.dmi' + inhand_icon_state = "stg" + worn_icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_back.dmi' + worn_icon_state = "stg" + slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK + w_class = WEIGHT_CLASS_BULKY + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/stg + can_suppress = FALSE + burst_size = 4 + fire_delay = 1.5 + fire_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/fire/stg_fire.ogg' + fire_sound_volume = 70 + alt_icons = TRUE + realistic = TRUE + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_BURST_SHOT, SELECT_FULLY_AUTOMATIC) + rack_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_cock.ogg' + load_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magin.ogg' + eject_sound = 'modular_skyrat/modules/gunsgalore/sound/guns/interact/ltrifle_magout.ogg' + company_flag = COMPANY_OLDARMS + +/obj/item/ammo_box/magazine/stg + name = "stg magazine (7.92x33mm)" + icon = 'modular_skyrat/modules/gunsgalore/icons/guns/gunsgalore_items.dmi' + icon_state = "stg" + ammo_type = /obj/item/ammo_casing/realistic/a792x33 + caliber = "a792x33" + max_ammo = 30 + multiple_sprites = AMMO_BOX_FULL_EMPTY + diff --git a/modular_skyrat/modules/mapping/code/shuttles.dm b/modular_skyrat/modules/mapping/code/shuttles.dm new file mode 100644 index 000000000000..f0f589b9053b --- /dev/null +++ b/modular_skyrat/modules/mapping/code/shuttles.dm @@ -0,0 +1,191 @@ +/datum/map_template/shuttle/arrival/outpost + suffix = "outpost" + name = "arrival shuttle (Outpost)" + +/datum/map_template/shuttle/emergency/outpost + suffix = "outpost" + prefix = "_maps/shuttles/skyrat/" + name = "Outpoststation Emergency Shuttle" + description = "The perfect shuttle for rectangle enthuasiasts, this long and slender shuttle has been known for it's incredible(Citation Needed) safety rating." + admin_notes = "Has airlocks on both sides of the shuttle and will probably ram deltastation's maint wing below medical. Oh well?" + credit_cost = CARGO_CRATE_VALUE * 4 + +/*----- Black Market Shuttle Datum + related code -----*/ +/datum/map_template/shuttle/ruin/blackmarket_chevvy + prefix = "_maps/shuttles/skyrat/" + suffix = "blackmarket_chevvy" + name = "Black Market Chevvy" + +/obj/machinery/computer/shuttle/caravan/blackmarket_chevvy + name = "Chevvy Shuttle Console" + desc = "Used to control the affectionately named 'Chevvy'." + req_access = list(208) + circuit = /obj/item/circuitboard/computer/blackmarket_chevvy + shuttleId = "blackmarket_chevvy" + possible_destinations = "blackmarket_chevvy_custom;blackmarket_chevvy_home;whiteship_home" + +/obj/machinery/computer/camera_advanced/shuttle_docker/blackmarket_chevvy + name = "Chevvy Navigation Computer" + desc = "Used to designate a precise transit location for the affectionately named 'Chevvy'." + shuttleId = "blackmarket_chevvy" + lock_override = NONE + shuttlePortId = "blackmarket_chevvy_custom" + jump_to_ports = list("blackmarket_chevvy_home" = 1, "whiteship_home" = 1) + view_range = 0 + x_offset = 2 + y_offset = 0 + +/obj/item/circuitboard/computer/blackmarket_chevvy + name = "Chevvy Control Console (Computer Board)" + build_path = /obj/machinery/computer/shuttle/caravan/blackmarket_chevvy +/*----- End of Black Market Shuttle Code -----*/ + +/datum/map_template/shuttle/prison_transport + prefix = "_maps/shuttles/skyrat/" + port_id = "prison_transport" + suffix = "skyrat" + name = "Prison Transporter NSS-74" + + +/obj/machinery/computer/camera_advanced/shuttle_docker/slaver + name = "Ship Navigation Computer" + desc = "Used to designate a precise custom destination to land." + shuttleId = "slaver_syndie" + lock_override = NONE + shuttlePortId = "slaver" + jump_to_ports = list("whiteship_away" = 1, "whiteship_home" = 1, "whiteship_z4" = 1, "syndicate_ne" = 1, "syndicate_nw" = 1, "syndicate_n" = 1, "syndicate_se" = 1, "syndicate_sw" = 1, "syndicate_s" = 1) + view_range = 10 + x_offset = 0 + y_offset = 0 + designate_time = 30 + +/obj/machinery/computer/shuttle/slaver + name = "Ship Travel Terminal" + desc = "Controls for moving the ship to a pre-programmed destination or a custom one marked out by the navigation computer." + icon_screen = "syndishuttle" + icon_keyboard = "syndie_key" + light_color = COLOR_SOFT_RED + req_access = list(ACCESS_SYNDICATE) + shuttleId = "slaver_syndie" + possible_destinations = "syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + flags_1 = NODECONSTRUCT_1 + +/datum/map_template/shuttle/slaver_ship + port_id = "slaver ship" + prefix = "_maps/shuttles/skyrat/" + port_id = "slaver" + suffix = "syndie" + name = "Slaver Ship" + who_can_purchase = null + +/obj/effect/mob_spawn/ghost_role/human/guild + name = "Privateer Slaver" + prompt_name = "a privateer slaver" + you_are_text = "You're here to capture valuable hostages to sell into slavery." + flavour_text = "You're part of a privateer crew that sometimes takes contracts from the illusive Guild, which offers bounties and contracts to independent crews. Raiding colonies of the many less technologically advanced species in the area is much easier than this. You've been told that your mission is to capture as many valuable hostages from the station as possible. Your anonymous employer insists on the importance of humiliating SolFed by snatching those under their protection from right under their noses." + important_text = "" + +/obj/effect/mob_spawn/ghost_role/human/guild/slaver + name = "Privateer Slaver" + icon = 'icons/obj/machines/sleeper.dmi' + icon_state = "sleeper_s" + outfit = /datum/outfit/guild/slaver + +/obj/effect/mob_spawn/ghost_role/human/guild/slaver/captain + name = "Privateer Slaver Captain" + you_are_text = "You lead a small team focused on capturing hostages." + flavour_text = "You're the captain of a privateer crew that sometimes takes contracts from the illusive Guild, which offers bounties and contracts to independent crews, like yours! Lead your crew to infiltrate the station and capture hostages and hold them till the station's emergency shuttle leaves. The higher ranking the hostages, the more you'll get paid out. You're free to (and encouraged to) beat and humiliate, but not kill. Your anonymous employer wants your victims as their personel slaves. They mentioned something about propaganda? Ah, who knows with the Guild... All sorts of types posts these bounties." + important_text = "You are expected to roleplay heavily and lead effectively in this role." + outfit = /datum/outfit/guild/slaver/captain + +/obj/item/radio/headset/guild + keyslot = new /obj/item/encryptionkey/headset_guild + +/obj/item/radio/headset/guild/command + command = TRUE + +/datum/outfit/guild/slaver + name = "Privateer Slaver" + head = /obj/item/clothing/head/helmet/alt + suit = /obj/item/clothing/suit/armor/bulletproof + uniform = /obj/item/clothing/under/syndicate/combat + shoes = /obj/item/clothing/shoes/jackboots + gloves = /obj/item/clothing/gloves/tackler/combat/insulated + ears = /obj/item/radio/headset/guild + glasses = /obj/item/clothing/glasses/hud/security/chameleon + back = /obj/item/storage/backpack + implants = list(/obj/item/implant/weapons_auth) + belt = /obj/item/storage/belt/military + r_pocket = /obj/item/storage/bag/ammo + l_pocket = /obj/item/gun/energy/disabler/bolt_disabler + id = /obj/item/card/id/advanced/chameleon + id_trim = /datum/id_trim/chameleon/operative + skillchips = list(/obj/item/skillchip/job/engineer) + backpack_contents = list( + /obj/item/storage/box/survival/engineer/radio, + /obj/item/melee/baton/telescopic, + /obj/item/gun/ballistic/automatic/pistol/cfa_snub/empty, + /obj/item/ammo_box/magazine/multi_sprite/cfa_snub, + /obj/item/ammo_box/magazine/multi_sprite/cfa_snub, + /obj/item/ammo_box/magazine/multi_sprite/cfa_snub/ap, + /obj/item/ammo_box/magazine/multi_sprite/cfa_snub/rubber, + /obj/item/ammo_box/magazine/multi_sprite/cfa_snub/rubber, + /obj/item/grenade/c4, + /obj/item/grenade/smokebomb + ) + +/datum/outfit/guild/slaver/captain + name = "Privateer Slaver Captain" + head = /obj/item/clothing/head/helmet/alt + suit = /obj/item/clothing/suit/armor/bulletproof + uniform = /obj/item/clothing/under/syndicate/combat + shoes = /obj/item/clothing/shoes/jackboots + gloves = /obj/item/clothing/gloves/tackler/combat/insulated + ears = /obj/item/radio/headset/guild/command + glasses = /obj/item/clothing/glasses/thermal/syndi + back = /obj/item/storage/backpack + implants = list(/obj/item/implant/weapons_auth) + belt = /obj/item/storage/belt/military + r_pocket = /obj/item/storage/bag/ammo + l_pocket = /obj/item/gun/energy/disabler/bolt_disabler + id = /obj/item/card/id/advanced/chameleon + id_trim = /datum/id_trim/chameleon/operative + skillchips = list(/obj/item/skillchip/job/engineer) + backpack_contents = list( + /obj/item/storage/box/survival/engineer/radio, + /obj/item/melee/baton/telescopic, + /obj/item/gun/ballistic/automatic/pistol/cfa_ruby/empty, + /obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/ap, + /obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/ap, + /obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/rubber, + /obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/rubber, + /obj/item/megaphone/command + ) + +/*----- Tarkon Shuttle Datum + related code -----*/ +/datum/map_template/shuttle/ruin/tarkon_driver + prefix = "_maps/skyrat/shuttles/" + suffix = "tarkon_driver" + name = "Tarkon Drill Driver" + +/obj/machinery/computer/shuttle/tarkon_driver + name = "Tarkon Driver Control" + desc = "Used to control the Tarkon Driver." + circuit = /obj/item/circuitboard/computer/tarkon_driver + shuttleId = "tarkon_driver" + possible_destinations = "tarkon_driver_custom;port_tarkon;whiteship_home" + +/obj/machinery/computer/camera_advanced/shuttle_docker/tarkon_driver + name = "Tarkon Driver Navigation Computer" + desc = "The Navigation console for the Tarkon Driver. A broken \"Engage Drill\" button seems to dimly blink in a yellow colour" + shuttleId = "tarkon_driver" + lock_override = NONE + shuttlePortId = "tarkon_driver_custom" + jump_to_ports = list("port_tarkon" = 1, "whiteship_home" = 1) + view_range = 0 + +/obj/item/circuitboard/computer/tarkon_driver + name = "Chevvy Control Console (Computer Board)" + build_path = /obj/machinery/computer/shuttle/tarkon_driver +/*----- End of Tarkon Shuttle Code -----*/ diff --git a/modular_skyrat/modules/modular_weapons/code/autolathe_designs.dm b/modular_skyrat/modules/modular_weapons/code/autolathe_designs.dm new file mode 100644 index 000000000000..23d593451598 --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/autolathe_designs.dm @@ -0,0 +1,120 @@ +//////////////////////// +//ID: MODULAR_WEAPONS // +//////////////////////// + +//////////////////////// +// AMMO // +//////////////////////// + +// .32 - 15 damage pistol round. + +/datum/design/c32 + name = ".32 Bullet" + id = "c32" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c32 + category = list("hacked", "Security") + +/datum/design/c32/rubber + name = ".32 Rubber Bullet" + id = "c32/rubber" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c32/rubber + category = list("initial", "Security") + +/datum/design/a762 + name = "7.62 Bullet" + id = "a762" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 2000) + build_path = /obj/item/ammo_casing/a762 + category = list("hacked", "Security") + +/datum/design/a762_rubber + name = "7.62 Rubber Bullet" + id = "a762_rubber" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 2000) + build_path = /obj/item/ammo_casing/a762/rubber + category = list("hacked", "Security") + +// 4.6x30mm - SMG round, used in the WT550 and in numerous modular guns as a weaker alternative to 9mm. + +/datum/design/c46x30mm + name = "4.6x30mm Bullet" + id = "c46x30mm" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c46x30mm + category = list("hacked", "Security") + +/datum/design/c46x30mm_rubber + name = "4.6x30mm Rubber Bullet" + id = "c46x30mm_rubber" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c46x30mm/rubber + category = list("initial", "Security") + +// .45 + +/datum/design/c45_lethal + name = ".45 Bullet" + id = "c45_lethal" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c45 + category = list("hacked", "Security") + +/datum/design/c45_rubber + name = ".45 Bouncy Rubber Ball" + id = "c45_rubber" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c45/rubber + category = list("initial", "Security") + +// .460 Rowland magnum, for the M45A5 + +/datum/design/b460 + name = ".460 Rowland magnum" + id = "b460" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1500) + build_path = /obj/item/ammo_casing/b460 + category = list("hacked", "Security") + +// 10mm Magnum +/datum/design/c10mm_lethal + name = "10mm Magnum bullet" + id = "c10mm_lethal" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c10mm + category = list("hacked", "Security") + +/datum/design/c10mm_rubber + name = "10mm Magnum rubber bullet" + id = "c10mm_rubber" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/ammo_casing/c10mm/rubber + category = list("initial", "Security") + +/datum/design/shotgun_slug + name = "Shotgun Slug" + id = "shotgun_slug" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 6000) + build_path = /obj/item/ammo_casing/shotgun + category = list("hacked", "Security") + +/datum/design/buckshot_shell + name = "Buckshot Shell" + id = "buckshot_shell" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 4000) + build_path = /obj/item/ammo_casing/shotgun/buckshot + category = list("hacked", "Security") diff --git a/modular_skyrat/modules/modular_weapons/code/automatic.dm b/modular_skyrat/modules/modular_weapons/code/automatic.dm new file mode 100644 index 000000000000..5599ee8ca094 --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/automatic.dm @@ -0,0 +1,112 @@ +//////////////////////// +//ID: MODULAR_WEAPONS // +//////////////////////// + +// Magazines + +/obj/item/ammo_box/magazine/multi_sprite/cfa_wildcat + name = "CFA Wildcat magazine (.34)" + desc = "Magazines taking .34 ammunition; it fits in the CFA Wildcat. Alt+click to reskin it." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi' + icon_state = "smg34" + possible_types = list(AMMO_TYPE_LETHAL, AMMO_TYPE_AP, AMMO_TYPE_RUBBER, AMMO_TYPE_INCENDIARY) + ammo_type = /obj/item/ammo_casing/c34 + caliber = "c34acp" + max_ammo = 30 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/cfa_wildcat/ap + ammo_type = /obj/item/ammo_casing/c34/ap + round_type = AMMO_TYPE_AP + +/obj/item/ammo_box/magazine/multi_sprite/cfa_wildcat/rubber + ammo_type = /obj/item/ammo_casing/c34/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/ammo_box/magazine/multi_sprite/cfa_wildcat/incendiary + ammo_type = /obj/item/ammo_casing/c34_incendiary + round_type = AMMO_TYPE_INCENDIARY + +/obj/item/ammo_box/magazine/multi_sprite/cfa_wildcat/empty + start_empty = 1 + +/////////////// +// Wildcat // +/////////////// +// 3rnd burst .32 calibre, 15 damage. +// Fills the role of a low damage, high magazine capacity magdump gun. +/obj/item/gun/ballistic/automatic/cfa_wildcat + name = "\improper CFA Wildcat" + desc = "A robust roller-delayed SMG chambered for .34 ammunition." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile40x32.dmi' + icon_state = "mp5" + inhand_icon_state = "arg" + selector_switch_icon = TRUE + mag_type = /obj/item/ammo_box/magazine/multi_sprite/cfa_wildcat + can_suppress = FALSE + burst_size = 3 + fire_delay = 1.25 + spread = 5 + mag_display = TRUE + empty_indicator = FALSE + fire_sound = 'sound/weapons/gun/smg/shot_alt.ogg' + weapon_weight = WEAPON_MEDIUM + w_class = WEIGHT_CLASS_BULKY + company_flag = COMPANY_CANTALAN + dirt_modifier = 0.2 + +/obj/item/gun/ballistic/automatic/cfa_wildcat/no_mag + spawnwithmagazine = FALSE + +/////////////// +// MP7 // +/////////////// + +/obj/item/gun/ballistic/automatic/cfa_lynx + name = "\improper CFA Lynx" + desc = "A carbine with a high magazine capacity. Chambered in 4.2x30mm." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile.dmi' + icon_state = "cfa-lynx" + inhand_icon_state = "arg" + selector_switch_icon = FALSE + mag_type = /obj/item/ammo_box/magazine/multi_sprite/cfa_lynx + can_suppress = FALSE + burst_size = 3 + fire_delay = 1.90 //Previously 0.5. Changed due to it being the Blueshield's default firearm. + spread = 2 + mag_display = TRUE + empty_indicator = FALSE + fire_sound = 'sound/weapons/gun/smg/shot_alt.ogg' + weapon_weight = WEAPON_MEDIUM + w_class = WEIGHT_CLASS_BULKY + company_flag = COMPANY_CANTALAN + dirt_modifier = 0.2 + +/obj/item/gun/ballistic/automatic/cfa_lynx/no_mag + spawnwithmagazine = FALSE + +/obj/item/ammo_box/magazine/multi_sprite/cfa_lynx + name = "CFA Lynx Magazine (4.2x30mm)" + desc = "A magazine for the CFA Lynx. It has a small inscription on the base, '4.2x30mm'. Alt+click to reskin it." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi' + icon_state = "lynx" + possible_types = list(AMMO_TYPE_LETHAL, AMMO_TYPE_AP, AMMO_TYPE_RUBBER, AMMO_TYPE_INCENDIARY) + ammo_type = /obj/item/ammo_casing/c42x30mm + caliber = CALIBER_42X30MM + max_ammo = 40 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/cfa_lynx/ap + ammo_type = /obj/item/ammo_casing/c42x30mm/ap + round_type = AMMO_TYPE_AP + +/obj/item/ammo_box/magazine/multi_sprite/cfa_lynx/rubber + ammo_type = /obj/item/ammo_casing/c42x30mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/ammo_box/magazine/multi_sprite/cfa_lynx/incendiary + ammo_type = /obj/item/ammo_casing/c42x30mm/inc + round_type = AMMO_TYPE_INCENDIARY + +/obj/item/ammo_box/magazine/multi_sprite/cfa_lynx/empty + start_empty = TRUE diff --git a/modular_skyrat/modules/modular_weapons/code/energy.dm b/modular_skyrat/modules/modular_weapons/code/energy.dm new file mode 100644 index 000000000000..96ec60e501ab --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/energy.dm @@ -0,0 +1,230 @@ +////////////////////// +// Bolt Responder // +////////////////////// +// A mini disabler with 12 shot capacity in comparison to the normal disabler's 20. + +/obj/item/gun/energy/disabler/bolt_disabler + name = "Bolt Responder" + desc = "A pocket-sized non-lethal energy gun with low ammo capacity." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile.dmi' + icon_state = "cfa-disabler" + inhand_icon_state = null + ammo_type = list(/obj/item/ammo_casing/energy/disabler) + ammo_x_offset = 2 + w_class = WEIGHT_CLASS_SMALL + cell_type = /obj/item/stock_parts/cell/mini_egun + ammo_x_offset = 2 + charge_sections = 3 + can_flashlight = FALSE // Can't attach or detach the flashlight, and override it's icon update + gunlight_state = "cfa-disabler-light" + has_gun_safety = FALSE + company_flag = COMPANY_BOLT + +/obj/item/gun/energy/disabler/bolt_disabler/Initialize() + set_gun_light(new /obj/item/flashlight/seclite(src)) + return ..() + +////////////////////// +// CFA Phalanx // +////////////////////// +// Similar to the HoS's laser. Fires a bouncing non-lethal, lethal and knockdown projectile. + +/obj/item/gun/energy/e_gun/cfa_phalanx + name = "\improper Mk.II Phalanx plasma blaster" + desc = "Fires a disabling and lethal bouncing projectile, as well as a special muscle-seizing projectile that knocks targets down. It has Cantalan Federal Arms etched into the grip." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile.dmi' + icon_state = "phalanx1" + w_class = WEIGHT_CLASS_NORMAL + force = 10 + ammo_type = list(/obj/item/ammo_casing/energy/disabler/bounce, /obj/item/ammo_casing/energy/laser/bounce, /obj/item/ammo_casing/energy/electrode/knockdown) + ammo_x_offset = 1 + charge_sections = 5 + has_gun_safety = FALSE + cell_type = /obj/item/stock_parts/cell/hos_gun + +////////////////////// +// CFA Paladin // +////////////////////// +// Identical to a heavy laser. + +/obj/item/gun/energy/laser/cfa_paladin + name = "\improper Mk.IV Paladin plasma carbine" + desc = "Essentially a handheld laser cannon. This is solely for killing, and it's dual-laser system reflects that. It has Cantalan Federal Arms etched into the grip." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile.dmi' + icon_state = "paladin" + force = 10 + ammo_type = list(/obj/item/ammo_casing/energy/laser/double) + charge_sections = 5 + has_gun_safety = FALSE + +////////////////////// +// Bounce Disabler // +////////////////////// +// It's a disabler that will always ricochet. + +/obj/item/ammo_casing/energy/disabler/bounce + projectile_type = /obj/projectile/beam/disabler/bounce + select_name = "disable" + e_cost = 60 + fire_sound = 'sound/weapons/taser2.ogg' + harmful = FALSE + +/obj/effect/projectile/tracer/disabler/bounce + name = "disabler" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/projectiles.dmi' + icon_state = "bouncebeam" + +/obj/projectile/beam/disabler/bounce + name = "disabler arc" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/projectiles.dmi' + icon_state = "bouncebeam" + damage = 30 + damage_type = STAMINA + armor_flag = ENERGY + eyeblur = 1 + tracer_type = /obj/effect/projectile/tracer/disabler/bounce + light_range = 5 + light_power = 0.75 + speed = 1.4 + ricochets_max = 6 + ricochet_incidence_leeway = 170 + ricochet_chance = 130 + ricochet_decay_damage = 0.9 + +/obj/projectile/beam/disabler/bounce/check_ricochet_flag(atom/A) + return TRUE +// Allows the projectile to reflect on walls like how bullets ricochet. + +////////////////////// +// Bounce Laser // +////////////////////// +// It's a laser that will always ricochet. + +/obj/item/ammo_casing/energy/laser/bounce + projectile_type = /obj/projectile/beam/laser/bounce + select_name = "lethal" + e_cost = 100 + +/obj/projectile/beam/laser/bounce + name = "energy arc" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/projectiles.dmi' + icon_state = "bouncebeam_red" + damage = 20 + damage_type = BURN + armor_flag = LASER + light_range = 5 + light_power = 0.75 + speed = 1.4 + ricochets_max = 6 + ricochet_incidence_leeway = 170 + ricochet_chance = 130 + ricochet_decay_damage = 0.9 + +/obj/projectile/beam/laser/bounce/check_ricochet_flag(atom/A) + return TRUE +// Allows the projectile to reflect on walls like how bullets ricochet. + +////////////////////// +// Knockdown Bolt // +////////////////////// +// A taser that had the same stamina impact as a disabler, but a five-second knockdown and taser hitter effects. + +/obj/item/ammo_casing/energy/electrode/knockdown + projectile_type = /obj/projectile/energy/electrode/knockdown + select_name = "knockdown" + fire_sound = 'sound/weapons/taser.ogg' + e_cost = 200 + harmful = FALSE + +/obj/projectile/energy/electrode/knockdown + name = "electrobolt" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/projectiles.dmi' + icon_state = "electro_bolt" + knockdown = 50 + stamina = 30 + range = 6 + +////////////////////// +// Single Laser // +////////////////////// +// Has an unique sprite, it's a low-powered laser for rapid fire. Pea-shooter tier. + +/obj/item/ammo_casing/energy/laser/single + projectile_type = /obj/projectile/beam/laser/single + e_cost = 50 + select_name = "lethal" + +/obj/projectile/beam/laser/single + name = "laser bolt" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/projectiles.dmi' + icon_state = "single_laser" + damage = 15 + eyeblur = 1 + light_range = 5 + light_power = 0.75 + speed = 0.5 + armour_penetration = 10 + +////////////////////// +// Double Laser // +////////////////////// +// Visually, this fires two lasers. In code, it's just one. It's fast and great for turrets. + +/obj/item/ammo_casing/energy/laser/double + projectile_type = /obj/projectile/beam/laser/double + e_cost = 100 + select_name = "lethal" + fire_sound = 'sound/weapons/lasercannonfire.ogg' + +/obj/projectile/beam/laser/double + name = "laser bolt" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/projectiles.dmi' + icon_state = "double_laser" + damage = 40 + eyeblur = 1 + light_range = 5 + light_power = 0.75 + speed = 0.5 + armour_penetration = 10 + +////////////////////// +// Energy Bullets // +////////////////////// +// Ballistic gunplay but it allows us to target a different part of the armour block. +// Also allows the benefits of lasers (blobs strains, xenos) over bullets to be used with ballistic gunplay. + +/obj/item/ammo_casing/caseless/laser + name = "type I plasma projectile" + desc = "A chemical mixture that once triggered, creates a deadly projectile, melting it's own casing in the process." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi' + icon_state = "plasma_shell" + worn_icon_state = "shell" + caliber = "Beam Shell" + custom_materials = list(/datum/material/iron=4000,/datum/material/plasma=250) + projectile_type = /obj/projectile/beam/laser/single + +/obj/item/ammo_casing/caseless/laser/double + name = "type II plasma projectile" + desc = "A chemical mixture that once triggered, creates a deadly projectile, melting it's own casing in the process." + icon_state = "plasma_shell2" + worn_icon_state = "shell" + caliber = "Beam Shell" + custom_materials = list(/datum/material/iron=4000,/datum/material/plasma=500) + projectile_type = /obj/projectile/beam/laser/double + +/obj/item/ammo_casing/caseless/laser/bounce + name = "type III reflective projectile (Lethal)" + desc = "A chemical mixture that once triggered, creates a deadly bouncing projectile, melting it's own casing in the process." + icon_state = "bounce_shell" + worn_icon_state = "shell" + caliber = "Beam Shell" + custom_materials = list(/datum/material/iron=4000,/datum/material/plasma=250) + projectile_type = /obj/projectile/beam/laser/bounce + +/obj/item/ammo_casing/caseless/laser/bounce/disabler + name = "type III reflective projectile (Disabler)" + desc = "A chemical mixture that once triggered, creates bouncing disabler projectile, melting it's own casing in the process." + icon_state = "disabler_shell" + projectile_type = /obj/projectile/beam/disabler/bounce + + diff --git a/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm b/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm new file mode 100644 index 000000000000..0cbb9a9eca3d --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm @@ -0,0 +1,401 @@ +//////////////////////// +//ID: MODULAR_WEAPONS // +//////////////////////// + +//////////////////////// +////// .32 ACP ////// + +/obj/item/ammo_casing/c32 + name = ".32 bullet casing" + desc = "A .32 bullet casing." + caliber = "c32acp" + projectile_type = /obj/projectile/bullet/c32 + +/obj/projectile/bullet/c32 + name = ".32 bullet" + damage = 15 + wound_bonus = 0 + +/obj/item/ammo_casing/c32/rubber + name = ".32 rubber bullet casing" + desc = "A .32 rubber bullet casing." + caliber = "c32acp" + projectile_type = /obj/projectile/bullet/c32/rubber + harmful = FALSE + +/obj/projectile/bullet/c32/rubber + name = ".32 rubber bullet" + damage = 5 + stamina = 20 + wound_bonus = -75 + shrapnel_type = null + sharpness = NONE + embedding = null + +/obj/item/ammo_casing/c32/ap + name = ".32 armor-piercing bullet" + desc = "A .32 armor-piercing bullet casing." + caliber = "c32acp" + projectile_type = /obj/projectile/bullet/c32/ap + +/obj/projectile/bullet/c32/ap + name = ".32 armor-piercing bullet" + damage = 15 + armour_penetration = 40 + wound_bonus = -75 + +/obj/item/ammo_casing/c32_incendiary + name = ".32 incendiary bullet" + desc = "A .32 incendiary bullet casing." + caliber = "c32acp" + projectile_type = /obj/projectile/bullet/incendiary/c32_incendiary + +/obj/projectile/bullet/incendiary/c32_incendiary + name = ".32 incendiary bullet" + damage = 8 + fire_stacks = 1 + wound_bonus = -90 + +////// .32 ACP ////// +//////////////////////// +///// 10mm Magnum ///// + +/obj/item/ammo_casing/c10mm/rubber + name = "10mm Magnum rubber bullet casing" + desc = "A 10mm Magnum bullet casing. This fires a non-lethal projectile to cause compliance by pain and bruising. Don't aim for the head." + caliber = CALIBER_10MM + projectile_type = /obj/projectile/bullet/c10mm/rubber + harmful = FALSE + +/obj/projectile/bullet/c10mm/rubber + name = "10mm Magnum rubber ball" + damage = 10 + stamina = 40 + ricochets_max = 6 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + +///// 10mm Magnum ///// +//////////////////////// +////// .45 ACP ////// + +/obj/item/ammo_casing/c45/rubber + name = ".45 rubber bullet casing" + desc = "A .45 bullet casing." + projectile_type = /obj/projectile/bullet/c45/rubber + +/obj/projectile/bullet/c45/rubber + name = ".45 rubber ball" + damage = 10 + stamina = 30 + ricochets_max = 6 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + wound_bonus = -50 + +////// .45 ACP ////// +//////////////////////// +///// HK 4.6x30mm ///// + +/obj/projectile/bullet/c46x30mm_rubber + name = "4.6x30mm rubber bullet" + damage = 3 + stamina = 17 + ricochets_max = 6 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + wound_bonus = -50 + +/obj/item/ammo_casing/c46x30mm/rubber + name = "4.6x30mm rubber bullet casing" + desc = "A 4.6x30mm rubber bullet casing." + projectile_type = /obj/projectile/bullet/c46x30mm_rubber + harmful = FALSE + +///// HK 4.6x30mm ///// +//////////////////////// +//// 5.56x30mm MARS //// + +/obj/item/ammo_casing/a556/rubber + name = "5.56mm rubber bullet casing" + desc = "A 5.56mm rubber bullet casing." + caliber = CALIBER_A556 + projectile_type = /obj/projectile/bullet/a556/rubber + harmful = FALSE + +/obj/projectile/bullet/a556/rubber + name = "5.56mm rubber bullet" + damage = 10 + armour_penetration = 10 + stamina = 30 + ricochets_max = 6 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + wound_bonus = -50 + +/obj/item/ammo_casing/a556/ap + name = "5.56mm AP bullet casing" + desc = "A 5.56mm AP bullet casing." + caliber = CALIBER_A556 + projectile_type = /obj/projectile/bullet/a556/ap + +/obj/projectile/bullet/a556/ap + name = "5.56mm AP bullet" + armour_penetration = 60 + +//// 5.56x30mm MARS //// +//////////////////////// +////// 7.62 ////// + +/obj/item/ammo_casing/a762/rubber + name = "7.62 rubber bullet casing" + desc = "A 7.62 rubber bullet casing. This is isn't exactly 'non-lethal'." + icon_state = "762-casing" + caliber = CALIBER_A762 + projectile_type = /obj/projectile/bullet/a762/rubber + harmful = FALSE + +/obj/projectile/bullet/a762/rubber + name = "7.62mm rubber bullet" + damage = 15 + stamina = 55 + ricochets_max = 5 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + +////// 7.62 ////// +//////////////////////// +///// 5.56x45mm ///// +// Very good at piercing armour at short range, not as good at going through armour at over 100m. But this is SS13... + +/// The 5.56 you see pretty much everyone under NATO use. +#define CALIBER_A556x45 "a556x45" +/obj/item/ammo_casing/a556x45 + name = "5.56x45mm bullet casing" + desc = "A 5.56mm rubber bullet casing." + caliber = CALIBER_A556x45 + projectile_type = /obj/projectile/bullet/a556x45 + +/obj/projectile/bullet/a556x45 + name = "5.56x45mm bullet" + damage = 50 + armour_penetration = 20 + stamina = 10 + speed = 0.2 + wound_bonus = 20 + bare_wound_bonus = 10 + +///// 5.56x45mm ///// +//////////////////////// +////// .34 ACP ////// +// Why? Blame CFA, they want their bullets to be *proprietary* +/obj/item/ammo_casing/c34 + name = ".34 bullet casing" + desc = "A .34 bullet casing." + caliber = "c32acp" + projectile_type = /obj/projectile/bullet/c34 + +/obj/projectile/bullet/c34 + name = ".34 bullet" + damage = 15 + wound_bonus = 0 + +/obj/item/ammo_casing/c34/rubber + name = ".34 rubber bullet casing" + desc = "A .34 rubber bullet casing." + caliber = "c34acp" + projectile_type = /obj/projectile/bullet/c34/rubber + harmful = FALSE + +/obj/projectile/bullet/c34/rubber + name = ".34 rubber bullet" + damage = 5 + stamina = 20 + wound_bonus = -75 + shrapnel_type = null + sharpness = NONE + embedding = null + +/obj/item/ammo_casing/c34/ap + name = ".34 armor-piercing bullet" + desc = "A .34 armor-piercing bullet casing." + caliber = "c34acp" + projectile_type = /obj/projectile/bullet/c34/ap + +/obj/projectile/bullet/c34/ap + name = ".34 armor-piercing bullet" + damage = 15 + armour_penetration = 40 + wound_bonus = -75 + +/obj/item/ammo_casing/c34_incendiary + name = ".34 incendiary bullet" + desc = "A .34 incendiary bullet casing." + caliber = "c34acp" + projectile_type = /obj/projectile/bullet/incendiary/c34_incendiary + +/obj/projectile/bullet/incendiary/c34_incendiary + name = ".34 incendiary bullet" + damage = 8 + fire_stacks = 1 + wound_bonus = -90 + +////// .34 ACP ////// +//////////////////////// +////// 4.2x30mm ////// + +/obj/item/ammo_casing/c42x30mm + name = "4.2x30mm bullet casing" + desc = "A 4.2x30mm bullet casing." + caliber = CALIBER_42X30MM + projectile_type = /obj/projectile/bullet/c42x30mm + +/obj/item/ammo_casing/c42x30mm/ap + name = "4.2x30mm armor-piercing bullet casing" + desc = "A 4.2x30mm armor-piercing bullet casing." + projectile_type = /obj/projectile/bullet/c42x30mm/ap + +/obj/item/ammo_casing/c42x30mm/inc + name = "4.2x30mm incendiary bullet casing" + desc = "A 4.2x30mm incendiary bullet casing." + projectile_type = /obj/projectile/bullet/incendiary/c42x30mm + +/obj/projectile/bullet/c42x30mm + name = "4.2x30mm bullet" + damage = 20 + wound_bonus = -5 + bare_wound_bonus = 5 + embed_falloff_tile = -4 + +/obj/projectile/bullet/c42x30mm/ap + name = "4.2x30mm armor-piercing bullet" + damage = 15 + armour_penetration = 40 + embedding = null + +/obj/projectile/bullet/incendiary/c42x30mm + name = "4.2x30mm incendiary bullet" + damage = 10 + fire_stacks = 1 + +/obj/projectile/bullet/c42x30mm_rubber + name = "4.2x30mm rubber bullet" + damage = 3 + stamina = 17 + ricochets_max = 6 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + wound_bonus = -50 + +/obj/item/ammo_casing/c42x30mm/rubber + name = "4.2x30mm rubber bullet casing" + desc = "A 4.2x30mm rubber bullet casing." + projectile_type = /obj/projectile/bullet/c42x30mm_rubber + harmful = FALSE + +////// 4.2x30mm ////// +//////////////////////// +////// 12mm ////// + +/obj/item/ammo_casing/c12mm + name = "12mm Magnum bullet casing" + desc = "A 12mm Magnum bullet casing." + caliber = CALIBER_12MM + projectile_type = /obj/projectile/bullet/c12mm + +/obj/item/ammo_casing/c12mm/ap + name = "12mm Magnum armor-piercing bullet casing" + desc = "A 12mm Magnum bullet casing with a tungsten core tip." + projectile_type = /obj/projectile/bullet/c12mm/ap + +/obj/item/ammo_casing/c12mm/hp + name = "12mm Magnum hollow-point bullet casing" + desc = "A 12mm Magnum bullet casing with a hollow tip that fragments on contact." + projectile_type = /obj/projectile/bullet/c12mm/hp + +/obj/item/ammo_casing/c12mm/fire + name = "12mm Magnum incendiary bullet casing" + desc = "A 12mm Magnum bullet casing with a magnesium coated tip meant for setting things on fire." + projectile_type = /obj/projectile/bullet/incendiary/c12mm + +/obj/item/ammo_casing/c12mm/rubber + name = "12mm Magnum rubber bullet casing" + desc = "A low powder load 12mm Magnum bullet casing with a flat rubber tip. Headshots heavily discouraged." + projectile_type = /obj/projectile/bullet/c12mm/rubber + harmful = FALSE + +/obj/projectile/bullet/c12mm + name = "12mm bullet" + damage = 40 + +/obj/projectile/bullet/c12mm/ap + name = "12mm armor-piercing bullet" + damage = 37 + armour_penetration = 40 + +/obj/projectile/bullet/c12mm/hp + name = "12mm hollow-point bullet" + damage = 60 + weak_against_armour = TRUE + +/obj/projectile/bullet/incendiary/c12mm + name = "12mm incendiary bullet" + damage = 20 + fire_stacks = 2 + +/obj/projectile/bullet/c12mm/rubber + name = "12mm Magnum rubber ball" + damage = 10 + stamina = 40 + ricochets_max = 6 + ricochet_incidence_leeway = 0 + ricochet_chance = 130 + ricochet_decay_damage = 0.7 + shrapnel_type = null + sharpness = NONE + embedding = null + +////// 12mm ////// +//////////////////////// +////// 6.8x43mm ////// + + +/obj/item/ammo_casing/a68 + name = "6.8mm bullet casing" + desc = "A 6.8mm bullet casing." + icon_state = "762-casing" + caliber = CALIBER_A68 + projectile_type = /obj/projectile/bullet/a68 + +/obj/projectile/bullet/a68 + name = "6.8 bullet" + damage = 55 + armour_penetration = 10 + wound_bonus = -45 + wound_falloff_tile = 0 + +////// 6.8x43mm ////// diff --git a/modular_skyrat/modules/modular_weapons/code/pistol.dm b/modular_skyrat/modules/modular_weapons/code/pistol.dm new file mode 100644 index 000000000000..61f64db38ff5 --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/pistol.dm @@ -0,0 +1,98 @@ +//////////////////////// +//ID: MODULAR_WEAPONS // +//////////////////////// + +//////////////////////// +// PISTOLS // +//////////////////////// + +/obj/item/gun/ballistic/automatic/pistol/cfa_snub + name = "CFA Snub" + desc = "An easily-concealable pistol chambered for 4.2x30mm." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile.dmi' + icon_state = "cfa-snub" + mag_type = /obj/item/ammo_box/magazine/multi_sprite/cfa_snub + can_suppress = TRUE + fire_sound_volume = 30 + w_class = WEIGHT_CLASS_SMALL + has_gun_safety = FALSE + company_flag = COMPANY_CANTALAN + dirt_modifier = 0.2 + +/obj/item/gun/ballistic/automatic/pistol/cfa_snub/empty + spawnwithmagazine = FALSE + +/obj/item/gun/ballistic/automatic/pistol/cfa_ruby + name = "CFA Ruby" + desc = "A heavy-duty sidearm chambered in 12x27mm." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile.dmi' + icon_state = "cfa_ruby" + mag_type = /obj/item/ammo_box/magazine/multi_sprite/cfa_ruby + can_suppress = FALSE + fire_sound_volume = 120 + w_class = WEIGHT_CLASS_NORMAL + has_gun_safety = FALSE + company_flag = COMPANY_CANTALAN + dirt_modifier = 0.2 + +/obj/item/gun/ballistic/automatic/pistol/cfa_ruby/empty + spawnwithmagazine = FALSE + +//////////////////////// +// AMMO // +//////////////////////// +/obj/item/ammo_box/magazine/multi_sprite/cfa_snub + name = "CFA Snub magazine (4.2x30mm)" + desc = "An advanced magazine with smart type displays. Alt+click to reskin it." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi' + icon_state = "m42x30" + possible_types = list(AMMO_TYPE_LETHAL, AMMO_TYPE_AP, AMMO_TYPE_RUBBER, AMMO_TYPE_INCENDIARY) + ammo_type = /obj/item/ammo_casing/c42x30mm + caliber = CALIBER_42X30MM + max_ammo = 16 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/cfa_snub/ap + ammo_type = /obj/item/ammo_casing/c42x30mm/ap + round_type = AMMO_TYPE_AP + +/obj/item/ammo_box/magazine/multi_sprite/cfa_snub/rubber + ammo_type = /obj/item/ammo_casing/c42x30mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/ammo_box/magazine/multi_sprite/cfa_snub/incendiary + ammo_type = /obj/item/ammo_casing/c42x30mm/inc + round_type = AMMO_TYPE_INCENDIARY + +/obj/item/ammo_box/magazine/multi_sprite/cfa_snub/empty + start_empty = TRUE + +/obj/item/ammo_box/magazine/multi_sprite/cfa_ruby + name = "CFA Ruby magazine (12mm Magnum)" + desc = "An advanced magazine with smart type displays. Alt+click to reskin it." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi' + icon_state = "m12mm" + possible_types = list(AMMO_TYPE_LETHAL, AMMO_TYPE_AP, AMMO_TYPE_RUBBER, AMMO_TYPE_HOLLOWPOINT, AMMO_TYPE_INCENDIARY) + ammo_type = /obj/item/ammo_casing/c12mm + caliber = CALIBER_12MM + max_ammo = 8 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/empty + start_empty = TRUE + +/obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/ap + ammo_type = /obj/item/ammo_casing/c12mm/ap + round_type = AMMO_TYPE_AP + +/obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/rubber + ammo_type = /obj/item/ammo_casing/c12mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/hp + ammo_type = /obj/item/ammo_casing/c12mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/cfa_ruby/incendiary + ammo_type = /obj/item/ammo_casing/c12mm/fire + round_type = AMMO_TYPE_INCENDIARY diff --git a/modular_skyrat/modules/modular_weapons/code/revolver.dm b/modular_skyrat/modules/modular_weapons/code/revolver.dm new file mode 100644 index 000000000000..21515953d9b3 --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/revolver.dm @@ -0,0 +1,54 @@ +//////////////////////// +//ID: MODULAR_WEAPONS // +//////////////////////// + +/////////////// +// REVOLVERS // +/////////////// +// Revolving rifles! We have three versions. An improvised slower firing one, a normal one, and a golden premium one. +// The gold rifle uses .45, it's only 5 more points of damage unfortunately. Fun hint: A box of .45 bullets functions the same as a speedloader. +// + +/obj/item/gun/ballistic/revolver/rifle + name = "\improper .38 Revolving Rifle" + desc = "A revolving rifle chambered in .38. " + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile40x32.dmi' + icon_state = "revolving-rifle" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38 //This is just a detective's revolver but it's too big for bags.. + pixel_x = -4 // It's centred on a 40x32 pixel spritesheet. + w_class = WEIGHT_CLASS_BULKY + weapon_weight = WEAPON_HEAVY // The entire purpose of this is that it's a bulky rifle instead of a revolver. + slot_flags = ITEM_SLOT_BELT + inhand_x_dimension = 64 + inhand_y_dimension = 64 + lefthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_left.dmi' + righthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_right.dmi' + pixel_x = -8 + inhand_icon_state = "revolving" + company_flag = COMPANY_IZHEVSK + dirt_modifier = 0.75 + +/obj/item/gun/ballistic/revolver/rifle/improvised + name = "\improper Improvised .38 Revolving Rifle" + desc = "A crudely made revolving rifle. It fires .38 rounds. The cylinder doesn't rotate very well." + icon_state = "revolving-rifle" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38 //TAs far as improvised weapons go, this is fairly decent, this isn't half bad. + fire_delay = 15 + recoil = 1 + company_flag = null + +/obj/item/gun/ballistic/revolver/rifle/gold + name = "\improper .45 Revolving Rifle" + desc = "A gold trimmed revolving rifle! It fires .45 bullets." + icon_state = "revolving-rifle-gold" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev45 //Gold! We're using .45 because TG's 10mm does 40 damage, this does 30. + w_class = WEIGHT_CLASS_BULKY + inhand_icon_state = "revolving_gold" + +// .45 Cylinder + +/obj/item/ammo_box/magazine/internal/cylinder/rev45 + name = "revolver .45 cylinder" + ammo_type = /obj/item/ammo_casing/c45 + caliber = list(".45") + max_ammo = 6 diff --git a/modular_skyrat/modules/modular_weapons/code/rifle.dm b/modular_skyrat/modules/modular_weapons/code/rifle.dm new file mode 100644 index 000000000000..31713b3bba37 --- /dev/null +++ b/modular_skyrat/modules/modular_weapons/code/rifle.dm @@ -0,0 +1,163 @@ +//////////////////////// +//ID: MODULAR_WEAPONS // +//////////////////////// + +//////////////////////// +// IMPROVISED RIFLE // +//////////////////////// +// There was an improvised rifle on Cit/Skyrat, it's pretty cool so here it is too. +// We're using a slightly modified sprite designed around a Short Magazine Lee Enfield (SMLE) Mk.III +// + +/obj/item/ammo_box/magazine/internal/boltaction/improvised + max_ammo = 1 + multiload = 0 + +/obj/item/gun/ballistic/rifle/irifle + name = "improvised 7.62 rifle" + desc = "An improvised rifle that fires hard-hitting 7.62 bullets." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile40x32.dmi' + icon_state = "irifle" + inhand_icon_state = "irifle" + worn_icon_state = null + mag_type = /obj/item/ammo_box/magazine/internal/boltaction/improvised + inhand_x_dimension = 64 + inhand_y_dimension = 64 + lefthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_left.dmi' + righthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_right.dmi' + pixel_x = -8 + weapon_weight = WEAPON_HEAVY // It's big. + +//////////////////////// +// IMPROVISED SHOTGUN // +//////////////////////// +// We're using the rifle because we want the bolt action so we can pretend it's a break action gun. +// On Skyrat/Cit there was a need to tone improvised weapons down due to their incredible ease of access. +// This is the same nerf, but drastically more fun. We now need two hands to fire and we have a slightly slower action. + +/obj/item/gun/ballistic/rifle/ishotgun + name = "improvised shotgun" + desc = "A break-action 12 gauge shotgun. You need both hands to fire this." + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile40x32.dmi' + icon_state = "ishotgun" + inhand_x_dimension = 64 + inhand_y_dimension = 64 + lefthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_left.dmi' + righthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_right.dmi' + pixel_x = -8 + inhand_icon_state = "ishotgun" + w_class = WEIGHT_CLASS_BULKY + force = 10 + slot_flags = null + mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised + sawn_desc = "A break-action 12 gauge shotgun, but with most of the stock and some of the barrel removed. You still need both hands to fire this." + unique_reskin = null + var/slung = FALSE + weapon_weight = WEAPON_HEAVY // It's big. + recoil = 4 // We're firing 12 gauge. + can_be_sawn_off = TRUE + bolt_wording = "barrel" + +/obj/item/ammo_box/magazine/internal/shot/improvised + name = "improvised shotgun internal magazine" + ammo_type = /obj/item/ammo_casing/shotgun/improvised + max_ammo = 1 + +/obj/item/gun/ballistic/rifle/ishotgun/examine(mob/user) + . = ..() + . += "The barrel is [bolt_locked ? "broke open" : "closed"]." + +/obj/item/gun/ballistic/rifle/ishotgun/attackby(obj/item/A, mob/user, params) + ..() + if(istype(A, /obj/item/stack/cable_coil) && !sawn_off) + var/obj/item/stack/cable_coil/C = A + if(C.use(10)) + slot_flags = ITEM_SLOT_BACK + to_chat(user, span_notice("You tie the lengths of cable to the shotgun, making a sling.")) + slung = TRUE + update_icon() + else + to_chat(user, span_warning("You need at least ten lengths of cable if you want to make a sling!")) + +/obj/item/gun/ballistic/rifle/ishotgun/update_icon_state() + . = ..() + if(slung) + inhand_icon_state = "ishotgunsling" + if(sawn_off) + inhand_icon_state = "ishotgun_sawn" + +/obj/item/gun/ballistic/rifle/ishotgun/update_overlays() + . = ..() + if(slung) + . += "ishotgunsling" + if(sawn_off) + . += "ishotgun_sawn" + +/obj/item/gun/ballistic/rifle/ishotgun/sawoff(mob/user) + . = ..() + if(. && slung) //sawing off the gun removes the sling + new /obj/item/stack/cable_coil(get_turf(src), 10) + slung = 0 + update_icon() + lefthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_left.dmi' + righthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_right.dmi' + +/obj/item/gun/ballistic/rifle/ishotgun/sawn + name = "sawn-off improvised shotgun" + desc = "A break-action 12 gauge shotgun, but with most of the stock and some of the barrel removed. You still need both hands to fire this." + icon_state = "ishotgun_sawn" + inhand_icon_state = "ishotgun_sawn" + worn_icon_state = "gun" + worn_icon = null + w_class = WEIGHT_CLASS_NORMAL + sawn_off = TRUE + slot_flags = ITEM_SLOT_BELT + +//////////////////////// +// CFA RIFLE // +//////////////////////// + +/obj/item/gun/ballistic/automatic/cfa_rifle + name = "Cantanheim 6.8mm rifle" + desc = "A simple semi-automatic rifle chambered in 6.8mm. The letters 'XJP' are crossed out in the receiver." //Different 6.8mm than the FTU's propietary pulse ballistics + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/guns/projectile40x32.dmi' + icon_state = "cfa_rifle" + inhand_icon_state = "irifle" + inhand_x_dimension = 64 + inhand_y_dimension = 64 + lefthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_left.dmi' + righthand_file = 'modular_skyrat/modules/modular_weapons/icons/mob/inhands/weapons/64x_guns_right.dmi' + worn_icon_state = null + mag_type = /obj/item/ammo_box/magazine/cm68 + fire_delay = 5 + can_suppress = FALSE + burst_size = 0 + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + mag_display = FALSE + mag_display_ammo = FALSE + empty_indicator = FALSE + recoil = 1 + weapon_weight = WEAPON_HEAVY + pixel_x = -8 + zoomable = TRUE + zoom_amt = 4 + zoom_out_amt = 2 + has_gun_safety = FALSE + w_class = WEIGHT_CLASS_BULKY + company_flag = COMPANY_CANTALAN + dirt_modifier = 0.25 + +/obj/item/gun/ballistic/automatic/cfa_rifle/empty + spawnwithmagazine = FALSE + +/obj/item/ammo_box/magazine/cm68 + name = "rifle magazine (6.8mm)" + icon = 'modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi' + icon_state = "6.8" + ammo_type = /obj/item/ammo_casing/a68 + caliber = CALIBER_A68 + max_ammo = 10 + multiple_sprites = 2 + +/obj/item/ammo_box/magazine/cm762/empty + start_empty = 1 diff --git a/modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi b/modular_skyrat/modules/modular_weapons/icons/obj/ammo.dmi new file mode 100644 index 0000000000000000000000000000000000000000..9531519b341b49c5b819f6bcf552c2c160976b66 GIT binary patch literal 2182 zcmXw42{aUX7yl22iOh&BAwvk2HOp%=QxA>AHzHdYp}t5+V#t`WMfNRA_Ti;G&sx+G zGafaTL}Z(YAzSmZG&E)~^YNY6Ilps$zjN-n=iYPg{hj*=YjaUtR9+MSAa02w=ewVGaq+gWxT>vfk^>9~z`z?E!qo9i z;wkFaNPIruKgZi88mn|xb$%ZI;)O*{jsZUh+l4pC@m9+5KI>wjJw86(64aTYO%9MH z)YjH!XJ&<6ix!fEO+yt;W+*%8!zerTyJL$c?g0I-v0rdRX&0U=p zZtoOqcH^E`kWXN+Pk=uF_`=7zeg4ttgK?v)2hBz$p@x&eL${JG?+=OS#UvZtjf9=F zCu~Kdq+e>W|Di@KMCNwq$L&me8RM#>mx35X)}Uy43|o0$d|RkQelIikw;!#ANp8zJ zx+D5DCe6K22-h3d&o;27bK^5s?pQtDoa4wg`pRk;`quqbp+ZZxhjza^jXwCPr{tmdzroBCROB zT7^DdXh{z<)C^XoL(u125hikSDH9Jv0G1lcP=|I66s#(epNn=^d)_X%7flwwSQLEp zgq6DPqYgW};a(|5t8oG0CS0B#;pjtm{<22=Pd)Oz!w?IXfFxV|sj!g*Uj{%}*3#^} zJ-+aJQBruhu|(YY=VePz4e!uj+z)Ae?H91ZkDi+!tN)mc?)tCZLMQUIVzLoM{kocX zcaZt`%On6J{U6FOQg492e;W&Vi9JX5C`O5rT(xqR(jawOiAQvIbS0QX;)4eTe7#A2 zaA;^Q|F=P;I2CuGoFJeFFHNIPNoxZs;TS!Pe@onolpB*M@j(I>2T^gYMpqs%@ZhzA8vQpjaP!Y;RMwk zE#NoIzz`Klu3=G7?kw=`Ai6c6B&i#Z{%w3@KZ&fFNPcF~TR2r>YrL=$6EW)V%1=7O zo%;$q;>jM`*&*;6Dc}jex1-~C9y6HVOrz1Z+4~}8gIIyi>~dyV;XfLx?k7Mq!U3wB zmaijAVjkOWQ+jn-s5B-2iTq2%`sC74VbXKkEi@6wo;x}qXlQf{l{K}oRWmz%PV5%V zMA0L!){@vZX`wWKTome2pApY#_@o1H@s*tKmUUBai0q$Ho?;D$O6Ob3X$+brm`=fG z5);1MV1c^NT_S{L%E3+Sp%0MQ)a z27Vy&fml3@;zl-@OcN1$O?#Vx>Xk1Z7F^Z6;&KkW6mxoogn>zsSuS1`Dx{--K^A=P z&@i^!It^~{BG%fB8>{y|DN=rcB z4huyjtwrVz&QDwb6|efN(#Zw*uL3fvAdqPSQyzA{S+mU(gJAB%v8=6Ht{oZ^iP~07 zhohY$QA+44sAv>tM;NHNluG1HrMaUsBcr0pZ_=mAKAE~MLe+lF>@UYfPS`q&!D8J) znxfKvGRm*qLb?M5Q-5!z?+RgpV*)TR9}}=zTGNkt5jk5Iv$4+m)W{a93j&LcdUP7Q z{p>zTAOpf9mA-c@EPOPL*cE#l`SkYj@e8@SuYdVT4*d-(1X7^NqhgIF605h>NMld| z-*3}zjiBhxIyndioDDU~>kAl)wK-EpD7^|Jb=nE~+YybR>%m#)+ZO)VI&A!*NX^O` zr2Bci(!t@V3_Z`C_tFZE#s%e+!;o9ZtHXpCpve^o|3Y&@?MF99320`6N-hJW%6Eow zq&_G`LtYHysvzA9simMwrac_8`2pG}{7g`j4nzY;wry~aX;-`hFI!Bgr=ePG%r9$G zp5(jONOcBU3pB)~88&!`f^iJJNa4H)U-5QlX_86`2;}9q|8D(LUtVxJ&4p9KT-r0_xdbdaJs8giU&A7(PGn-k0*xAqlHY!O&ITZ4aNo?so0X%0!M))Bm z+29-OkIe#^(oN58aflZ0AxVbl3G$_8#a7>L-o_^Pnur#+ZtGVD2{XZXk3lsnV literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/sec_haul/code/guns/armory_spawns.dm b/modular_skyrat/modules/sec_haul/code/guns/armory_spawns.dm new file mode 100644 index 000000000000..6f78cf18e28c --- /dev/null +++ b/modular_skyrat/modules/sec_haul/code/guns/armory_spawns.dm @@ -0,0 +1,116 @@ +/obj/effect/spawner/armory_spawn + icon = 'modular_skyrat/modules/sec_haul/icons/guns/spawner.dmi' + icon_state = "random_gun" + layer = OBJ_LAYER + /// How many guns will be spawned here. + var/gun_count = 1 + /// If the same gun can be spawned twice. + var/gun_doubles = TRUE + /// A list of possible guns to spawn. + var/list/guns + /// Do we fan out the items spawned for a natural effect? + var/fan_out_items = TRUE + /// How many mags per gun do we spawn, if it takes magazines. + var/mags_to_spawn = 3 + /// Do we want to angle it so that it is horizontal? + var/vertical_guns = TRUE + + +/obj/effect/spawner/armory_spawn/Initialize(mapload) + ..() + if(guns) + var/current_offset = -10 + var/offset_percent = 20 / guns.len + for(var/gun in guns) // 11/20/21: Gun spawners now spawn 1 of each gun in it's list no matter what, so as to reduce the RNG of the armory stock. + var/obj/item/gun/spawned_gun = new gun(loc) + + if(vertical_guns) + spawned_gun.place_on_rack() + spawned_gun.pixel_x = current_offset + current_offset += offset_percent + + if(istype(spawned_gun, /obj/item/gun/ballistic)) + var/obj/item/gun/ballistic/spawned_ballistic_gun = spawned_gun + if(spawned_ballistic_gun.magazine && !istype(spawned_ballistic_gun.magazine, /obj/item/ammo_box/magazine/internal)) + var/obj/item/storage/box/ammo_box/spawned_box = new(loc) + spawned_box.name = "ammo box - [spawned_ballistic_gun.name]" + for(var/i in 1 to mags_to_spawn) + new spawned_ballistic_gun.mag_type (spawned_box) + + if(istype(spawned_gun, /obj/item/gun/microfusion)) + var/obj/item/gun/microfusion/spawned_microfusion_gun = spawned_gun + var/obj/item/storage/box/ammo_box/microfusion/spawned_box = new(loc) + for(var/i in 1 to mags_to_spawn) + new spawned_microfusion_gun.cell_type (spawned_box) + + return INITIALIZE_HINT_QDEL + +/obj/effect/spawner/armory_spawn/shotguns + icon_state = "random_shotgun" + gun_count = 4 + guns = list( + /obj/item/gun/ballistic/shotgun/riot, + /obj/item/gun/ballistic/shotgun/riot, + /obj/item/gun/ballistic/shotgun/riot, + /obj/item/gun/ballistic/shotgun/riot, + ) + +/obj/structure/closet/ammunitionlocker/useful/PopulateContents() + new /obj/item/storage/box/rubbershot(src) + new /obj/item/storage/box/rubbershot(src) + new /obj/item/storage/box/rubbershot(src) + new /obj/item/storage/box/rubbershot(src) + +//////////////////////////AMMO BOXES +/obj/item/storage/box/ammo_box + name = "ammo box" + desc = "A box filled with ammunition." + icon_state = "boxhrifle" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/ammoboxes.dmi' + illustration = null + layer = 2.9 + +/obj/item/storage/box/ammo_box/microfusion + name = "microfusion cell container" + desc = "A box filled with microfusion cells." + icon = 'modular_skyrat/modules/microfusion/icons/microfusion_cells.dmi' + icon_state = "microfusion_box" + +/obj/item/storage/box/ammo_box/microfusion/PopulateContents() + new /obj/item/storage/bag/ammo(src) + new /obj/item/stock_parts/cell/microfusion(src) + new /obj/item/stock_parts/cell/microfusion(src) + new /obj/item/stock_parts/cell/microfusion(src) + +/obj/item/storage/box/ammo_box/microfusion/bagless + +/obj/item/storage/box/ammo_box/microfusion/bagless/PopulateContents() + new /obj/item/stock_parts/cell/microfusion(src) + new /obj/item/stock_parts/cell/microfusion(src) + new /obj/item/stock_parts/cell/microfusion(src) + +/obj/effect/spawner/armory_spawn/centcom_rifles + icon_state = "random_rifle" + gun_count = 2 + guns = list( + /obj/item/gun/ballistic/automatic/ar, + /obj/item/gun/ballistic/automatic/m16, + /obj/item/gun/ballistic/automatic/cfa_rifle, + ) + +/obj/effect/spawner/armory_spawn/centcom_lasers + gun_count = 2 + guns = list( + /obj/item/gun/energy/laser, + /obj/item/gun/energy/laser/cfa_paladin, + /obj/item/gun/energy/e_gun, + ) + +/obj/effect/spawner/armory_spawn/cmg + icon_state = "random_rifle" + gun_count = 3 + guns = list( + /obj/item/gun/ballistic/automatic/cmg, + /obj/item/gun/ballistic/automatic/cmg, + /obj/item/gun/ballistic/automatic/cmg, + ) diff --git a/modular_skyrat/modules/sec_haul/code/guns/guns.dm b/modular_skyrat/modules/sec_haul/code/guns/guns.dm new file mode 100644 index 000000000000..7852d05f7837 --- /dev/null +++ b/modular_skyrat/modules/sec_haul/code/guns/guns.dm @@ -0,0 +1,811 @@ +/obj/item/gun/ballistic + var/emp_damageable = FALSE + +/obj/item/gun/ballistic/automatic/emp_act(severity) + . = ..() + if(emp_damageable) + jammed = TRUE + playsound(src, 'sound/effects/stall.ogg', 60, TRUE) + if(magazine) + eject_magazine() + +/obj/item/gun/ballistic/automatic/examine(mob/user) + . = ..() + if(!emp_damageable) + . += "It has an EMP prevention system." + +//////////////////GLOCK +/obj/item/gun/ballistic/automatic/pistol/g17 + name = "\improper GK-17" + desc = "A weapon from bygone times, this has been made to look like an old, blocky firearm from the 21st century. Let's hope it's more reliable. Chambered in 9mm." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/glock.dmi' + icon_state = "glock" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/g17 + can_suppress = FALSE + fire_sound = 'sound/weapons/gun/pistol/shot_alt.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + can_flashlight = TRUE + dirt_modifier = 1 + emp_damageable = TRUE + fire_delay = 1.90 + company_flag = COMPANY_CANTALAN + +/obj/item/ammo_box/magazine/multi_sprite/g17 + name = "9x19mm double stack magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "g17" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 17 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/g17/hp + ammo_type = /obj/item/ammo_casing/b9mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/g17/ihdf + ammo_type = /obj/item/ammo_casing/b9mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/g17/rubber + ammo_type = /obj/item/ammo_casing/b9mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/gun/ballistic/automatic/pistol/g18 + name = "\improper GK-18" + desc = "A CFA-made burst firing cheap polymer pistol chambered in 9mm. Its heavy duty barrel affects firerate." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/glock.dmi' + icon_state = "glock_spec" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/g18 + can_suppress = FALSE + fire_sound = 'sound/weapons/gun/pistol/shot_alt.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + burst_size = 3 + fire_delay = 2.10 + spread = 8 + mag_display = FALSE + mag_display_ammo = FALSE + can_flashlight = TRUE + company_flag = COMPANY_CANTALAN + dirt_modifier = 1 + +/obj/item/ammo_box/magazine/multi_sprite/g18 + name = "extended 9x19mm magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "g18" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 33 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/g18/hp + ammo_type = /obj/item/ammo_casing/b9mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/g18/ihdf + ammo_type = /obj/item/ammo_casing/b9mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/g18/rubber + ammo_type = /obj/item/ammo_casing/b9mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/gun/ballistic/automatic/pistol/g17/mesa + name = "\improper Glock-17" + desc = "A weapon from bygone times, and this is the exact 21st century version. In fact, even more reliable. Chambered in 9mm." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/glock.dmi' + icon_state = "glock_mesa" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/g17 + can_suppress = FALSE + fire_sound = 'modular_skyrat/master_files/sound/weapons/glock17_fire.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + realistic = TRUE + can_flashlight = TRUE + dirt_modifier = 0.2 + emp_damageable = FALSE + fire_delay = 0.9 + company_flag = null + +////////////////PDH 40x32 +/obj/item/gun/ballistic/automatic/pistol/pdh + name = "\improper PDH-6H 'Osprey'" + desc = "A modern ballistics sidearm, used primarily by the military, however this one has had a paintjob to match command. It's chambered in 12mm." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/pdh.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand40x32.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand40x32.dmi' + icon_state = "pdh" + inhand_icon_state = "pdh" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/pdh + can_suppress = FALSE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/hpistol_fire.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + realistic = TRUE + can_flashlight = TRUE + emp_damageable = TRUE + company_flag = COMPANY_ARMADYNE + +/obj/item/gun/ballistic/automatic/pistol/pdh/alt + name = "\improper PDH-6C 'SOCOM'" + desc = "A prestigious 12mm sidearm normally seen in the hands of SolFed special operation units due to its reliable and time-tested design. Now's one of those times that pays to be the strong, silent type." + icon_state = "pdh_alt" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/pdh + can_suppress = FALSE + fire_sound = 'sound/weapons/gun/pistol/shot_suppressed.ogg' + fire_delay = 8 + fire_sound_volume = 30 + spread = 1 + realistic = TRUE + dirt_modifier = 0.1 + can_flashlight = TRUE + emp_damageable = FALSE + +/obj/item/ammo_box/magazine/multi_sprite/pdh + name = "12.7x30mm pistol magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pdh" + ammo_type = /obj/item/ammo_casing/b12mm + caliber = CALIBER_12MM + max_ammo = 8 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + possible_types = list("lethal" = AMMO_TYPE_LETHAL, "hollowpoint" = AMMO_TYPE_HOLLOWPOINT, "rubber" = AMMO_TYPE_RUBBER) + +/obj/item/ammo_box/magazine/multi_sprite/pdh/hp + ammo_type = /obj/item/ammo_casing/b12mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/pdh/rubber + ammo_type = /obj/item/ammo_casing/b12mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/gun/ballistic/automatic/pistol/pdh/corpo + name = "\improper PDH-6M 'Corpo'" + desc = "A prestigious ballistic sidearm, from Armadyne's military division, normally given to corporate agents. It has a 3 round burst mode and uses .357 Magnum ammunition." + icon_state = "pdh_corpo" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/pdh_corpo + can_suppress = FALSE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/hpistol_fire.ogg' + burst_size = 3 + fire_delay = 2 + spread = 5 + realistic = TRUE + dirt_modifier = 0.1 + can_flashlight = TRUE + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/multi_sprite/pdh_corpo + name = ".357 pistol magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pdh" + ammo_type = /obj/item/ammo_casing/a357 + caliber = "357" + max_ammo = 14 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + possible_types = list("lethal" = AMMO_TYPE_LETHAL) + + +///////////////////////////PDH PEACEKEEPER +/obj/item/gun/ballistic/automatic/pistol/pdh/peacekeeper + name = "\improper PDH-6B" + desc = "A modern ballistic sidearm, used primarily by law enforcement." + fire_delay = 1.95 + icon_state = "pdh_peacekeeper" + mag_type = /obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper + fire_sound = 'modular_skyrat/modules/sec_haul/sound/pistol_fire.ogg' + realistic = TRUE + can_flashlight = TRUE + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper + name = "9x19mm polymer magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pdh" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 16 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper/hp + ammo_type = /obj/item/ammo_casing/b9mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper/ihdf + ammo_type = /obj/item/ammo_casing/b9mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper/rubber + ammo_type = /obj/item/ammo_casing/b9mm/rubber + round_type = AMMO_TYPE_RUBBER + +///////////////////////LADON 40x32 +/obj/item/gun/ballistic/automatic/pistol/ladon + name = "\improper Ladon pistol" + desc = "Modern handgun based off the PDH series, chambered in 10mm." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/ladon.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand40x32.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand40x32.dmi' + icon_state = "ladon" + inhand_icon_state = "ladon" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/ladon + can_suppress = FALSE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/pistol_fire.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + realistic = TRUE + can_flashlight = TRUE + dirt_modifier = 0.8 + emp_damageable = TRUE + fire_delay = 4.20 + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/multi_sprite/ladon + name = "10mm Auto pistol magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pdh" + ammo_type = /obj/item/ammo_casing/b10mm + caliber = CALIBER_10MMAUTO + max_ammo = 12 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/ladon/hp + ammo_type = /obj/item/ammo_casing/b10mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/ladon/ihdf + ammo_type = /obj/item/ammo_casing/b10mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/ladon/rubber + ammo_type = /obj/item/ammo_casing/b10mm/rubber + round_type = AMMO_TYPE_RUBBER + +/////////////////////MAKAROV +/obj/item/gun/ballistic/automatic/pistol/makarov + name = "\improper R-C 'Makarov'" + desc = "A mediocre pocket-sized handgun of seemingly Russian origin, chambered in 10mm." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/makarov.dmi' + icon_state = "makarov" + w_class = WEIGHT_CLASS_SMALL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/makarov + can_suppress = TRUE + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + dirt_modifier = 0.75 + emp_damageable = TRUE + company_flag = COMPANY_IZHEVSK + +/obj/item/ammo_box/magazine/multi_sprite/makarov + name = "small 10mm Auto pistol magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pdh" + ammo_type = /obj/item/ammo_casing/b10mm + caliber = CALIBER_10MMAUTO + max_ammo = 6 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/makarov/hp + ammo_type = /obj/item/ammo_casing/b10mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/makarov/ihdf + ammo_type = /obj/item/ammo_casing/b10mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/makarov/rubber + ammo_type = /obj/item/ammo_casing/b10mm/rubber + round_type = AMMO_TYPE_RUBBER + +////////////////////////////MK58 + +/obj/item/gun/ballistic/automatic/pistol/mk58 + name = "\improper MK-58" + desc = "A modern 9mm handgun with an olive polymer lower frame. Looks like a generic 21st century military sidearm." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mk58.dmi' + icon_state = "mk58" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/mk58 + can_suppress = FALSE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/pistol_fire.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + realistic = TRUE + dirt_modifier = 0.4 + emp_damageable = TRUE + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/multi_sprite/mk58 + name = "outdated 9x19mm magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "g17" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 12 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/mk58/hp + ammo_type = /obj/item/ammo_casing/b9mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/mk58/ihdf + ammo_type = /obj/item/ammo_casing/b9mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/mk58/rubber + ammo_type = /obj/item/ammo_casing/b9mm/rubber + round_type = AMMO_TYPE_RUBBER + +//////////////////////FIREFLY +/obj/item/gun/ballistic/automatic/pistol/firefly + name = "\improper P-92 'Firefly'" + desc = "A 9mm sidearm made by Armadyne's Medical Directive, with a heavy front for weak wrists. A small warning label on the back says it's not fit for surgical work." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/firefly.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + icon_state = "firefly" + inhand_icon_state = "firefly" + fire_delay = 1.95 + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/firefly + can_suppress = FALSE + realistic = TRUE + can_flashlight = TRUE + emp_damageable = TRUE + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/multi_sprite/firefly + name = "9x19mm special pistol magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "pdh" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 12 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/firefly/hp + ammo_type = /obj/item/ammo_casing/b9mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/firefly/rubber + ammo_type = /obj/item/ammo_casing/b9mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/ammo_box/magazine/multi_sprite/firefly/ihdf + ammo_type = /obj/item/ammo_casing/b9mm/ihdf + round_type = AMMO_TYPE_IHDF + +/////////////////////PCR + +/////////////////DTR + +/////////////////////CROON 40x32 +/obj/item/gun/ballistic/automatic/croon + name = "\improper DT-4 'Croon'" + desc = "A low-quality 6.3mm reproduction of a popular SMG model, jams like a bitch. Although crude and unofficial, it gets the job done." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/croon.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand40x32.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand40x32.dmi' + icon_state = "croon" + inhand_icon_state = "croon" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/croon + can_suppress = FALSE + fire_sound = 'sound/weapons/gun/smg/shot.ogg' + rack_sound = 'sound/weapons/gun/smg/smgrack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + burst_size = 3 + fire_delay = 2.10 + spread = 25 + mag_display = FALSE + mag_display_ammo = FALSE + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_BURST_SHOT) + realistic = TRUE + dirt_modifier = 1.7 //the croon is an EXTRA piece of shit + emp_damageable = TRUE + company_flag = COMPANY_IZHEVSK + +/obj/item/ammo_box/magazine/multi_sprite/croon + name = "6.3mm SMG magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "croon" + ammo_type = /obj/item/ammo_casing/b6mm + caliber = CALIBER_6MM + max_ammo = 15 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + possible_types = list(AMMO_TYPE_LETHAL, AMMO_TYPE_RUBBER, AMMO_TYPE_IHDF) + +/obj/item/ammo_box/magazine/multi_sprite/croon/rubber + ammo_type = /obj/item/ammo_casing/b6mm/rubber + round_type = AMMO_TYPE_RUBBER + +/obj/item/ammo_box/magazine/multi_sprite/croon/ihdf + ammo_type = /obj/item/ammo_casing/b6mm/ihdf + round_type = AMMO_TYPE_IHDF + +///////////////////////////Dozer +/obj/item/gun/ballistic/automatic/dozer + name = "\improper DZR-9 'Dozer'" + desc = "The DZR-9, a notorious 9mm PDW that lives up to its nickname." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/dozer.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + icon_state = "dozer" + inhand_icon_state = "dozer" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/multi_sprite/dozer + can_suppress = TRUE + mag_display = FALSE + mag_display_ammo = FALSE + burst_size = 2 + fire_delay = 1.90 + fire_select_modes = list(SELECT_SEMI_AUTOMATIC, SELECT_BURST_SHOT) + fire_sound = 'sound/weapons/gun/rifle/shot.ogg' + rack_sound = 'sound/weapons/gun/smg/smgrack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + realistic = TRUE + emp_damageable = TRUE + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/multi_sprite/dozer + name = "9x19mm small PDW magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "croon" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 8 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/dozer/hp + ammo_type = /obj/item/ammo_casing/b9mm/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/dozer/ihdf + ammo_type = /obj/item/ammo_casing/b9mm/ihdf + round_type = AMMO_TYPE_IHDF + +/obj/item/ammo_box/magazine/multi_sprite/dozer/rubber + ammo_type = /obj/item/ammo_casing/b9mm/rubber + round_type = AMMO_TYPE_RUBBER + +/////////////////DMR 40x32 +/obj/item/gun/ballistic/automatic/dmr + name = "\improper M557 'Ripper' Gen-2" + desc = "An incredibly powerful marksman rifle with an internal stabilization gymbal. It's chambered in .577 Snider." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/dmr.dmi' + icon_state = "dmr" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/dmr.dmi' + worn_icon_state = "dmr_worn" + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand40x32.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand40x32.dmi' + inhand_icon_state = "dmr" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_SUITSTORE + mag_type = /obj/item/ammo_box/magazine/dmr + fire_delay = 1.7 + can_suppress = FALSE + burst_size = 3 + can_bayonet = FALSE + mag_display = TRUE + realistic = TRUE + fire_sound_volume = 60 + fire_sound = 'modular_skyrat/modules/sec_haul/sound/sniper_fire.ogg' + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/dmr + name = ".557 DMR Magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "dmr" + ammo_type = /obj/item/ammo_casing/b577 + caliber = ".557 Snider" + max_ammo = 25 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/////////////////////////////////////////////ZETA +/obj/item/gun/ballistic/revolver/zeta + name = "\improper Zeta-6 'Spurchamber'" + desc = "A fairly common double-action six-shooter chambered for 10mm Auto." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/zeta.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + icon_state = "zeta" + inhand_icon_state = "zeta" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/zeta + fire_sound = 'modular_skyrat/modules/sec_haul/sound/revolver_fire.ogg' + fire_delay = 3 + company_flag = COMPANY_BOLT + +/obj/item/ammo_box/magazine/internal/cylinder/zeta + name = "10mm Auto revolver cylinder" + ammo_type = /obj/item/ammo_casing/b10mm + caliber = CALIBER_10MMAUTO + max_ammo = 6 + +/obj/item/ammo_box/revolver/zeta + name = "10mm Auto speedloader" + desc = "Designed to quickly reload the Zeta-6." + icon_state = "speedloader" + ammo_type = /obj/item/ammo_casing/b10mm + max_ammo = 6 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + caliber = CALIBER_10MMAUTO + start_empty = TRUE + +/obj/item/ammo_box/revolver/zeta/full + start_empty = FALSE + +/////////////////////////////////////////////////////////REVOLUTION +/obj/item/gun/ballistic/revolver/revolution + name = "\improper Revolution-8 'Spurmaster'" + desc = "The Zeta 6's distant cousin, sporting an eight-round competition grade cylinder chambered for 9mm Peacekeeper." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/revolution.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + icon_state = "revolution" + inhand_icon_state = "revolution" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/revolution + fire_sound = 'modular_skyrat/modules/sec_haul/sound/revolver_fire.ogg' + fire_delay = 1.90 + company_flag = COMPANY_BOLT + +/obj/item/ammo_box/magazine/internal/cylinder/revolution + name = "revolver cylinder" + ammo_type = /obj/item/ammo_casing/b9mm + caliber = CALIBER_9MM + max_ammo = 8 + +/obj/item/ammo_box/revolver/revolution + name = "9x19mm speedloader" + desc = "Designed to quickly reload revolvers." + icon_state = "speedloader" + ammo_type = /obj/item/ammo_casing/b9mm + max_ammo = 8 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + caliber = CALIBER_9MM + start_empty = TRUE + +/obj/item/ammo_box/revolver/revolution/full + start_empty = FALSE + +/////////////////SMARTGUN 40x32 +/obj/item/gun/ballistic/automatic/smartgun + name = "\improper OP-15 'S.M.A.R.T.' Rifle" + desc = "Suppressive Manual Action Reciprocating Taser rifle. A modified version of an Armadyne heavy machine gun fitted to fire miniature shock-bolts." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/smartgun.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand40x32.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand40x32.dmi' + icon_state = "smartgun" + w_class = WEIGHT_CLASS_HUGE + weapon_weight = WEAPON_HEAVY + slot_flags = ITEM_SLOT_BACK + inhand_icon_state = "smartgun_worn" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/smartgun.dmi' + worn_icon_state = "smartgun_worn" + mag_type = /obj/item/ammo_box/magazine/smartgun + actions_types = null + can_suppress = FALSE + can_bayonet = FALSE + mag_display = TRUE + mag_display_ammo = TRUE + empty_alarm = TRUE + tac_reloads = FALSE + bolt_type = BOLT_TYPE_STANDARD + semi_auto = FALSE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_fire.ogg' + rack_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_cock.ogg' + lock_back_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_open.ogg' + bolt_drop_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_cock.ogg' + load_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_magin.ogg' + load_empty_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_magin.ogg' + eject_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_magout.ogg' + load_empty_sound = 'modular_skyrat/modules/sec_haul/sound/chaingun_magout.ogg' + var/recharge_time = 5 SECONDS + var/recharging = FALSE + company_flag = COMPANY_ARMADYNE + +/obj/item/gun/ballistic/automatic/smartgun/process_chamber() + . = ..() + recharging = TRUE + addtimer(CALLBACK(src, .proc/recharge), recharge_time) + +/obj/item/gun/ballistic/automatic/smartgun/proc/recharge() + recharging = FALSE + playsound(src, 'sound/weapons/kenetic_reload.ogg', 60, 1) + +/obj/item/gun/ballistic/automatic/smartgun/can_shoot() + . = ..() + if(recharging) + return FALSE + +/obj/item/gun/ballistic/automatic/smartgun/update_icon() + . = ..() + if(!magazine) + icon_state = "smartgun_open" + else + icon_state = "smartgun_closed" + +/obj/item/ammo_box/magazine/smartgun + name = "rail rifle magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "smartgun" + ammo_type = /obj/item/ammo_casing/smartgun + caliber = "smartgun" + max_ammo = 5 + multiple_sprites = AMMO_BOX_PER_BULLET + +/obj/item/gun/ballistic/automatic/smartgun/nomag + spawnwithmagazine = FALSE + +/obj/structure/closet/secure_closet/smartgun + name = "smartgun locker" + req_access = list(ACCESS_ARMORY) + icon_state = "shotguncase" + +/obj/structure/closet/secure_closet/smartgun/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/smartgun/nomag(src) + new /obj/item/ammo_box/magazine/smartgun(src) + new /obj/item/ammo_box/magazine/smartgun(src) + new /obj/item/ammo_box/magazine/smartgun(src) + +////////////////////////////////////////////////////////// +/////////////////KRAUT SPACE MAGIC G11//////////////////// +////////////////////////////////////////////////////////// + +/obj/item/gun/ballistic/automatic/g11 + name = "\improper G11 K-490" + desc = "An outdated german caseless battle rifle that has been revised countless times during the late 2400s. Takes 4.73x33mm toploaded magazines." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/g11.dmi' + righthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/righthand.dmi' + lefthand_file = 'modular_skyrat/modules/sec_haul/icons/guns/inhands/lefthand.dmi' + icon_state = "g11" + inhand_icon_state = "g11" + worn_icon = 'modular_skyrat/modules/sec_haul/icons/guns/g11.dmi' + worn_icon_state = "g11_worn" + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_OCLOTHING + mag_type = /obj/item/ammo_box/magazine/multi_sprite/g11 + can_suppress = FALSE + burst_size = 3 + fire_delay = 0.5 + spread = 10 + mag_display = TRUE + mag_display_ammo = TRUE + realistic = TRUE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/ltrifle_fire.ogg' + emp_damageable = FALSE + can_bayonet = TRUE + can_flashlight = TRUE + dirt_modifier = 0.1 + company_flag = COMPANY_OLDARMS + +/obj/item/ammo_box/magazine/multi_sprite/g11 + name = "4.73x33mm top-loader magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "g11" + ammo_type = /obj/item/ammo_casing/caseless/b473 + caliber = CALIBER_473MM + max_ammo = 50 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_box/magazine/multi_sprite/g11/hp + ammo_type = /obj/item/ammo_casing/caseless/b473/hp + round_type = AMMO_TYPE_HOLLOWPOINT + +/obj/item/ammo_box/magazine/multi_sprite/g11/ihdf + ammo_type = /obj/item/ammo_casing/caseless/b473/ihdf + round_type = AMMO_TYPE_IHDF + +///////////////////////////////////////////////// +//////////////////SHOTGUNS/////////////////////// +///////////////////////////////////////////////// + +/obj/item/gun/ballistic/shotgun/m23 + name = "\improper Model 23-37" + desc = "An outdated police shotgun sporting an eight-round tube." + icon_state = "riotshotgun" + inhand_icon_state = "shotgun" + mag_type = /obj/item/ammo_box/magazine/internal/shot/m23 + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_OCLOTHING + company_flag = COMPANY_BOLT + +/obj/item/ammo_box/magazine/internal/shot/m23 + name = "m23 shotgun internal magazine" + caliber = CALIBER_SHOTGUN + ammo_type = /obj/item/ammo_casing/shotgun/beanbag + max_ammo = 8 + +/obj/item/gun/ballistic/shotgun/automatic/as2 + name = "\improper M2 Auto-Shotgun" + desc = "A semi-automatic shotgun with a four-round internal tube." + icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' + icon_state = "as2" + worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi' + lefthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/aesthetics/guns/icons/guns_righthand.dmi' + inhand_icon_state = "riot_shotgun" + inhand_x_dimension = 32 + inhand_y_dimension = 32 + can_suppress = TRUE + suppressed_sound = 'modular_skyrat/modules/aesthetics/guns/sound/suppressed_shotgun.ogg' + suppressed_volume = 100 + vary_fire_sound = TRUE + fire_sound = 'modular_skyrat/modules/aesthetics/guns/sound/shotgun_light.ogg' + fire_delay = 5 + mag_type = /obj/item/ammo_box/magazine/internal/shot/as2 + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_OCLOTHING + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/internal/shot/as2 + name = "shotgun internal magazine" + caliber = CALIBER_SHOTGUN + ammo_type = /obj/item/ammo_casing/shotgun + max_ammo = 4 + +/obj/item/gun/ballistic/shotgun/sas14 + name = "\improper SAS-14" + desc = "A semi-automatic shotgun with a five-round box magazine." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/sas14.dmi' + icon_state = "sas14" + inhand_icon_state = "shotgun" + worn_icon_state = "shotgun" + can_suppress = TRUE + suppressed_sound = 'modular_skyrat/modules/aesthetics/guns/sound/suppressed_shotgun.ogg' + suppressed_volume = 100 + vary_fire_sound = TRUE + fire_sound = 'modular_skyrat/modules/sec_haul/sound/shotgun_bm.ogg' + fire_delay = 5 + mag_type = /obj/item/ammo_box/magazine/sas14 + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_OCLOTHING + weapon_weight = WEAPON_MEDIUM + burst_size = 1 + fire_select_modes = list(SELECT_SEMI_AUTOMATIC) + semi_auto = TRUE + internal_magazine = FALSE + company_flag = COMPANY_ARMADYNE + +/obj/item/ammo_box/magazine/sas14 + name = "14 Gauge box magazine" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/mags.dmi' + icon_state = "sas14" + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + caliber = CALIBER_14GAUGE + ammo_type = /obj/item/ammo_casing/s14gauge + max_ammo = 5 + +//New SAS14 mags beyond here + +/obj/item/ammo_box/magazine/sas14/empty + start_empty = TRUE + +/obj/item/ammo_box/magazine/sas14/beanbag + ammo_type = /obj/item/ammo_casing/s14gauge/beanbag + +/obj/item/ammo_box/magazine/sas14/buckshot + ammo_type = /obj/item/ammo_casing/s14gauge/buckshot + +/obj/item/ammo_box/magazine/sas14/rubbershot + ammo_type = /obj/item/ammo_casing/s14gauge/rubbershot + +/obj/item/ammo_box/magazine/sas14/stunslug + ammo_type = /obj/item/ammo_casing/s14gauge/stunslug diff --git a/modular_skyrat/modules/sec_haul/code/guns/pepperball_gun.dm b/modular_skyrat/modules/sec_haul/code/guns/pepperball_gun.dm new file mode 100644 index 000000000000..8bd6cb8a4972 --- /dev/null +++ b/modular_skyrat/modules/sec_haul/code/guns/pepperball_gun.dm @@ -0,0 +1,74 @@ +/obj/item/gun/ballistic/automatic/pistol/pepperball + name = "\improper Bolt Pepperball AHG" + desc = "An incredibly mediocre 'firearm' designed to fire soft pepper balls meant to easily subdue targets." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/pepperball.dmi' + icon_state = "peppergun" + w_class = WEIGHT_CLASS_NORMAL + mag_type = /obj/item/ammo_box/magazine/pepperball + can_suppress = FALSE + fire_sound = 'sound/effects/pop_expl.ogg' + rack_sound = 'sound/weapons/gun/pistol/rack.ogg' + lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' + bolt_drop_sound = 'sound/weapons/gun/pistol/slide_drop.ogg' + realistic = TRUE + can_flashlight = TRUE + dirt_modifier = 2 + emp_damageable = TRUE + fire_sound_volume = 50 + company_flag = COMPANY_BOLT + +/obj/item/ammo_box/magazine/pepperball + name = "pistol magazine (pepperball)" + desc = "A gun magazine filled with balls." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/pepperball.dmi' + icon_state = "pepperball" + ammo_type = /obj/item/ammo_casing/pepperball + caliber = CALIBER_PEPPERBALL + max_ammo = 8 + multiple_sprites = AMMO_BOX_FULL_EMPTY_BASIC + +/obj/item/ammo_casing/pepperball + name = "pepperball" + desc = "A pepperball casing." + caliber = CALIBER_PEPPERBALL + projectile_type = /obj/projectile/bullet/pepperball + harmful = FALSE + +/obj/projectile/bullet/pepperball + name = "pepperball orb" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/projectiles.dmi' + icon_state = "pepperball" + damage = 0 + stamina = 5 + nodamage = TRUE + shrapnel_type = null + sharpness = NONE + embedding = null + impact_effect_type = /obj/effect/temp_visual/impact_effect + var/contained_reagent = /datum/reagent/consumable/condensedcapsaicin + var/reagent_volume = 5 + +/obj/projectile/bullet/pepperball/on_hit(atom/target, blocked, pierce_hit) + if(isliving(target)) + var/mob/living/M = target + if(M.can_inject()) + var/datum/reagent/R = new contained_reagent + R.expose_mob(M, VAPOR, reagent_volume) + . = ..() + +/datum/design/pepperballs + name = "Pepperball Ammo Box" + id = "pepperballs" + build_type = AUTOLATHE | PROTOLATHE + materials = list(/datum/material/iron = 5000) + build_path = /obj/item/ammo_box/advanced/pepperballs + category = list("intial", "Security", "Ammo") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + +/obj/item/ammo_box/advanced/pepperballs + name = "pepperball ammo box" + icon = 'modular_skyrat/modules/sec_haul/icons/guns/ammoboxes.dmi' + icon_state = "box10x24" + ammo_type = /obj/item/ammo_casing/pepperball + custom_materials = list(/datum/material/iron = 5000) + max_ammo = 15 diff --git a/modular_skyrat/modules/sec_haul/code/guns/token_system/gunsets.dm b/modular_skyrat/modules/sec_haul/code/guns/token_system/gunsets.dm new file mode 100644 index 000000000000..cdd1087297e6 --- /dev/null +++ b/modular_skyrat/modules/sec_haul/code/guns/token_system/gunsets.dm @@ -0,0 +1,379 @@ +/////////////// +//GUNSET BOXES +////////////// + +/obj/item/storage/box/gunset + name = "gun supply box" + desc = "An Armadyne weapons supply box." + icon = 'modular_skyrat/modules/sec_haul/icons/guns/gunsets.dmi' + icon_state = "box" + var/box_state = "box" + var/opened = FALSE + inhand_icon_state = "sec-case" + lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi' + resistance_flags = FLAMMABLE + w_class = WEIGHT_CLASS_BULKY + drop_sound = 'sound/items/handling/ammobox_drop.ogg' + pickup_sound = 'sound/items/handling/ammobox_pickup.ogg' + foldable = FALSE + illustration = null + +/obj/item/storage/box/gunset/PopulateContents() + . = ..() + new /obj/item/storage/bag/ammo(src) + new /obj/item/gun_maintenance_supplies(src) + +/obj/item/storage/box/gunset/update_icon() + . = ..() + if(opened) + icon_state = "[box_state]-open" + else + icon_state = box_state + +/obj/item/storage/box/gunset/AltClick(mob/user) + . = ..() + opened = !opened + update_icon() + + +/obj/item/storage/box/gunset/attack_self(mob/user) + . = ..() + opened = !opened + update_icon() + +/////////////////// +//GUN SETS +////////////////// + + +///////////////// +//SIDEARM TOKEN GUNSETS +//////////////// + +//G-17 +/obj/item/storage/box/gunset/glock17 + name = "GK-17 supply box" + +/obj/item/gun/ballistic/automatic/pistol/g17/nomag + spawnwithmagazine = FALSE + + +/obj/item/storage/box/gunset/glock17/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/g17/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/g17(src) + new /obj/item/ammo_box/magazine/multi_sprite/g17(src) + new /obj/item/ammo_box/magazine/multi_sprite/g17(src) + new /obj/item/ammo_box/magazine/multi_sprite/g17(src) + +//LADON +/obj/item/storage/box/gunset/ladon + name = "p-3 ladon supply box" + +/obj/item/gun/ballistic/automatic/pistol/ladon/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/ladon/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/ladon/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/ladon(src) + new /obj/item/ammo_box/magazine/multi_sprite/ladon(src) + new /obj/item/ammo_box/magazine/multi_sprite/ladon(src) + new /obj/item/ammo_box/magazine/multi_sprite/ladon(src) + +//DOZER +/obj/item/storage/box/gunset/dozer + name = "dozer supply box" + +/obj/item/gun/ballistic/automatic/dozer/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/dozer/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/dozer/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/dozer(src) + new /obj/item/ammo_box/magazine/multi_sprite/dozer(src) + new /obj/item/ammo_box/magazine/multi_sprite/dozer(src) + +//PDH +/obj/item/storage/box/gunset/pdh_peacekeeper + name = "9x19mm handgun supply box" + desc = "Ideally contains a fast-firing 9x19mm Pistol." + +/obj/item/gun/ballistic/automatic/pistol/pdh/peacekeeper/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/pdh_peacekeeper/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/pdh/peacekeeper/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_peacekeeper(src) + +// MK-58 +/obj/item/storage/box/gunset/mk58 + name = "mk-58 supply box" + +/obj/item/gun/ballistic/automatic/pistol/mk58/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/mk58/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/mk58/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/mk58(src) + new /obj/item/ammo_box/magazine/multi_sprite/mk58(src) + new /obj/item/ammo_box/magazine/multi_sprite/mk58(src) + new /obj/item/ammo_box/magazine/multi_sprite/mk58(src) + +//CROON +/obj/item/storage/box/gunset/croon + name = "weathered supply box" + desc = "Ideally contains a cheap 6mm SMG." + +/obj/item/gun/ballistic/automatic/croon/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/croon/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/croon/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/croon(src) + new /obj/item/ammo_box/magazine/multi_sprite/croon(src) + new /obj/item/ammo_box/magazine/multi_sprite/croon(src) + new /obj/item/ammo_box/magazine/multi_sprite/croon(src) + +//MAKAROV +/obj/item/storage/box/gunset/makarov + name = "makarov supply box" + + +/obj/item/ammo_box/magazine/multi_sprite/makarov/empty + start_empty = TRUE + +/obj/item/storage/box/gunset/makarov/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/makarov(src) + new /obj/item/ammo_box/magazine/multi_sprite/makarov(src) + new /obj/item/ammo_box/magazine/multi_sprite/makarov(src) + new /obj/item/ammo_box/magazine/multi_sprite/makarov(src) + new /obj/item/ammo_box/magazine/multi_sprite/makarov(src) + +//ZETA +/obj/item/storage/box/gunset/zeta + name = "10mm Auto revolver supply box" + desc = "Ideally contains a slow-firing revolver that packs a punch." + +/obj/item/storage/box/gunset/zeta/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/revolver/zeta(src) + new /obj/item/ammo_box/revolver/zeta(src) //These start empty. + new /obj/item/ammo_box/revolver/zeta(src) + new /obj/item/ammo_box/revolver/zeta(src) + new /obj/item/ammo_box/advanced/b10mm(src) + +//REVOLUTION +/obj/item/storage/box/gunset/revolution + name = "revolution supply box" + +/obj/item/storage/box/gunset/revolution/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/revolver/revolution(src) + new /obj/item/ammo_box/revolver/revolution(src) + new /obj/item/ammo_box/revolver/revolution(src) + new /obj/item/ammo_box/revolver/revolution(src) + new /obj/item/ammo_box/advanced/b9mm(src) + +///////////////// +//PRIMARY TOKEN GUNSETS +//////////////// + +///////PCR-9 +/obj/item/storage/box/gunset/pcr + name = "9mm SMG supply box" + desc = "Ideally contains a 9x19mm SMG with decent firerate." + +/obj/item/storage/box/gunset/pcr/PopulateContents() + . = ..() + new /obj/item/gun/energy/pcr(src) + +////M112 + +/obj/item/storage/box/gunset/norwind + name = "12.7x30mm DMR supply box." + desc = "Ideally contains an unwieldy rifle that hits like a truck." + +/obj/item/storage/box/gunset/norwind/PopulateContents() + . = ..() + new /obj/item/gun/energy/norwind(src) + +//////DTR-6 + +/obj/item/storage/box/gunset/ostwind + name = "6mm SPR box." + desc = "Ideally contains an all-around balanced special purpose rifle." + +/obj/item/storage/box/gunset/ostwind/PopulateContents() + . = ..() + new /obj/item/gun/energy/ostwind(src) +////////PITBULL + +/obj/item/storage/box/gunset/pitbull + name = "10mm PDW supply box" + desc = "Ideally contains a slow-firing 10mm Auto PDW that packs a punch." + +/obj/item/storage/box/gunset/pitbull/PopulateContents() + . = ..() + new /obj/item/gun/energy/pitbull(src) + +///////////////// +//JOB SPECIFIC GUNSETS +//////////////// + +//CAPTAIN +/obj/item/storage/box/gunset/pdh_captain + name = "pdh 'socom' supply box" + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/gun/ballistic/automatic/pistol/pdh/alt/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/pdh_captain/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/pdh/alt/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + +//HOS +/obj/item/storage/box/gunset/glock18_hos + name = "GK-18 supply box" + desc = "Ideally contains a fast-firing 9x19mm pistol made out of cheap plastic." + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/gun/ballistic/automatic/pistol/g18/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/glock18_hos/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/g18/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/g18(src) + new /obj/item/ammo_box/magazine/multi_sprite/g18(src) + new /obj/item/ammo_box/magazine/multi_sprite/g18(src) + new /obj/item/ammo_box/magazine/multi_sprite/g18/ihdf(src) + +//HOP +/obj/item/storage/box/gunset/pdh + name = "pdh 'osprey' supply box" + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/gun/ballistic/automatic/pistol/pdh/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/pdh/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/pdh/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh(src) + +//CORPO +/obj/item/storage/box/gunset/pdh_corpo + name = "pdh 'corporate' supply box" + w_class = WEIGHT_CLASS_NORMAL +/obj/item/gun/ballistic/automatic/pistol/pdh/corpo/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/pdh_corpo/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/pdh/corpo/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_corpo(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_corpo(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_corpo(src) + new /obj/item/ammo_box/magazine/multi_sprite/pdh_corpo(src) + +//////KRAUT SPACE MAGIC! +/obj/item/storage/box/gunset/g11 + name = "g11 supply box" + +/obj/item/gun/ballistic/automatic/g11/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/g11/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/g11/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/g11(src) + new /obj/item/ammo_box/magazine/multi_sprite/g11(src) + new /obj/item/ammo_box/magazine/multi_sprite/g11(src) + new /obj/item/ammo_box/magazine/multi_sprite/g11(src) + +//SECURITY MEDIC +/obj/item/storage/box/gunset/firefly + name = "9x19mm special pistol supply box" + desc = "Ideally contains a special 9x19mm Pistol." + w_class = WEIGHT_CLASS_NORMAL +/obj/item/gun/ballistic/automatic/pistol/firefly/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/firefly/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/firefly/nomag(src) + new /obj/item/ammo_box/magazine/multi_sprite/firefly(src) + new /obj/item/ammo_box/magazine/multi_sprite/firefly(src) + new /obj/item/ammo_box/magazine/multi_sprite/firefly(src) + new /obj/item/ammo_box/magazine/multi_sprite/firefly(src) + +//LASER +/obj/item/storage/box/gunset/laser + name = "laser gun supply box" + +/obj/item/storage/box/gunset/laser/PopulateContents() + . = ..() + new /obj/item/gun/energy/laser(src) + +/obj/item/storage/box/gunset/e_gun + +/obj/item/storage/box/gunset/e_gun/PopulateContents() + . = ..() + new /obj/item/gun/energy/e_gun(src) + +//PEPPERBALLS +/obj/item/storage/box/gunset/pepperball + name = "pepperball supply box" + w_class = WEIGHT_CLASS_NORMAL +/obj/item/gun/ballistic/automatic/pistol/pepperball/nomag + spawnwithmagazine = FALSE + +/obj/item/storage/box/gunset/pepperball/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/automatic/pistol/pepperball/nomag(src) + new /obj/item/ammo_box/magazine/pepperball(src) + new /obj/item/ammo_box/magazine/pepperball(src) + new /obj/item/ammo_box/magazine/pepperball(src) + new /obj/item/ammo_box/magazine/pepperball(src) + + +///////////////// +//SHOTGUN GUNSETS +//////////////// +/obj/item/storage/box/gunset/m23 + name = "m23 supply box" + +/obj/item/storage/box/gunset/m23/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/shotgun/m23(src) + new /obj/item/storage/box/beanbag(src) + new /obj/item/storage/box/beanbag(src) + new /obj/item/storage/box/beanbag(src) + +/obj/item/storage/box/gunset/as2 + name = "as2 supply box" + +/obj/item/storage/box/gunset/as2/PopulateContents() + . = ..() + new /obj/item/gun/ballistic/shotgun/automatic/as2(src) + new /obj/item/storage/box/beanbag(src) + new /obj/item/storage/box/beanbag(src) + new /obj/item/storage/box/beanbag(src) diff --git a/modular_skyrat/modules/sec_haul/code/misc/packs.dm b/modular_skyrat/modules/sec_haul/code/misc/packs.dm new file mode 100644 index 000000000000..20532c63d3d3 --- /dev/null +++ b/modular_skyrat/modules/sec_haul/code/misc/packs.dm @@ -0,0 +1,17 @@ +/datum/supply_pack/vending/sectech + name = "Peacekeeper Equipment Supply Crate" + desc = "Armadyne branded Peacekeeper supply crate, filled with things you need to restock the equipment vendor." + cost = CARGO_CRATE_VALUE * 3 + access = ACCESS_SECURITY + contains = list(/obj/item/vending_refill/security_peacekeeper) + crate_name = "Peacekeeper equipment supply crate" + crate_type = /obj/structure/closet/crate/secure/gear + +/datum/supply_pack/vending/wardrobes/security + name = "Peacekeeper Wardrobe Supply Crate" + desc = "This crate contains refills for the Peacekeeper Outfitting Station and LawDrobe." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/vending_refill/wardrobe/peacekeeper_wardrobe, + /obj/item/vending_refill/wardrobe/law_wardrobe) + crate_name = "security department supply crate" + diff --git a/monkestation/code/modules/microfusion/code/cargo_stuff.dm b/monkestation/code/modules/microfusion/code/cargo_stuff.dm index f4d49054a98b..85fc96a0895e 100644 --- a/monkestation/code/modules/microfusion/code/cargo_stuff.dm +++ b/monkestation/code/modules/microfusion/code/cargo_stuff.dm @@ -34,7 +34,7 @@ ) crate_name = "Microfusion Cell Crate" -/datum/supply_pack/security/mcr01_attachments_A +/datum/supply_pack/security/mcr01_attachments_a name = "MCR-01 Military Attachments Crate Type A" desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments! This crate comes with two utilitarian repeater loadout." cost = CARGO_CRATE_VALUE * 14 @@ -52,7 +52,7 @@ ) crate_name = "MCR-01 Military Attachments Crate Type A" -/datum/supply_pack/security/mcr01_attachments_type_B +/datum/supply_pack/security/mcr01_attachments_type_b name = "MCR-01 Military Attachments Crate Type B" desc = "Micron Control Systems Incorporated supplied MCR-01 Military spec attachments! This crate comes in a mixed specialist loadout." cost = CARGO_CRATE_VALUE * 16 @@ -69,7 +69,7 @@ crate_name = "MCR-01 Military Attachments Crate Type B" -/datum/supply_pack/security/mcr01_attachments_H +/datum/supply_pack/security/mcr01_attachments_h name = "HCR-01 Military Attachments Crate Type H" desc = "Honkicron Clownery Systems Inhonkorated supplied HCR-01 Clownery spec attachments! This crate oddly smells of bananas." cost = CARGO_CRATE_VALUE * 20 @@ -86,4 +86,3 @@ /obj/item/food/pie/cream, ) crate_name = "MCR-01 Military Attachments Crate Type H" - diff --git a/monkestation/code/modules/microfusion/code/gun_types.dm b/monkestation/code/modules/microfusion/code/gun_types.dm index bc59c449176b..b65a84bf4616 100644 --- a/monkestation/code/modules/microfusion/code/gun_types.dm +++ b/monkestation/code/modules/microfusion/code/gun_types.dm @@ -1,9 +1,10 @@ /obj/item/gun/microfusion/mcr01 name = "MCR-01" - desc = "An advanced, modular energy weapon produced by Allstar Lasers Incorporated. These cutting edge weapons differ from traditional beam weaponry in producing individual bolts, as well as utilizing hotswapped cells rather than being tied to immobile power sources." + desc = "An advanced, modular energy weapon produced by Micron Control Systems. These cutting edge weapons differ from traditional beam weaponry in producing individual bolts, as well as utilizing hotswapped cells rather than being tied to immobile power sources." icon_state = "mcr01" inhand_icon_state = "mcr01" shaded_charge = TRUE + company_flag = COMPANY_MICRON /// Gun for cargo crates. /obj/item/gun/microfusion/mcr01/advanced @@ -49,6 +50,13 @@ new /obj/item/stock_parts/cell/microfusion/advanced(src) new /obj/item/stock_parts/cell/microfusion/advanced(src) +/obj/item/storage/box/ammo_box/microfusion/advanced/bagless + +/obj/item/storage/box/ammo_box/microfusion/advanced/bagless/PopulateContents() + new /obj/item/stock_parts/cell/microfusion/advanced(src) + new /obj/item/stock_parts/cell/microfusion/advanced(src) + new /obj/item/stock_parts/cell/microfusion/advanced(src) + //////////////MICROFUSION SPAWNERS /obj/effect/spawner/armory_spawn/microfusion icon_state = "random_rifle" diff --git a/tgui/packages/tgui-panel/styles/goon/chat-dark.scss b/tgui/packages/tgui-panel/styles/goon/chat-dark.scss new file mode 100644 index 000000000000..9fbd3db9877a --- /dev/null +++ b/tgui/packages/tgui-panel/styles/goon/chat-dark.scss @@ -0,0 +1,1043 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +em { + font-style: normal; + font-weight: bold; +} + +img { + margin: 0; + padding: 0; + line-height: 1; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; +} + +img.icon { + height: 1em; + min-height: 16px; + width: auto; + vertical-align: bottom; +} + +a { + color: #397ea5; +} + +a.visited { + color: #7c00e6; +} + +a:visited { + color: #7c00e6; +} + +a.popt { + text-decoration: none; +} + +/* POPUPS */ + +.popup { + position: fixed; + top: 50%; + left: 50%; + background: #ddd; +} + +.popup .close { + position: absolute; + background: #aaa; + top: 0; + right: 0; + color: #333; + text-decoration: none; + z-index: 2; + padding: 0 10px; + height: 30px; + line-height: 30px; +} + +.popup .close:hover { + background: #999; +} + +.popup .head { + background: #999; + color: #ddd; + padding: 0 10px; + height: 30px; + line-height: 30px; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; + border-bottom: 2px solid green; +} + +.popup input { + border: 1px solid #999; + background: #fff; + margin: 0; + padding: 5px; + outline: none; + color: #333; +} + +.popup input[type=text]:hover, +.popup input[type=text]:active, +.popup input[type=text]:focus { + border-color: green; +} + +.popup input[type=submit] { + padding: 5px 10px; + background: #999; + color: #ddd; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; +} + +.popup input[type=submit]:hover, +.popup input[type=submit]:focus, +.popup input[type=submit]:active { + background: #aaa; + cursor: pointer; +} + +.changeFont { + padding: 10px; +} + +.changeFont a { + display: block; + text-decoration: none; + padding: 3px; + color: #333; +} + +.changeFont a:hover { + background: #ccc; +} + +.highlightPopup { + padding: 10px; + text-align: center; +} + +.highlightPopup input[type=text] { + display: block; + width: 215px; + text-align: left; + margin-top: 5px; +} + +.highlightPopup input.highlightColor { + background-color: #FFFF00; +} + +.highlightPopup input.highlightTermSubmit { + margin-top: 5px; +} + + + +/* ADMIN CONTEXT MENU */ + + +.contextMenu { + background-color: #ddd; + position: fixed; + margin: 2px; + width: 150px; +} + +.contextMenu a { + display: block; + padding: 2px 5px; + text-decoration: none; + color: #333; +} + +.contextMenu a:hover { + background-color: #ccc; +} + + + +/* ADMIN FILTER MESSAGES MENU */ + + +.filterMessages { + padding: 5px; +} + +.filterMessages div { + padding: 2px 0; +} + +.filterMessages input { +} + +.filterMessages label { +} + +.icon-stack { + height: 1em; + line-height: 1em; + width: 1em; + vertical-align: middle; + margin-top: -2px; +} + + + + +/***************************************** +* +* OUTPUT ACTUALLY RELATED TO MESSAGES +* +******************************************/ + + + + + +/* MOTD */ + + +.motd { + color: #a4bad6; + font-family: Verdana, sans-serif; + white-space: normal; +} + +.motd h1, +.motd h2, +.motd h3, +.motd h4, +.motd h5, +.motd h6 { + color: #a4bad6; + text-decoration: underline; +} + +.motd a, +.motd a:link, +.motd a:visited, +.motd a:active, +.motd a:hover { + color: #a4bad6; +} + + + +/* ADD HERE FOR BOLD */ + + +.bold, +.name, +.prefix, +.ooc, +.looc, +.adminooc, +.admin, +.medal, +.yell { + font-weight: bold; +} + + + +/* ADD HERE FOR ITALIC */ + + +.italic, .italics { + font-style: italic; +} + + + +/* OUTPUT COLORS */ + + +.highlight { + background: yellow; +} + +h1, h2, h3, h4, h5, h6 { + color: #a4bad6; + font-family: Georgia, Verdana, sans-serif; +} + +h1.alert, h2.alert { + color: #a4bad6; +} + +em { + font-style: normal; + font-weight: bold; +} + +.ooc { + color: #cca300; + font-weight: bold; +} + +.adminobserverooc { + color: #0099cc; + font-weight: bold; +} + +.adminooc { + color: #3d5bc3; + font-weight: bold; +} + +.adminsay { + color: #ff4500; + font-weight: bold; +} + +.admin { + color: #5975da; + font-weight: bold; +} + +.name { + font-weight: bold; +} + +.say, .emote, .infoplain, .oocplain, .warningplain, .mentor { +} + +.deadsay { + color: #e2c1ff; +} + +.binarysay { + color: #1e90ff; +} + +.binarysay a { + color: #00ff00; +} + +.binarysay a:active, .binarysay a:visited { + color: #88ff88; +} + +/* RADIO COLORS */ +/* IF YOU CHANGE THIS KEEP IT IN SYNC WITH TGUI CONSTANTS */ + +.radio { + color: #1ecc43; +} + +.sciradio { + color: #c68cfa; +} + +.comradio { + color: #fcdf03; +} + +.secradio { + color: #dd3535; +} + +.medradio { + color: #57b8f0; +} + +.engradio { + color: #f37746; +} + +.suppradio { + color: #b88646; +} + +.servradio { + color: #6ca729; +} + +.syndradio { + color: #8f4a4b; +} + +.gangradio { + color: #ac2ea1; +} + +.centcomradio { + color: #2681a5; +} + +.aiprivradio { + color: #d65d95; +} + +.redteamradio { + color: #ff4444; +} + +.blueteamradio { + color: #3434fd; +} + +.greenteamradio { + color: #34fd34; +} + +.yellowteamradio { + color: #fdfd34; +} + +.yell { + font-weight: bold; +} + +.alert { + color: #d82020; +} + +.userdanger { + color: #c51e1e; + font-weight: bold; + font-size: 185%; +} + +.bolddanger { + color: #c51e1e; + font-weight: bold; +} + +.danger { + color: #c51e1e; +} + +.warning { + color: #c51e1e; + font-style: italic; +} + +.alertwarning { + color: #FF0000; + font-weight: bold; +} + +.boldwarning { + color: #c51e1e; + font-style: italic; + font-weight: bold; +} + +.announce { + color: #c51e1e; + font-weight: bold; +} + +.boldannounce { + color: #c51e1e; + font-weight: bold; +} + +.minorannounce { + font-weight: bold; + font-size: 185%; +} + +.greenannounce { + color: #059223; + font-weight: bold; +} + +.rose { + color: #ff5050; +} + +.info { + color: #9ab0ff; +} + +.notice { + color: #6685f5; +} + +.tinynotice { + color: #6685f5; + font-size: 85%; +} + +.tinynoticeital { + color: #6685f5; + font-style: italic; + font-size: 85%; +} + +.smallnotice { + color: #6685f5; + font-size: 90%; +} + +.smallnoticeital { + color: #6685f5; + font-style: italic; + font-size: 90%; +} + +.boldnotice { + color: #6685f5; + font-weight: bold; +} + +.hear { + color: #6685f5; + font-style: italic; +} + +.adminnotice { + color: #6685f5; +} + +.adminhelp { + color: #ff0000; + font-weight: bold; +} + +.unconscious { + color: #a4bad6; + font-weight: bold; +} + +.suicide { + color: #ff5050; + font-style: italic; +} + +.green { + color: #059223; +} + +.grey { + color: #838383; +} + +.red { + color: #FF0000; +} + +.blue { + color: #215cff; +} + +.nicegreen { + color: #059223; +} + +.boldnicegreen { + color: #059223; + font-weight: bold; +} + +.cult { + color: #973e3b; +} + +.cultitalic { + color: #973e3b; + font-style: italic; +} + +.cultbold { + color: #973e3b; + font-style: italic; + font-weight: bold; +} + +.cultboldtalic { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.cultlarge { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.narsie { + color: #973e3b; + font-weight: bold; + font-size: 925%; +} + +.narsiesmall { + color: #973e3b; + font-weight: bold; + font-size: 370%; +} + +.colossus { + color: #7F282A; + font-size: 310%; +} + +.hierophant { + color: #b441ee; + font-weight: bold; + font-style: italic; +} + +.hierophant_warning { + color: #c56bf1; + font-style: italic; +} + +.purple { + color: #9956d3; +} + +.holoparasite { + color: #88809c; +} + +.revennotice { + color: #c099e2; +} + +.revenboldnotice { + color: #c099e2; + font-weight: bold; +} + +.revenbignotice { + color: #c099e2; + font-weight: bold; + font-size: 185%; +} + +.revenminor { + color: #823abb; +} + +.revenwarning { + color: #760fbb; + font-style: italic; +} + +.revendanger { + color: #760fbb; + font-weight: bold; + font-size: 185%; +} + +.deconversion_message { + color: #a947ff; + font-size: 185%; + font-style: italic; +} + +.ghostalert { + color: #6600ff; + font-style: italic; + font-weight: bold; +} + +.alien { + color: #855d85; +} + +.noticealien { + color: #059223; +} + +.alertalien { + color: #059223; + font-weight: bold; +} + +.changeling { + color: #059223; + font-style: italic; +} + +.alertsyndie { + color: #FF0000; + font-size: 185%; + font-weight: bold; +} + +.spider { + color: #8800ff; + font-weight: bold; + font-size: 185%; +} + +.interface { + color: #750e75; +} + +.sans { + font-family: "Comic Sans MS", cursive, sans-serif; +} + +.papyrus { + font-family: "Papyrus", cursive, sans-serif; +} + +.robot { + font-family: "Courier New", cursive, sans-serif; +} + +.tape_recorder { + color: #FF0000; + font-family: "Courier New", cursive, sans-serif; +} + +.command_headset { + font-weight: bold; + font-size: 160%; +} + +.small { + font-size: 60%; +} + +.big { + font-size: 185%; +} + +.reallybig { + font-size: 245%; +} + +.extremelybig { + font-size: 310%; +} + +.greentext { + color: #059223; + font-size: 185%; +} + +.redtext { + color: #c51e1e; + font-size: 185%; +} + +.clown { + color: #ff70c1; + font-size: 160%; + font-family: "Comic Sans MS", cursive, sans-serif; + font-weight: bold; +} + +.singing { + font-family: "Trebuchet MS", cursive, sans-serif; + font-style: italic; +} + +.his_grace { + color: #15D512; + font-family: "Courier New", cursive, sans-serif; + font-style: italic; +} + +.hypnophrase { + color: #202020; + font-weight: bold; + animation: hypnocolor 1500ms infinite; + animation-direction: alternate; +} + +@keyframes hypnocolor { + 0% { + color: #202020; + } + + 25% { + color: #4b02ac; + } + + 50% { + color: #9f41f1; + } + + 75% { + color: #541c9c; + } + + 100% { + color: #7adbf3; + } +} + +// SKYRAT ADDITION BEGIN +.velvet { + color: #660015; + font-weight: bold; + animation: velvet 5000ms infinite; +} +@keyframes velvet { + 0% { + color: #400020; + } + 40% { + color: #ff0000; + } + 50% { + color: #ff8888; + } + 60% { + color: #ff0000; + } + 100% { + color: #400020; + } +} + +.hexnut { + color: #0099ff; + font-weight: bold; + animation: hexnut 5000ms infinite; + animation-direction: alternate; +} + +@keyframes hexnut { + 0% { + color: #0099ff; + } + 35% { + color: #a64dff; + } + 50% { + color: #00997a; + } + 60% { + color: #ffb31a; + } + 100% { + color: #ff33cc; + } +} + +.doyourjobidiot { + color: #c51e1e; + text-shadow: 0 0 4px #e22525; + font-size: 125%; + font-weight: bold; + animation: flashingfuckingwarning 250ms infinite; +} + +@keyframes flashingfuckingwarning { + 0% { + color: #c51e1e; + text-shadow: 0 0 4px #c51e1e; + } + + 50% { + color: #e22525; + text-shadow: 0 0 8px #e22525; + } + + 100% { + color: #c51e1e; + text-shadow: 0 0 4px #c51e1e; + } +} +// SKYRAT ADDITION END + +.phobia { + color: #dd0000; + font-weight: bold; + animation: phobia 750ms infinite; +} + +@keyframes phobia { + 0% { + color: #f75a5a; + } + + 50% { + color: #dd0000; + } + + 100% { + color: #f75a5a; + } +} + +.icon { + height: 1em; + width: auto; +} + +.bigicon { + font-size: 2.5em; +} + +.memo { + color: #638500; + text-align: center; +} + +.memoedit { + text-align: center; + font-size: 125%; +} + +.abductor { + color: #c204c2; + font-style: italic; +} + +.mind_control { + color: #df3da9; + font-size: 100%; + font-weight: bold; + font-style: italic; +} + +.slime { + color: #00CED1; +} + +.drone { + color: #848482; +} + +.monkey { + color: #975032; +} + +.swarmer { + color: #2C75FF; +} + +.resonate { + color: #298F85; +} + +.monkeyhive { + color: #a56408; +} + +.monkeylead { + color: #af6805; + font-size: 80%; +} + +.connectionClosed, .fatalError { + background: red; + color: white; + padding: 5px; +} + +.connectionClosed.restored { + background: green; +} + +.internal.boldnshit { + color: #3d5bc3; + font-weight: bold; +} + + + +/* HELPER CLASSES */ + + +.text-normal { + font-weight: normal; + font-style: normal; +} + +.hidden { + display: none; + visibility: hidden; +} + +.ml-1 { + margin-left: 1em; +} + +.ml-2 { + margin-left: 2em; +} + +.ml-3 { + margin-left: 3em; +} + +.tooltip { + font-style: italic; + border-bottom: 1px dashed #fff; +} + +/* SKYRAT DARK MODE CLASSES */ +.mentor {color: #8a2be2;} +.looc {color: #d8b555;} +.rlooc {color: #b09448;} + +.examine_block { + background: rgba(0, 0, 0, 0.2); + border: 1px solid rgba(55, 55, 55, 0.33); + margin: 7px 4px; + padding: 8px 12px; + max-width: 550px; +} + +.examine_block hr { + border: none; + background: #222; + height: 1px; + margin: 8px 16px 8px 16px; +} + +.userlove { + color: #FF1493; + font-style: italic; + font-weight: bold; + text-shadow: 0 0 6px #ff6dbc; +} + +.crossooc { + color: #9f6efc; + font-weight: bold; +} + +.crossasay { + color: #ff0000; + font-weight: bold; +} + +.pink { + color: #ff00ff; + font-weight: bold; +} + +.brown { + color: #3d2009; + font-weight: bold; +} + +.orange { + color: #b8761a; + font-weight: bold; +} + +.yellow { + color: #c7b72c; + font-weight: bold; +} + +.cyan { + color: #0ea1e6; + font-weight: bold; +} diff --git a/tgui/packages/tgui-panel/styles/goon/chat-light.scss b/tgui/packages/tgui-panel/styles/goon/chat-light.scss new file mode 100644 index 000000000000..20ed07138ce8 --- /dev/null +++ b/tgui/packages/tgui-panel/styles/goon/chat-light.scss @@ -0,0 +1,994 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +html, body { + padding: 0; + margin: 0; + height: 100%; + color: #000000; +} + +body { + background: #fff; + font-family: Verdana, sans-serif; + font-size: 13px; + line-height: 1.2; + overflow-x: hidden; + overflow-y: scroll; + word-wrap: break-word; +} + +em { + font-style: normal; + font-weight: bold; +} + +img { + margin: 0; + padding: 0; + line-height: 1; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; +} + +img.icon { + height: 1em; + min-height: 16px; + width: auto; + vertical-align: bottom; +} + +a { + color: #0000ff; +} + +a.visited { + color: #ff00ff; +} + +a:visited { + color: #ff00ff; +} + +a.popt { + text-decoration: none; +} + +/* POPUPS */ + +.popup { + position: fixed; + top: 50%; + left: 50%; + background: #ddd; +} + +.popup .close { + position: absolute; + background: #aaa; + top: 0; + right: 0; + color: #333; + text-decoration: none; + z-index: 2; + padding: 0 10px; + height: 30px; + line-height: 30px; +} + +.popup .close:hover { + background: #999; +} + +.popup .head { + background: #999; + color: #ddd; + padding: 0 10px; + height: 30px; + line-height: 30px; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; + border-bottom: 2px solid green; +} + +.popup input { + border: 1px solid #999; + background: #fff; + margin: 0; + padding: 5px; + outline: none; + color: #333; +} + +.popup input[type=text]:hover, +.popup input[type=text]:active, +.popup input[type=text]:focus { + border-color: green; +} + +.popup input[type=submit] { + padding: 5px 10px; + background: #999; + color: #ddd; + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; +} + +.popup input[type=submit]:hover, +.popup input[type=submit]:focus, +.popup input[type=submit]:active { + background: #aaa; + cursor: pointer; +} + +.changeFont { + padding: 10px; +} + +.changeFont a { + display: block; + text-decoration: none; + padding: 3px; + color: #333; +} + +.changeFont a:hover { + background: #ccc; +} + +.highlightPopup { + padding: 10px; + text-align: center; +} + +.highlightPopup input[type=text] { + display: block; + width: 215px; + text-align: left; + margin-top: 5px; +} + +.highlightPopup input.highlightColor { + background-color: #FFFF00; +} + +.highlightPopup input.highlightTermSubmit { + margin-top: 5px; +} + + + +/* ADMIN CONTEXT MENU */ + + +.contextMenu { + background-color: #ddd; + position: fixed; + margin: 2px; + width: 150px; +} + +.contextMenu a { + display: block; + padding: 2px 5px; + text-decoration: none; + color: #333; +} + +.contextMenu a:hover { + background-color: #ccc; +} + + + +/* ADMIN FILTER MESSAGES MENU */ + + +.filterMessages { + padding: 5px; +} + +.filterMessages div { + padding: 2px 0; +} + +.filterMessages input { +} + +.filterMessages label { +} + +.icon-stack { + height: 1em; + line-height: 1em; + width: 1em; + vertical-align: middle; + margin-top: -2px; +} + + + + +/***************************************** +* +* OUTPUT ACTUALLY RELATED TO MESSAGES +* +******************************************/ + + + + + +/* MOTD */ + + +.motd { + color: #638500; + font-family: Verdana, sans-serif; + white-space: normal; +} + +.motd h1, +.motd h2, +.motd h3, +.motd h4, +.motd h5, +.motd h6 { + color: #638500; + text-decoration: underline; +} + +.motd a, +.motd a:link, +.motd a:visited, +.motd a:active, +.motd a:hover { + color: #638500; +} + + + +/* ADD HERE FOR BOLD */ + + +.bold, +.name, +.prefix, +.ooc, +.looc, +.adminooc, +.admin, +.medal, +.yell { + font-weight: bold; +} + + + +/* ADD HERE FOR ITALIC */ + + +.italic, +.italics { + font-style: italic; +} + + + +/* OUTPUT COLORS */ + + +.highlight { + background: yellow; +} + +h1, h2, h3, h4, h5, h6 { + color: #0000ff; + font-family: Georgia, Verdana, sans-serif; +} + +h1.alert, h2.alert { + color: #000000; +} + +em { + font-style: normal; + font-weight: bold; +} + +.ooc { + color: #002eb8; + font-weight: bold; +} + +.adminobserverooc { + color: #0099cc; + font-weight: bold; +} + +.adminooc { + color: #700038; + font-weight: bold; +} + +.adminsay { + color: #ff4500; + font-weight: bold; +} + +.admin { + color: #4473ff; + font-weight: bold; +} + +.name { + font-weight: bold; +} + +.say, .emote, .infoplain, .oocplain, .warningplain, .mentor { +} + +.deadsay { + color: #5c00e6; +} + +.binarysay { + color: #20c20e; + background-color: #000000; + display: block; +} + +.binarysay a { + color: #00ff00; +} + +.binarysay a:active, +.binarysay a:visited { + color: #88ff88; +} + +.radio { + color: #008000; +} + +.sciradio { + color: #993399; +} + +.comradio { + color: #948f02; +} + +.secradio { + color: #a30000; +} + +.medradio { + color: #337296; +} + +.engradio { + color: #fb5613; +} + +.suppradio { + color: #a8732b; +} + +.servradio { + color: #6eaa2c; +} + +.syndradio { + color: #6d3f40; +} + +.gangradio { + color: #ac2ea1; +} + +.centcomradio { + color: #686868; +} + +.aiprivradio { + color: #ff00ff; +} + +.redteamradio { + color: #ff0000; +} + +.blueteamradio { + color: #0000ff; +} + +.greenteamradio { + color: #00ff00; +} + +.yellowteamradio { + color: #d1ba22; +} + +.yell { + font-weight: bold; +} + +.alert { + color: #ff0000; +} + +h1.alert, h2.alert { + color: #000000; +} + +.userdanger { + color: #ff0000; + font-weight: bold; + font-size: 185%; +} + +.bolddanger { + color: #ff0000; + font-weight: bold; +} + +.danger { + color: #ff0000; +} + +.tinydanger { + color: #ff0000; + font-size: 85%; +} + +.smalldanger { + color: #ff0000; + font-size: 90%; +} + +.warning { + color: #ff0000; + font-style: italic; +} + +.alertwarning { + color: #FF0000; + font-weight: bold; +} + +.boldwarning { + color: #ff0000; + font-style: italic; + font-weight: bold; +} + +.announce { + color: #228b22; + font-weight: bold; +} + +.boldannounce { + color: #ff0000; + font-weight: bold; +} + +.minorannounce { + font-weight: bold; + font-size: 185%; +} + +.greenannounce { + color: #00ff00; + font-weight: bold; +} + +.rose { + color: #ff5050; +} + +.info { + color: #0000CC; +} + +.notice { + color: #000099; +} + +.tinynotice { + color: #000099; + font-size: 85%; +} + +.tinynoticeital { + color: #000099; + font-style: italic; + font-size: 85%; +} + +.smallnotice { + color: #000099; + font-size: 90%; +} + +.smallnoticeital { + color: #000099; + font-style: italic; + font-size: 90%; +} + +.boldnotice { + color: #000099; + font-weight: bold; +} + +.hear { + color: #000099; + font-style: italic; +} + +.adminnotice { + color: #0000ff; +} + +.adminhelp { + color: #ff0000; + font-weight: bold; +} + +.unconscious { + color: #0000ff; + font-weight: bold; +} + +.suicide { + color: #ff5050; + font-style: italic; +} + +.green { + color: #03ff39; +} + +.grey { + color: #838383; +} + +.red { + color: #FF0000; +} + +.blue { + color: #0000FF; +} + +.nicegreen { + color: #14a833; +} + +.boldnicegreen { + color: #14a833; + font-weight: bold; +} + +.cult { + color: #973e3b; +} + +.cultitalic { + color: #973e3b; + font-style: italic; +} + +.cultbold { + color: #973e3b; + font-style: italic; + font-weight: bold; +} + +.cultboldtalic { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.cultlarge { + color: #973e3b; + font-weight: bold; + font-size: 185%; +} + +.narsie { + color: #973e3b; + font-weight: bold; + font-size: 925%; +} + +.narsiesmall { + color: #973e3b; + font-weight: bold; + font-size: 370%; +} + +.colossus { + color: #7F282A; + font-size: 310%; +} + +.hierophant { + color: #660099; + font-weight: bold; + font-style: italic; +} + +.hierophant_warning { + color: #660099; + font-style: italic; +} + +.purple { + color: #5e2d79; +} + +.holoparasite { + color: #35333a; +} + +.revennotice { + color: #1d2953; +} + +.revenboldnotice { + color: #1d2953; + font-weight: bold; +} + +.revenbignotice { + color: #1d2953; + font-weight: bold; + font-size: 185%; +} + +.revenminor { + color: #823abb; +} + +.revenwarning { + color: #760fbb; + font-style: italic; +} + +.revendanger { + color: #760fbb; + font-weight: bold; + font-size: 185%; +} + +.deconversion_message { + color: #5000A0; + font-size: 185%; + font-style: italic; +} + +.ghostalert { + color: #5c00e6; + font-style: italic; + font-weight: bold; +} + +.alien { + color: #543354; +} + +.noticealien { + color: #00c000; +} + +.alertalien { + color: #00c000; + font-weight: bold; +} + +.changeling { + color: #800080; + font-style: italic; +} + +.alertsyndie { + color: #FF0000; + font-size: 185%; + font-weight: bold; +} + +.spider { + color: #4d004d; + font-weight: bold; + font-size: 185%; +} + +.interface { + color: #330033; +} + +.sans { + font-family: "Comic Sans MS", cursive, sans-serif; +} + +.papyrus { + font-family: "Papyrus", cursive, sans-serif; +} + +.robot { + font-family: "Courier New", cursive, sans-serif; +} + +.tape_recorder { + color: #800000; + font-family: "Courier New", cursive, sans-serif; +} + +.command_headset { + font-weight: bold; + font-size: 160%; +} + +.small { + font-size: 60%; +} + +.big { + font-size: 185%; +} + +.reallybig { + font-size: 245%; +} + +.extremelybig { + font-size: 310%; +} + +.greentext { + color: #00FF00; + font-size: 185%; +} + +.redtext { + color: #FF0000; + font-size: 185%; +} + +.clown { + color: #FF69Bf; + font-size: 160%; + font-family: "Comic Sans MS", cursive, sans-serif; + font-weight: bold; +} + +.singing { + font-family: "Trebuchet MS", cursive, sans-serif; + font-style: italic; +} + +.his_grace { + color: #15D512; + font-family: "Courier New", cursive, sans-serif; + font-style: italic; +} + +.hypnophrase { + color: #0d0d0d; + font-weight: bold; + animation: hypnocolor 1500ms infinite; + animation-direction: alternate; +} + +@keyframes hypnocolor { + 0% { + color: #0d0d0d; + } + + 25% { + color: #410194; + } + + 50% { + color: #7f17d8; + } + + 75% { + color: #410194; + } + + 100% { + color: #3bb5d3; + } +} + +.phobia { + color: #dd0000; + font-weight: bold; + animation: phobia 750ms infinite; +} + +@keyframes phobia { + 0% { + color: #0d0d0d; + } + + 50% { + color: #dd0000; + } + + 100% { + color: #0d0d0d; + } +} + +.icon { + height: 1em; + width: auto; +} + +.bigicon { + font-size: 2.5em; +} + +.memo { + color: #638500; + text-align: center; +} + +.memoedit { + text-align: center; + font-size: 125%; +} + +.abductor { + color: #800080; + font-style: italic; +} + +.mind_control { + color: #A00D6F; + font-size: 100%; + font-weight: bold; + font-style: italic; +} + +.slime { + color: #00CED1; +} + +.drone { + color: #848482; +} + +.monkey { + color: #975032; +} + +.swarmer { + color: #2C75FF; +} + +.resonate { + color: #298F85; +} + +.monkeyhive { + color: #774704; +} + +.monkeylead { + color: #774704; + font-size: 80%; +} + +.connectionClosed, +.fatalError { + background: red; + color: white; + padding: 5px; +} + +.connectionClosed.restored { + background: green; +} + +.internal.boldnshit { + color: blue; + font-weight: bold; +} + + + +/* HELPER CLASSES */ + + +.text-normal { + font-weight: normal; + font-style: normal; +} + +.hidden { + display: none; + visibility: hidden; +} + +.ml-1 { + margin-left: 1em; +} + +.ml-2 { + margin-left: 2em; +} + +.ml-3 { + margin-left: 3em; +} + +.tooltip { + font-style: italic; + border-bottom: 1px dashed #000; +} + +/* SKYRAT LIGHT MODE CLASSES */ +.mentor {color: #8a2be2;} +.looc {color: #6699CC; font-weight: bold;} +.rlooc {color: #507294; font-weight: bold;} + +.examine_block { + background: rgba(0, 0, 0, 0.1); + border: 1px solid #111a27; + margin: 2px 8px; + padding: 8px 12px; + max-width: 550px; +} + +.examine_block hr { + border: none; + background: #333; + height: 1px; + margin: 8px 16px 8px 16px; +} + +.crossooc { + color: #9f6efc; + font-weight: bold; +} + +.crossasay { + color: #ff0000; + font-weight: bold; +} + +.pink { + color: #ff00ff; + font-weight: bold; +} + +.brown { + color: #3d2009; + font-weight: bold; +} + +.orange { + color: #b8761a; + font-weight: bold; +} + +.yellow { + color: #c7b72c; + font-weight: bold; +} + +.cyan { + color: #0ea1e6; + font-weight: bold; +} diff --git a/tgui/packages/tgui/interfaces/Cargo.js b/tgui/packages/tgui/interfaces/Cargo.js index 6692e4afb1f1..9857fbf795d4 100644 --- a/tgui/packages/tgui/interfaces/Cargo.js +++ b/tgui/packages/tgui/interfaces/Cargo.js @@ -38,6 +38,12 @@ export const CargoContent = (props, context) => { onClick={() => setTab('requests')}> Requests ({requests.length}) + act('gun_window')}> + Gun Requisitions + {!requestonly && ( <> { {tab === 'requests' && } {tab === 'cart' && } {tab === 'help' && } + {tab === 'gun_window' && tab === 'catalog'} ); }; diff --git a/tgui/packages/tgui/interfaces/CargoGunConsole.js b/tgui/packages/tgui/interfaces/CargoGunConsole.js new file mode 100644 index 000000000000..19727bf9c807 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CargoGunConsole.js @@ -0,0 +1,201 @@ +import { useBackend, useLocalState } from '../backend'; +import { Section, Stack, Box, Divider, Button, NumberInput } from '../components'; +import { Window } from '../layouts'; + +export const CargoGunConsole = (props, context) => { + const [category, setCategory] = useLocalState(context, 'category', ''); + const [weapon, setArmament] = useLocalState(context, 'weapon'); + const { act, data } = useBackend(context); + const { + armaments_list = [], + budget_points, + budget_name, + ammo_amount, + self_paid, + } = data; + return ( + + +
+ + + act('toggleprivate')} /> + + Current Budget: {budget_name} + + + Budget Remaining: {budget_points} + + + + + + +
+ + {armaments_list.map(armament_category => ( + + {armament_category.category_purchased ? ( +
+
+ + +
+ {armaments_list.map(armament_category => ( + armament_category.category === category && ( + armament_category.subcategories.map(subcat => ( +
+ + {subcat.items.map(item => ( + + + + ))} + +
+ )) + ) + ))} +
+
+ + +
+ {armaments_list.map(armament_category => ( + armament_category.subcategories.map(subcat => ( + subcat.items.map(item => ( + item.ref === weapon && ( + + + + + + + + {item.description} + + {!!item.cant_purchase && ( + + {'Company interest needs to be higher to buy this item!'} + + )} + + {'Quantity Remaining: ' + (item.quantity)} + + budget_points) ? "red" : "green"}> + {'Cost: ' + item.cost} + + {!!item.buyable_ammo && ( + budget_points) ? "red" : "green"}> + {'Ammo Cost: ' + item.magazine_cost} + + )} + +
+
+
+
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/KeycardAuth.js b/tgui/packages/tgui/interfaces/KeycardAuth.js index f38e8b3b6800..3c2c0c1c3028 100644 --- a/tgui/packages/tgui/interfaces/KeycardAuth.js +++ b/tgui/packages/tgui/interfaces/KeycardAuth.js @@ -5,7 +5,8 @@ import { Window } from '../layouts'; export const KeycardAuth = (props, context) => { const { act, data } = useBackend(context); return ( - + // SKYRAT EDIT: height 125 -> 150, addition of permit-locked firing pin +
- - - -
- {armaments_list.map(armament_category => ( - armament_category.category === category && ( - armament_category.subcategories.map(subcat => ( -
- - {subcat.items.map(item => ( - - - - ))} - -
- )) - ) - ))} -
-
- - -
- {armaments_list.map(armament_category => ( - armament_category.subcategories.map(subcat => ( - subcat.items.map(item => ( - item.ref === weapon && ( - - - - - - - - {item.description} - - {!!item.cant_purchase && ( - - {'Company interest needs to be higher to buy this item!'} - - )} - - {'Quantity Remaining: ' + (item.quantity)} - - budget_points) ? "red" : "green"}> - {'Cost: ' + item.cost} - - {!!item.buyable_ammo && ( - budget_points) ? "red" : "green"}> - {'Ammo Cost: ' + item.magazine_cost} - - )} - -
-
- -
@@ -55,6 +56,12 @@ export const KeycardAuth = (props, context) => { onClick={() => act('give_janitor_access')} content="Grant Janitor Access" /> +