diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index d3fcecdbea..b5a80b1523 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -422,6 +422,7 @@ /atom var/icon_type_smooth var/junction + var/bypass_interactions = FALSE /atom/proc/recalculate_junction() junction = 0 diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index a9300afbf5..8db23ce2f4 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -59,6 +59,12 @@ var/obj/item/h = get_active_held_item() if(h) . = h.CanItemAutoclick(object, location, params) + if(istype(loc, /obj/mecha)) + var/obj/mecha/piloting = loc + if(piloting.selected && istype(piloting.selected, /obj/item/mecha_parts/mecha_equipment/weapon)) + var/obj/item/mecha_parts/mecha_equipment/weapon/selectedweapon = piloting.selected + . = selectedweapon.is_automatic + /mob/proc/canMobMousedown(atom/object, location, params) diff --git a/code/controllers/subsystem/jukeboxes.dm b/code/controllers/subsystem/jukeboxes.dm index 614ffb6c89..ea50b50410 100644 --- a/code/controllers/subsystem/jukeboxes.dm +++ b/code/controllers/subsystem/jukeboxes.dm @@ -97,6 +97,14 @@ SUBSYSTEM_DEF(jukeboxes) var/area/currentarea = get_area(jukebox) var/turf/currentturf = get_turf(jukebox) var/list/hearerscache = hearers(7, jukebox) + var/turf/currentturfabove = SSmapping.get_turf_above(currentturf) + if(istype(currentturf, /turf/open/transparent/openspace)) + var/turf/belowturf = SSmapping.get_turf_below(currentturf) + hearerscache += hearers(7, belowturf) + if(istype(currentturfabove, /turf/open/transparent/openspace)) + hearerscache += hearers(7, currentturfabove) + if(!isturf(jukebox.loc)) + hearerscache += hearers(7, jukebox.loc) song_played.falloff = jukeinfo[4] @@ -108,16 +116,16 @@ SUBSYSTEM_DEF(jukeboxes) continue var/inrange = FALSE - if(jukebox.z == M.z) //todo - expand this to work with mining planet z-levels when robust jukebox audio gets merged to master - song_played.status = SOUND_UPDATE - if(get_area(M) == currentarea) - inrange = TRUE - else if(M in hearerscache) - inrange = TRUE + //if(jukebox.z == M.z) //todo - expand this to work with mining planet z-levels when robust jukebox audio gets merged to master + song_played.status = SOUND_UPDATE + if(get_area(M) == currentarea) + inrange = TRUE + else if(M in hearerscache) + inrange = TRUE else song_played.status = SOUND_MUTE | SOUND_UPDATE //Setting volume = 0 doesn't let the sound properties update at all, which is lame. - M.playsound_local(currentturf, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000)) + M.playsound_local(M, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000)) CHECK_TICK return //BIG IRON EDIT start diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index ec86f6735c..e1dd0102c8 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -86,7 +86,13 @@ SUBSYSTEM_DEF(throwing) if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept finalize() return - + var/turf/starting_turf = get_turf(AM) + if(AM.z < target_turf.z) + var/turf/new_turf = SSmapping.get_turf_above(starting_turf) + AM.forceMove(new_turf) + if(starting_turf.z > target_turf.z) + var/turf/new_turf = SSmapping.get_turf_below(starting_turf) + AM.forceMove(new_turf) var/atom/step last_move = world.time diff --git a/code/datums/components/crafting/recipes/recipes_carparts.dm b/code/datums/components/crafting/recipes/recipes_carparts.dm index 270d25b02e..00433bc3a8 100644 --- a/code/datums/components/crafting/recipes/recipes_carparts.dm +++ b/code/datums/components/crafting/recipes/recipes_carparts.dm @@ -23,6 +23,18 @@ category = CAT_CARPARTS subcategory = CAT_CAREQUIP +/datum/crafting_recipe/carpart/stereo + name = "Mounted Stereo" + result = /obj/item/mecha_parts/mecha_equipment/stereo + reqs = list(/obj/item/stack/sheet/metal = 5, + /obj/item/stack/crafting/metalparts = 10, + /obj/item/circuitboard/machine/jukebox = 1, + /obj/item/stack/rods = 5) + tools = list(TOOL_WORKBENCH) + time = 90 + category = CAT_CARPARTS + subcategory = CAT_CAREQUIP + /datum/crafting_recipe/carpart/Car_engine name = "Car Engine" result = /obj/item/mecha_parts/part/Car_engine diff --git a/code/datums/components/crafting/recipes/recipes_tools.dm b/code/datums/components/crafting/recipes/recipes_tools.dm index c4937363bc..2fe37ac87c 100644 --- a/code/datums/components/crafting/recipes/recipes_tools.dm +++ b/code/datums/components/crafting/recipes/recipes_tools.dm @@ -130,3 +130,14 @@ /obj/item/stack/rods = 2) category = CAT_CRAFTING subcategory = CAT_TOOL + +/datum/crafting_recipe/cellupgrade + name = "High cell to Ultra cell convertion" + result = /obj/item/stock_parts/cell/bluespace + time = 80 + reqs = list(/obj/item/stock_parts/cell/high = 4, + /obj/item/stack/cable_coil = 10, + /obj/item/toy/crayon/spraycan = 1) + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + category = CAT_CRAFTING + subcategory = CAT_TOOL diff --git a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm index aeaff12021..24c8cb6583 100644 --- a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm +++ b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm @@ -622,6 +622,199 @@ category = CAT_WEAPONRY subcategory = CAT_WEAPON +/datum/crafting_recipe/gun/InmolatorCannon + name = "CH-PS \"Immolator\" laser" + result = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser + reqs = list(/obj/item/stack/crafting/metalparts = 10, + /obj/item/stack/crafting/electronicparts = 10, + /obj/item/stack/sheet/metal = 15, + /obj/item/advanced_crafting_components/lenses = 1, + /obj/item/advanced_crafting_components/conductors = 1) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/SolarisCannon + name = "CH-PS \"Immolator\" laser" + result = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy + reqs = list(/obj/item/stack/crafting/metalparts = 10, + /obj/item/stack/crafting/electronicparts = 10, + /obj/item/stack/crafting/goodparts = 10, + /obj/item/stack/sheet/mineral/titanium = 5, + /obj/item/advanced_crafting_components/lenses = 1, + /obj/item/advanced_crafting_components/conductors = 2, + /obj/item/advanced_crafting_components/flux = 1) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/CarbineVehicle + name = "FNX-99 \"Hades\" Carbine" + result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine + reqs = list(/obj/item/stack/crafting/metalparts = 5, + /obj/item/stack/sheet/metal = 10, + /obj/item/stack/rods = 2, + /obj/item/advanced_crafting_components/assembly = 1, + /datum/reagent/fuel = 50) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/Scattershot + name = "LBX AC 10 \"Scattershot\"" + result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot + reqs = list(/obj/item/stack/crafting/metalparts = 10, + /obj/item/stack/crafting/goodparts = 5, + /obj/item/stack/sheet/metal = 15, + /obj/item/stack/rods = 4, + /obj/item/advanced_crafting_components/assembly = 1,) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/minigunVehicle + name = "Minigun" + result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/minigun + reqs = list(/obj/item/stack/crafting/metalparts = 10, + /obj/item/stack/crafting/goodparts = 5, + /obj/item/stack/crafting/electronicparts = 5, + /obj/item/stack/sheet/metal = 10, + /obj/item/stack/sheet/mineral/titanium = 20, + /obj/item/stack/rods = 6, + /obj/item/advanced_crafting_components/assembly = 1, + /obj/item/advanced_crafting_components/receiver = 1, + /obj/item/advanced_crafting_components/alloys = 1) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/PheumonicLauncherVehicle + name = "Mounted Pheumonic launcher" + result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind + reqs = list(/obj/item/stack/crafting/metalparts = 20, + /obj/item/stack/crafting/goodparts = 10, + /obj/item/stack/crafting/electronicparts = 5, + /obj/item/stack/sheet/metal = 30, + /obj/item/stack/sheet/mineral/titanium = 20, + /obj/item/stack/rods = 8, + /obj/item/advanced_crafting_components/assembly = 1, + /obj/item/advanced_crafting_components/receiver = 1) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/Missile_rack + name = "SRM-8 missile rack" + result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack + reqs = list(/obj/item/stack/crafting/metalparts = 20, + /obj/item/stack/crafting/goodparts = 20, + /obj/item/stack/crafting/electronicparts = 10, + /obj/item/stack/sheet/mineral/titanium = 50, + /obj/item/stack/rods = 8, + /obj/item/advanced_crafting_components/alloys = 1) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/gun/Breach_missile_rack + name = "BRM-6 missile rack" + result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/breaching + reqs = list(/obj/item/stack/crafting/metalparts = 20, + /obj/item/stack/crafting/goodparts = 20, + /obj/item/stack/crafting/electronicparts = 10, + /obj/item/stack/sheet/mineral/titanium = 40, + /obj/item/stack/rods = 6, + /obj/item/advanced_crafting_components/alloys = 1) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON + +/datum/crafting_recipe/mech_ammo/scattershot + name = "Scattershot ammo pack" + result = /obj/item/mecha_ammo/scattershot + reqs = list(/obj/item/ammo_box/shotgun/buck = 4, + /obj/item/stack/crafting/metalparts = 5, + /obj/item/stack/crafting/powder = 10) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_AMMO + +/datum/crafting_recipe/mech_ammo/carbine + name = "Hades ammo pack" + result = /obj/item/mecha_ammo/incendiary + reqs = list(/obj/item/ammo_box/a762box = 1, + /datum/reagent/fuel = 40, + /obj/item/stack/crafting/powder = 10) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_AMMO + +/datum/crafting_recipe/mech_ammo/srm8_missiles + name = "SRM-8 missile pack" + result = /obj/item/mecha_ammo/missiles_he + reqs = list(/obj/item/ammo_casing/caseless/rocket = 3, + /obj/item/stack/sheet/metal = 10, + /obj/item/assembly/timer = 4) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_AMMO + +/datum/crafting_recipe/mech_ammo/brm8_missiles + name = "BRM-8 missile pack" + result = /obj/item/mecha_ammo/missiles_br + reqs = list(/obj/item/ammo_casing/caseless/rocket = 4, + /obj/item/stack/sheet/mineral/titanium = 20, + /obj/item/stack/crafting/powder = 10) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_AMMO + +/datum/crafting_recipe/mech_ammo/minigun_ammo + name = "Minigun Ammo Pack" + result = /obj/item/mecha_ammo/minigun + reqs = list(/obj/item/ammo_box/magazine/ammobelt/m1919 = 3, + /obj/item/stack/sheet/metal = 10, + /obj/item/stack/sheet/mineral/titanium = 20, + /obj/item/stack/crafting/powder = 30) + tools = list(TOOL_WORKBENCH) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_AMMO + +/datum/crafting_recipe/mech_ammo/antoproj_armor + name = "armor booster module (Ranged Weaponry)" + result = /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster + reqs = list(/obj/item/shield/riot/tower = 2, + /obj/item/stack/cable_coil = 5, + /obj/item/stack/sheet/mineral/titanium = 20) + tools = list(TOOL_WELDER) + time = 180 + category = CAT_CARPARTS + subcategory = CAT_CAREQUIP + +/datum/crafting_recipe/mech_ammo/antomelee_armor + name = "armor booster module (Melee Weaponry)" + result = /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster + reqs = list(/obj/item/shield/riot/tower = 2, + /obj/item/stack/cable_coil = 5, + /obj/item/stack/sheet/mineral/titanium = 20) + tools = list(TOOL_WELDER) + time = 180 + category = CAT_CARPARTS + subcategory = CAT_CAREQUIP + /datum/crafting_recipe/gun/HMGvehicule name = "Improvised HMG (for vehicules)" result = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg/hobo diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm index 20a353e264..6e1ecbc265 100644 --- a/code/game/mecha/combat/phazon.dm +++ b/code/game/mecha/combat/phazon.dm @@ -88,7 +88,7 @@ strafing_action.Remove(user) zoom_action.Remove(user) eject_action.Remove(user) - landing_action.Grant(user) + landing_action.Remove(user) //rotorup_action.Remove(user) //rotordown_action.Remove(user) @@ -181,7 +181,7 @@ zoom_action.Remove(user) eject_action.Remove(user) smoke_action.Remove(user) - landing_action.Grant(user) + landing_action.Remove(user) //rotorup_action.Remove(user) //rotordown_action.Remove(user) @@ -262,7 +262,7 @@ strafing_action.Remove(user) zoom_action.Remove(user) eject_action.Remove(user) - landing_action.Grant(user) + landing_action.Remove(user) //rotorup_action.Remove(user) //rotordown_action.Remove(user) @@ -337,7 +337,7 @@ strafing_action.Remove(user) zoom_action.Remove(user) eject_action.Remove(user) - landing_action.Grant(user) + landing_action.Remove(user) //rotorup_action.Remove(user) //rotordown_action.Remove(user) @@ -401,6 +401,7 @@ zoom_action.Grant(user, src) eject_action.Grant(user, src) smoke_action.Grant(user, src) + landing_action.Grant(user, src) //rotorup_action.Grant(user, src) //rotordown_action.Grant(user, src) @@ -413,6 +414,7 @@ zoom_action.Remove(user) eject_action.Remove(user) smoke_action.Remove(user) + landing_action.Remove(user, src) //rotorup_action.Remove(user) //rotordown_action.Remove(user) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index e74c6edce0..511a63e71d 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -586,3 +586,221 @@ /obj/item/mecha_parts/mecha_equipment/generator/nuclear/process() if(..()) radiation_pulse(get_turf(src), rad_per_cycle) + +/////////////////////////////////////////// STEREO SYSTEM ///////////////////////////////////////////// + + +/obj/item/mecha_parts/mecha_equipment/stereo + name = "exosuit Stereo System" + desc = "a stereo system hooked up a jukebox, modified for easy transport." + icon_state = "mecha_stereo" + range = MELEE + var/active = FALSE + var/list/rangers = list() + var/stop = 0 + var/volume = 70 + var/datum/track/selection = null + var/open_tray = TRUE + var/list/obj/item/record_disk/record_disks = list() + var/obj/item/record_disk/selected_disk = null + +/obj/item/mecha_parts/mecha_equipment/stereo/attach(obj/mecha/M) + . = ..() + bypass_interactions = TRUE + +/obj/item/mecha_parts/mecha_equipment/stereo/detach(obj/mecha/M) + . = ..() + bypass_interactions = FALSE + +/obj/item/mecha_parts/mecha_equipment/stereo/attackby(obj/item/O, mob/user, params) + . = ..() + if(!active) + if(istype(O, /obj/item/record_disk)) //this one checks for a record disk and if the jukebox is open, it adds it to the machine + if(open_tray == FALSE) + to_chat(usr, "The Disk Tray is not open!") + return + var/obj/item/record_disk/I = O + if(!I.R.song_associated_id) + to_chat(user, span_warning("This record is empty!")) + return + for(var/datum/track/RT in SSjukeboxes.songs) + if(I.R.song_associated_id == RT.song_associated_id) + to_chat(user, span_warning("this track is already added to the jukebox!")) + return + record_disks += I + O.forceMove(src) + playsound(src, 'sound/effects/plastic_click.ogg', 100, 0) + if(I.R.song_path) + SSjukeboxes.add_song(I.R) + return + +/obj/item/mecha_parts/mecha_equipment/stereo/proc/eject_record(obj/item/record_disk/M) //BIG IRON EDIT -start- ejects a record as defined and removes it's song from the list + if(!M) + visible_message("no disk to eject") + return + playsound(src, 'sound/effects/disk_tray.ogg', 100, 0) + src.visible_message(" ejected the [selected_disk] from the [src]!") + M.forceMove(get_turf(src)) + SSjukeboxes.remove_song(M.R) + record_disks -= M + selected_disk = null + +/obj/item/mecha_parts/mecha_equipment/stereo/ui_status(mob/user) + if(!SSjukeboxes.songs.len && !isobserver(user)) + to_chat(user,"Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.") + playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE) + return UI_CLOSE + return ..() + +/obj/item/mecha_parts/mecha_equipment/stereo/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Jukebox", name) + ui.open() + +/obj/item/mecha_parts/mecha_equipment/stereo/ui_data(mob/user) + var/list/data = list() + data["active"] = active + data["songs"] = list() + for(var/datum/track/S in SSjukeboxes.songs) + var/list/track_data = list( + name = S.song_name + ) + data["songs"] += list(track_data) + data["track_selected"] = null + data["track_length"] = null + data["track_beat"] = null + data["disks"] = list() + for(var/obj/item/record_disk/RD in record_disks) + var/list/tracks_data = list( + name = RD.name + ) + data["disks"] += list(tracks_data) + data["disk_selected"] = null //BIG IRON EDIT- start more tracks data + data["disk_selected_lenght"] = null + data["disk_beat"] = null //BIG IRON EDIT -end + if(selection) + data["track_selected"] = selection.song_name + data["track_length"] = DisplayTimeText(selection.song_length) + data["track_beat"] = selection.song_beat + if(selected_disk) + data["disk_selected"] = selected_disk + data["disk_selected_length"] = DisplayTimeText(selected_disk.R.song_length) + data["disk_selected_beat"] = selected_disk.R.song_beat + data["volume"] = volume + return data + +/obj/item/mecha_parts/mecha_equipment/stereo/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("toggle") + if(QDELETED(src)) + return + if(!active) + if(stop > world.time) + to_chat(usr, "Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].") + playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE) + return + activate_music() + START_PROCESSING(SSobj, src) + return TRUE + else + stop = 0 + return TRUE + if("select_track") + if(active) + to_chat(usr, "Error: You cannot change the song until the current one is over.") + return + var/list/available = list() + for(var/datum/track/S in SSjukeboxes.songs) + available[S.song_name] = S + var/selected = params["track"] + if(QDELETED(src) || !selected || !istype(available[selected], /datum/track)) + return + selection = available[selected] + return TRUE + if("select_record") + if(!record_disks.len) + to_chat(usr, "Error: no tracks on the bin!.") + return + var/list/obj/item/record_disk/availabledisks = list() + for(var/obj/item/record_disk/RR in record_disks) + availabledisks[RR.name] = RR + var/selecteddisk = params["record"] + if(QDELETED(src) || !selecteddisk) + return + selected_disk = availabledisks[selecteddisk] + updateUsrDialog() + if("eject_disk") // sanity check for the disk ejection + if(!record_disks.len) + to_chat(usr, "Error: no disks in trays.") + return + if(!selected_disk) + to_chat(usr,"Error: no disk chosen." ) + return + if(selection == selected_disk.R) + selection = null + eject_record(selected_disk) + return TRUE + if("set_volume") + var/new_volume = params["volume"] + if(new_volume == "reset") + volume = initial(volume) + return TRUE + else if(new_volume == "min") + volume = 0 + return TRUE + else if(new_volume == "max") + volume = 100 + return TRUE + else if(text2num(new_volume) != null) + volume = text2num(new_volume) + return TRUE + +/obj/item/mecha_parts/mecha_equipment/stereo/proc/activate_music() + if(!selection) + visible_message("Track is no longer avaible") + return + var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2) + if(jukeboxslottotake) + active = TRUE + update_icon() + START_PROCESSING(SSobj, src) + stop = world.time + selection.song_length + return TRUE + else + return FALSE + +/obj/item/mecha_parts/mecha_equipment/stereo/get_equip_info() + var/output = ..() + if(output) + var/temp = "" + temp = "Dashboard" + return "[output] [temp]" + return + +/obj/item/mecha_parts/mecha_equipment/stereo/Topic(href,href_list) + ..() + if(href_list["dashboard"]) + var/mob/user = chassis.occupant + ui_interact(user) + return + +/obj/item/mecha_parts/mecha_equipment/stereo/process() + if(active && world.time >= stop) + active = FALSE + dance_over() + playsound(src,'sound/machines/terminal_off.ogg',50,1) + update_icon() + stop = world.time + 100 + +/obj/item/mecha_parts/mecha_equipment/stereo/proc/dance_over() + var/position = SSjukeboxes.findjukeboxindex(src) + if(!position) + return + SSjukeboxes.removejukebox(position) + STOP_PROCESSING(SSobj, src) + rangers = list() diff --git a/code/game/mecha/equipment/weapons/mecha_ammo.dm b/code/game/mecha/equipment/weapons/mecha_ammo.dm index 7a7ea295f5..020fdc9d06 100644 --- a/code/game/mecha/equipment/weapons/mecha_ammo.dm +++ b/code/game/mecha/equipment/weapons/mecha_ammo.dm @@ -99,3 +99,10 @@ round_term = "cluster" direct_load = TRUE ammo_type = "clusterbang" + +/obj/item/mecha_ammo/minigun + name = "Minigun ammo pack" + desc = "A box of high caliber ammo, ready to be consumed in nano seconds. Cannot be primed by hand." + icon_state = "lmg" + rounds = 600 + ammo_type = "minigun" diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 172e32645b..1f50c6217e 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -268,6 +268,7 @@ projectiles_cache = 300 projectiles_cache_max = 1200 projectiles_per_shot = 3 + is_automatic = TRUE variance = 6 randomspread = 1 projectile_delay = 2 @@ -308,6 +309,85 @@ harmful = TRUE ammo_type = "lmg" +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/minigun + name = "\improper Minigun" + desc = "A heavy machine gun capable of rapidly firing 7.62mm rounds. ready for vehicle mounting, with internal ammo box." + icon_state = "mecha_uac2" + fire_sound = 'sound/f13weapons/antimaterielfire.ogg' + equip_cooldown = 1 + projectile = /obj/item/projectile/bullet/a762 + projectiles = 300 + projectiles_cache = 300 + projectiles_cache_max = 600 + projectiles_per_shot = 1 + variance = 6 + is_automatic = TRUE + randomspread = 112 + harmful = TRUE + ammo_type = "minigun" + var/overheat = 0 + var/overheat_max = 160 + var/heat_diffusion = 2.5 //How much heat is lost per tick + var/damage = 25 + + + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/minigun/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/minigun/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/minigun/process() + overheat = max(0, overheat - heat_diffusion) + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/minigun/action(atom/target, params) + if(!action_checks(target)) + return 0 + var/turf/curloc = get_turf(chassis) + var/turf/targloc = get_turf(target) + if (!targloc || !istype(targloc) || !curloc) + return 0 + if (targloc == curloc) + return 0 + if(overheat < overheat_max) + overheat += projectiles_per_shot + else + chassis.occupant_message("The gun's heat sensor locked the trigger to prevent barrel damage.") + return + chassis.occupant.DelayNextAction(3) + set_ready_state(0) + for(var/i=1 to get_shot_amount()) + var/obj/item/projectile/A = new projectile(curloc) + A.firer = chassis.occupant + A.original = target + A.damage = damage + if(!A.suppressed && firing_effect_type) + new firing_effect_type(get_turf(src), chassis.dir) + + var/spread = 0 + if(variance) + if(randomspread) + spread = round((rand() - 0.5) * variance) + else + spread = round((i / projectiles_per_shot - 0.5) * variance) + A.preparePixelProjectile(target, chassis.occupant, params, spread) + + A.fire() + overheat++ + projectiles-- + playsound(chassis, fire_sound, 50, 1) + chassis.occupant.DelayNextAction(1) + + if(kickback) + chassis.newtonian_move(turn(chassis.dir,180)) + + return 1 + + + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack name = "\improper SRM-8 missile rack" desc = "A weapon for combat exosuits. Launches light explosive missiles." @@ -356,6 +436,90 @@ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/proc/proj_init(obj/O) return +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind + name = "\improper Pheumonic launcher" + desc = "A weapon for combat exosuits. anything loaded in it." + icon_state = "mecha_grenadelnchr" + projectile = null + fire_sound = 'sound/weapons/grenadelaunch.ogg' + projectiles = 0 + projectiles_cache = 15 + projectiles_cache_max = 20 + missile_speed = 1.5 + equip_cooldown = 10 + var/det_time = 20 + ammo_type = "Anything" + var/list/obj/stuffs = new + var/open = FALSE + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind/action(target) + if(!action_checks(target)) + return + if(!stuffs.len) + chassis.occupant_message("Nothing to shoot!") + return + var/obj/O = stuffs[1] + playsound(chassis, fire_sound, 50, 1) + mecha_log_message("Launched a [O.name] from [name], targeting [target].") + stuffs -= stuffs[1] + proj_init(O) + var/turf/nextt = (get_turf(src)) + O.forceMove(nextt) + O.throw_at(target, missile_range, missile_speed, chassis.occupant, FALSE, diagonals_first = diags_first) + return 1 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind/proj_init(obj/ammo) + var/turf/T = get_turf(src) + message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] fired a [src] in [ADMIN_VERBOSEJMP(T)]") + log_game("[key_name(chassis.occupant)] fired a [src] in [AREACOORD(T)]") + if(istype(ammo, /obj/item/grenade/)) + var/obj/item/grenade/payload = ammo + addtimer(CALLBACK(payload, /obj/item/grenade.proc/prime), det_time) + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind/attackby(obj/item/W, mob/user, params) + if(open) + if(stuffs.len < projectiles_cache_max) + W.forceMove(src) + stuffs += W + projectiles++ + else + to_chat(user, "The [src] is full!") + return + . = ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind/screwdriver_act(mob/living/carbon/user, obj/item/I) + if(user.a_intent != INTENT_DISARM) + if(open) + to_chat(user, "You close the [src]!.") + else + to_chat(user, "You open the [src]!.") + open = !open + return TRUE + . = ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind/attack_self(mob/user) + if(open && stuffs.len) + var/obj/selectedthing = input(user, "Chosee an item to take out.", "Stuffs inside") as null|anything in stuffs + if(!selectedthing) + return + stuffs -= selectedthing + projectiles-- + selectedthing.forceMove(get_turf(src)) + user.put_in_hand(selectedthing) + return + . = ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/anykind/AltClick(mob/user) + if(open && stuffs.len) + for(var/obj/I in stuffs) + I.forceMove(get_turf(src)) + stuffs -= I + projectiles-- + to_chat(user, "You empty the [src]!.") + return + . = ..() + + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang name = "\improper SGL-6 grenade launcher" diff --git a/code/modules/keybindings/keybind/carbon.dm b/code/modules/keybindings/keybind/carbon.dm index 46cb5cd0ac..fa01eae3b8 100644 --- a/code/modules/keybindings/keybind/carbon.dm +++ b/code/modules/keybindings/keybind/carbon.dm @@ -60,3 +60,39 @@ /datum/keybinding/carbon/select_harm_intent/down(client/user) user.mob?.a_intent_change(INTENT_HARM) return TRUE + +/datum/keybinding/carbon/lookup + hotkey_keys = list(",") + name = "Look_up" + full_name = "Look up" + description = "looks up" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/lookup/down(client/user) + var/mob/living/carbon/C = user.mob + C.lookup() + return TRUE + +/datum/keybinding/carbon/lookdown + hotkey_keys = list(".") + name = "Look_down" + full_name = "looks down" + description = "looks down your feet" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/lookdown/down(client/user) + var/mob/living/carbon/C = user.mob + C.lookdown() + return TRUE + +/datum/keybinding/carbon/lookstop + hotkey_keys = list("-") + name = "Look_stop" + full_name = "stop looking" + description = "stop looking around and see foward" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/lookstop/down(client/user) + var/mob/living/carbon/C = user.mob + C.stop_looking() + return TRUE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 204d342933..db465a7f8a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -427,6 +427,9 @@ set category = "IC" if(src.incapacitated()) to_chat(src, "You can't look up right now!") + if(client.eye != src && !istype(client.eye, /obj/mecha)) + stop_looking() + return var/turf/T = SSmapping.get_turf_above(get_turf(src)) if(!istype(T, /turf/open/transparent/openspace)) if(istype(T, /turf/open) || istype(T, /turf/closed)) @@ -435,16 +438,82 @@ else src.reset_perspective(T) RegisterSignal(src, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/stop_looking_up) //no binos/scops - RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/stop_looking_up) + RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/followcameraup) + if(istype(loc, /obj/mecha)) + RegisterSignal(loc, COMSIG_MOVABLE_MOVED, .proc/followcameraup) RegisterSignal(src, COMSIG_LIVING_STATUS_KNOCKDOWN, .proc/stop_looking_up) RegisterSignal(src, COMSIG_LIVING_STATUS_PARALYZE, .proc/stop_looking_up) RegisterSignal(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, .proc/stop_looking_up) RegisterSignal(src, COMSIG_LIVING_STATUS_SLEEP, .proc/stop_looking_up) +/mob/living/verb/stop_looking() + set name = "Stop Looking" + set category = "IC" + src.stop_looking_up(null) + /mob/living/proc/stop_looking_up() + if(istype(loc, /obj/mecha)) + UnregisterSignal(loc, COMSIG_MOVABLE_MOVED) reset_perspective(null) UnregisterSignal(src, list(COMSIG_LIVING_STATUS_PARALYZE, COMSIG_LIVING_STATUS_UNCONSCIOUS, COMSIG_LIVING_STATUS_SLEEP, COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_MOVABLE_MOVED, COMSIG_MOB_CLIENT_CHANGE_VIEW)) +/mob/living/verb/lookdown() + set name = "Look down" + set category = "IC" + if(src.incapacitated()) + to_chat(src, "You can't look down right now!") + if(client.eye != src && !istype(client.eye, /obj/mecha)) + stop_looking() + return + var/turf/T = get_turf(src) + if(!istype(T, /turf/open/transparent/openspace)) + var/turf/nt = get_step(T, dir) + if(!istype(nt, /turf/open/transparent/openspace)) + if(istype(nt, /turf/open) || istype(nt, /turf/closed)) + to_chat(src, "You look up at the floor. You can see floor.") + return + else + var/turf/nl = SSmapping.get_turf_below(nt) + src.reset_perspective(nl) + RegisterSignal(src, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/stop_looking_down) //no binos/scops + RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/followcameradown) + if(istype(loc, /obj/mecha)) + RegisterSignal(loc, COMSIG_MOVABLE_MOVED, .proc/followcameradown) + RegisterSignal(src, COMSIG_LIVING_STATUS_KNOCKDOWN, .proc/stop_looking_down) + RegisterSignal(src, COMSIG_LIVING_STATUS_PARALYZE, .proc/stop_looking_down) + RegisterSignal(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, .proc/stop_looking_down) + RegisterSignal(src, COMSIG_LIVING_STATUS_SLEEP, .proc/stop_looking_down) + else + var/turf/nl = SSmapping.get_turf_below(T) + src.reset_perspective(nl) + RegisterSignal(src, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/stop_looking_down) //no binos/scops + RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/followcameradown) + if(istype(loc, /obj/mecha)) + RegisterSignal(loc, COMSIG_MOVABLE_MOVED, .proc/followcameradown) + RegisterSignal(src, COMSIG_LIVING_STATUS_KNOCKDOWN, .proc/stop_looking_down) + RegisterSignal(src, COMSIG_LIVING_STATUS_PARALYZE, .proc/stop_looking_down) + RegisterSignal(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, .proc/stop_looking_down) + RegisterSignal(src, COMSIG_LIVING_STATUS_SLEEP, .proc/stop_looking_down) + +/mob/living/proc/stop_looking_down() + reset_perspective(null) + UnregisterSignal(src, list(COMSIG_LIVING_STATUS_PARALYZE, COMSIG_LIVING_STATUS_UNCONSCIOUS, COMSIG_LIVING_STATUS_SLEEP, COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_MOVABLE_MOVED, COMSIG_MOB_CLIENT_CHANGE_VIEW)) + +/mob/living/proc/followcameraup() + var/turf/T = get_turf(src) + var/turf/nl = SSmapping.get_turf_above(T) + if(istype(nl, /turf/open/transparent/openspace)) + reset_perspective(nl) + else + reset_perspective(null) + +/mob/living/proc/followcameradown() + var/turf/T = get_turf(src) + var/turf/nl = SSmapping.get_turf_below(T) + if(istype(T, /turf/open/transparent/openspace)) + reset_perspective(nl) + else + reset_perspective(null) /mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, check_immobilized = FALSE) if(stat || IsUnconscious() || IsStun() || IsParalyzed() || (combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (check_immobilized && IsImmobilized()) || (!ignore_restraints && restrained(ignore_grab))) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index a42ee45e01..a0ee164c82 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -857,7 +857,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) //Can the mob interact() with an atom? /mob/proc/can_interact_with(atom/A) - return IsAdminGhost(src) || Adjacent(A) || A.hasSiliconAccessInArea(src) + return IsAdminGhost(src) || Adjacent(A) || A.hasSiliconAccessInArea(src) || A.bypass_interactions //Can the mob use Topic to interact with machines /mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index f26d9c18b2..af27ba211d 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -502,6 +502,11 @@ if(spread) setAngle(Angle + ((rand() - 0.5) * spread)) var/turf/starting = get_turf(src) + if(original) + if(starting.z > original?.z) + starting = SSmapping.get_turf_below(starting) + if(starting.z < original?.z) + starting = SSmapping.get_turf_above(starting) if(isnull(Angle)) //Try to resolve through offsets if there's no angle set. if(isnull(xo) || isnull(yo)) stack_trace("WARNING: Projectile [type] deleted due to being unable to resolve a target after angle was null!") diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index 1d6bca71b9..90929fff46 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ