diff --git a/nsv13.dme b/nsv13.dme index 97b9c981cf1..2abd39ff698 100644 --- a/nsv13.dme +++ b/nsv13.dme @@ -4052,6 +4052,7 @@ #include "nsv13\code\modules\overmap\types\spacepirates.dm" #include "nsv13\code\modules\overmap\types\syndicate.dm" #include "nsv13\code\modules\overmap\weapons\damage.dm" +#include "nsv13\code\modules\overmap\weapons\mines.dm" #include "nsv13\code\modules\overmap\weapons\plasma_gun.dm" #include "nsv13\code\modules\overmap\weapons\projectiles_fx.dm" #include "nsv13\code\modules\overmap\weapons\ship_weapon.dm" diff --git a/nsv13/code/controllers/subsystem/starsystem.dm b/nsv13/code/controllers/subsystem/starsystem.dm index 366242bf860..a75482a2061 100644 --- a/nsv13/code/controllers/subsystem/starsystem.dm +++ b/nsv13/code/controllers/subsystem/starsystem.dm @@ -298,7 +298,7 @@ Returns a faction datum by its name (case insensitive!) if(backupx && backupy) target.contents_positions[OM] = list("x" = backupx, "y" = backupy) //Cache the ship's position so we can regenerate it later. else - target.contents_positions[OM] = list("x" = rand(15, 240), "y" = rand(15, 240)) + target.contents_positions[OM] = list("x" = rand(15, world.maxx - 15), "y" = rand(15, world.maxy - 15)) else if(!OM.z) START_PROCESSING(SSphysics_processing, OM) @@ -810,6 +810,8 @@ Returns a faction datum by its name (case insensitive!) SSstar_system.spawn_anomaly(/obj/effect/overmap_anomaly/wormhole, src, center=TRUE) if(alignment == "syndicate") spawn_enemies() //Syndicate systems are even more dangerous, and come pre-loaded with some Syndie ships. + if(prob(20)) //Watch your step! + spawn_mines("syndicate") if(alignment == "unaligned") if(prob(25)) spawn_enemies() @@ -897,11 +899,27 @@ Returns a faction datum by its name (case insensitive!) /datum/star_system/proc/spawn_enemies(enemy_type, amount) if(!amount) amount = difficulty_budget + if(amount <= 0) + amount = 1 //Why else are you calling this? for(var/i = 0, i < amount, i++) //number of enemies is set via the star_system vars if(!enemy_type) enemy_type = pick(SSstar_system.enemy_types) //Spawn a random set of enemies. SSstar_system.spawn_ship(enemy_type, src) +/datum/star_system/proc/spawn_mines(faction, amount) + if(!amount) + amount = difficulty_budget*2 + if(amount <= 0) + amount = 1 //Why else are you calling this? + if(!faction) //Someone forgot to set their IFF + faction = alignment + if(!occupying_z) //We didn't get one + for(var/i = 0, i < amount, i++) + var/obj/structure/space_mine/M = new /obj/structure/space_mine(null, faction, src) //You are in nullspace now + contents_positions[M] = list("x" = rand(5, world.maxx - 5),"y" = rand(5, world.maxy - 5)) + for(var/i = 0, i < amount, i++) + new /obj/structure/space_mine(get_turf(locate(rand(5, world.maxx - 5), rand(5, world.maxy - 5), occupying_z)), faction, src) //random location in the system + /datum/star_system/proc/lerp_x(datum/star_system/other, t) return x + (t * (other.x - x)) diff --git a/nsv13/code/modules/overmap/ai-skynet.dm b/nsv13/code/modules/overmap/ai-skynet.dm index 3a41913bb39..82be49c4fe0 100644 --- a/nsv13/code/modules/overmap/ai-skynet.dm +++ b/nsv13/code/modules/overmap/ai-skynet.dm @@ -1531,6 +1531,8 @@ Seek a ship thich we'll station ourselves around OM.send_radar_pulse() if(OM.patrol_target && overmap_dist(OM, OM.patrol_target) <= 8) OM.patrol_target = null //You have arrived at your destination. + if(OM.mines_left >= 1) //Deploy a mine if you have one, this should spread them out nicely + OM.deploy_mine() if(!OM.patrol_target || OM.patrol_target.z != OM.z) var/min_x = max(OM.x - 50, 15) var/max_x = min(OM.x + 50, 240) @@ -1628,6 +1630,7 @@ Seek a ship thich we'll station ourselves around var/decision_delay = 2 SECONDS var/move_mode = 0 var/next_boarding_attempt = 0 + var/mine_cooldown = 0 var/reloading_torpedoes = FALSE var/reloading_missiles = FALSE @@ -1636,6 +1639,7 @@ Seek a ship thich we'll station ourselves around //Fleet organisation var/shots_left = 15 //Number of arbitrary shots an AI can fire with its heavy weapons before it has to resupply with a supply ship. var/light_shots_left = 300 + var/mines_left = 0 var/resupply_range = 15 var/resupplying = 0 //Are we resupplying things right now? If yes, how many? var/can_resupply = FALSE //Can this ship resupply other ships? @@ -2026,6 +2030,8 @@ Seek a ship thich we'll station ourselves around if(!target || QDELETED(target)) return desired_angle = overmap_angle(src, target) - 180 + if(mines_left >= 1) //if we have mines, we should try to discourage anyone from following + deploy_mine() /obj/structure/overmap/proc/circle_around(atom/target) brakes = FALSE @@ -2081,6 +2087,16 @@ Seek a ship thich we'll station ourselves around return TRUE return FALSE +///Make this ship drop a mine. +/obj/structure/overmap/proc/deploy_mine() + if(mines_left <= 0) + return //why are we here + if(mine_cooldown > world.time) //Don't drop them all at once now + return + mine_cooldown = world.time + 6 SECONDS + mines_left-- + new /obj/structure/space_mine(get_center(),faction,current_system) + /client/proc/instance_overmap_menu() //Creates a verb for admins to open up the ui set name = "Instance Overmap" set desc = "Load a ship midround." diff --git a/nsv13/code/modules/overmap/ai_interiors.dm b/nsv13/code/modules/overmap/ai_interiors.dm index 0312a3ee693..5dd3a46ed71 100644 --- a/nsv13/code/modules/overmap/ai_interiors.dm +++ b/nsv13/code/modules/overmap/ai_interiors.dm @@ -3,11 +3,12 @@ duration = 3 SECONDS mouse_opacity = FALSE -/obj/effect/temp_visual/fading_overmap/Initialize(mapload, name, icon, icon_state) +/obj/effect/temp_visual/fading_overmap/Initialize(mapload, name, icon, icon_state, alpha = 255) . = ..() src.name = name src.icon = icon src.icon_state = icon_state + src.alpha = alpha play() /obj/effect/temp_visual/fading_overmap/proc/play() diff --git a/nsv13/code/modules/overmap/armour/armour_quadrant.dm b/nsv13/code/modules/overmap/armour/armour_quadrant.dm index 97746a39f4c..e5ea027f683 100644 --- a/nsv13/code/modules/overmap/armour/armour_quadrant.dm +++ b/nsv13/code/modules/overmap/armour/armour_quadrant.dm @@ -2,6 +2,7 @@ new /obj/structure/overmap/syndicate/ai(get_turf(pick(orange(10, src)))) //Thank you once again to qwerty for writing the directional calc for this. +///Returns the quadrant hit based on a vector point /obj/structure/overmap/proc/check_quadrant(matrix/vector/point_of_collision) if(!point_of_collision) return @@ -19,9 +20,10 @@ if(270 to 360) //Then this represents the last quadrant of the circle, the northwest one return ARMOUR_FORWARD_STARBOARD -/obj/structure/overmap/proc/projectile_quadrant_impact(obj/item/projectile/P) - var/shield_angle_hit = SIMPLIFY_DEGREES(get_angle(P, src) - angle) - switch(shield_angle_hit) +///Returns the quadrant hit by an object +/obj/structure/overmap/proc/quadrant_impact(obj/O) + var/hit_angle = SIMPLIFY_DEGREES(get_angle(O, src) - angle) + switch(hit_angle) if(0 to 89) //0 - 90 deg is the first right quarter of the circle, it's like dividing up a pizza! return ARMOUR_FORWARD_PORT if(90 to 179) diff --git a/nsv13/code/modules/overmap/physics.dm b/nsv13/code/modules/overmap/physics.dm index eee33df53e2..99665fffe79 100644 --- a/nsv13/code/modules/overmap/physics.dm +++ b/nsv13/code/modules/overmap/physics.dm @@ -81,6 +81,9 @@ This proc is to be used when someone gets stuck in an overmap ship, gauss, WHATE return locs[round(locs.len / 2)+1] */ +/obj/structure/overmap/proc/get_center_coordinates() + return list("x" = (src.x+(pixel_collision_size_x/32)/2),"y" = (src.y+(pixel_collision_size_y/32)/2)) + /obj/structure/overmap/proc/get_pixel_bounds() for(var/turf/T in obounds(src, pixel_x + pixel_collision_size_x/4, pixel_y + pixel_collision_size_y/4, pixel_x + -pixel_collision_size_x/4, pixel_y + -pixel_collision_size_x/4) )//Forms a zone of 4 quadrants around the desired overmap using some math fuckery. to_chat(world, "FOO!") @@ -479,8 +482,8 @@ This proc is to be used when someone gets stuck in an overmap ship, gauss, WHATE if(!impact_sound_cooldown && (bonk > 2 || bonk2 > 2)) bonk *= 5 //The rammer gets an innate penalty, to discourage ramming metas. bonk2 *= 5 - take_quadrant_hit(bonk, projectile_quadrant_impact(other)) //This looks horrible, but trust me, it isn't! Probably!. Armour_quadrant.dm for more info - other.take_quadrant_hit(bonk2, projectile_quadrant_impact(src)) //This looks horrible, but trust me, it isn't! Probably!. Armour_quadrant.dm for more info + take_quadrant_hit(bonk, quadrant_impact(other)) //This looks horrible, but trust me, it isn't! Probably!. Armour_quadrant.dm for more info + other.take_quadrant_hit(bonk2, quadrant_impact(src)) //This looks horrible, but trust me, it isn't! Probably!. Armour_quadrant.dm for more info log_game("[key_name(pilot)] has impacted an overmap ship into [other] with velocity [bonk]") diff --git a/nsv13/code/modules/overmap/types/syndicate.dm b/nsv13/code/modules/overmap/types/syndicate.dm index 2e9e7b7b1df..df542fc4112 100644 --- a/nsv13/code/modules/overmap/types/syndicate.dm +++ b/nsv13/code/modules/overmap/types/syndicate.dm @@ -124,6 +124,7 @@ name = "Mauler class flak frigate" icon_state = "mako_flak" flak_battery_amount = 1 + mines_left = 10 mass = MASS_MEDIUM combat_dice_type = /datum/combat_dice/frigate @@ -247,6 +248,7 @@ max_integrity = 600 //Tanky so that it can survive to deploy multiple fighter waves. bounty = 3000 torpedoes = 0 + mines_left = 5 //As a treat armor = list("overmap_light" = 90, "overmap_medium" = 60, "overmap_heavy" = 10) can_resupply = TRUE ai_flags = AI_FLAG_SUPPLY @@ -398,6 +400,7 @@ bound_width = 128 missiles = 10 torpedoes = 10 //Torp boat! + mines_left = 15 //And mine layer! shots_left = 10 armor = list("overmap_light" = 80, "overmap_medium" = 45, "overmap_heavy" = 10) ai_flags = AI_FLAG_DESTROYER diff --git a/nsv13/code/modules/overmap/weapons/damage.dm b/nsv13/code/modules/overmap/weapons/damage.dm index ca785286b9d..09147b657e4 100644 --- a/nsv13/code/modules/overmap/weapons/damage.dm +++ b/nsv13/code/modules/overmap/weapons/damage.dm @@ -53,7 +53,7 @@ Bullet reactions visible_message("[src] is hit by \a [P]!", null, null, COMBAT_MESSAGE_RANGE) if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object //var/datum/vector2d/point_of_collision = src.physics2d?.collider2d.get_collision_point(P.physics2d?.collider2d)//Get the collision point, see if the armour quadrants need to absorb this hit. - take_quadrant_hit(run_obj_armor(P.damage, P.damage_type, P.flag, null, P.armour_penetration), projectile_quadrant_impact(P)) //This looks horrible, but trust me, it isn't! Probably!. Armour_quadrant.dm for more info + take_quadrant_hit(run_obj_armor(P.damage, P.damage_type, P.flag, null, P.armour_penetration), quadrant_impact(P)) //This looks horrible, but trust me, it isn't! Probably!. Armour_quadrant.dm for more info /obj/structure/overmap/proc/relay_damage(proj_type) if(!length(occupying_levels)) diff --git a/nsv13/code/modules/overmap/weapons/mines.dm b/nsv13/code/modules/overmap/weapons/mines.dm new file mode 100644 index 00000000000..d6580916d51 --- /dev/null +++ b/nsv13/code/modules/overmap/weapons/mines.dm @@ -0,0 +1,107 @@ +/obj/structure/space_mine + name = "space mine" + desc = "Like a naval mine, but in space!" + icon = 'nsv13/icons/overmap/effects.dmi' + icon_state = "mine_syndicate" + anchored = TRUE + density = FALSE + layer = ABOVE_MOB_LAYER + animate_movement = NO_STEPS + max_integrity = 300 + integrity_failure = 100 + var/datum/star_system/current_system + var/faction = "syndicate" //evil mines + var/damage = 100 + var/damage_type = BRUTE + var/damage_flag = "overmap_heavy" + alpha = 110 //They're supposed to be sneaky, their main advantage is being cloaked + +/obj/structure/space_mine/Initialize(mapload, var/new_faction, var/datum/star_system/system) + . = ..() + if(system) + current_system = system + else if(!current_system) + for(var/obj/structure/overmap/OM in range(2, src)) //It probably spawned next to a ship + if(OM.current_system) + current_system = OM.current_system + break + if(!current_system) //If an admin spawned you in, it's their job to clean you up. This should never happen normally. + log_runtime("Space mine spawned at x=[x],y=[y],z=[z] with no system or ship nearby!") + if(new_faction) + faction = new_faction + update_icon() + var/static/list/loc_connections = list(COMSIG_ATOM_ENTERED = PROC_REF(on_entered)) + AddElement(/datum/element/connect_loc, loc_connections) + return + current_system.system_contents |= src + if(new_faction) + faction = new_faction + update_icon() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + +/obj/structure/space_mine/Destroy(force) + current_system?.contents_positions.Remove(src) + current_system?.system_contents.Remove(src) + current_system = null + RemoveElement(/datum/element/connect_loc) + . = ..() + +/// This makes us not drift like normal objects in space do +/obj/structure/space_mine/Process_Spacemove(movement_dir = 0) + return 1 + +/obj/structure/space_mine/proc/on_entered(datum/source, atom/movable/AM) + SIGNAL_HANDLER + + if(istype(AM, /obj/item/projectile)) + var/obj/item/projectile/P = AM + if(P.faction != faction) + P.Impact(src) + + if(istype(AM,/obj/structure/overmap)) + var/obj/structure/overmap/OM = AM + if(OM.faction != faction) + mine_explode(OM) + +/obj/structure/space_mine/update_icon(updates) + . = ..() + if(faction) + icon_state = "mine_[faction]" + else + icon_state = "mine_unaligned" + +/obj/structure/space_mine/obj_break(damage_flag) + if(prob(80)) + obj_destruction() + else //Whoops, IFF broke! + faction = "unaligned" + +/obj/structure/space_mine/obj_destruction(damage_flag) + mine_explode() //Why you mine explode? To the woods with you + . = ..() + +/obj/structure/space_mine/proc/mine_explode(obj/structure/overmap/OM) + var/armour_penetration = 0 + if(OM) //You just flew into a mine + armour_penetration = 20 //It's blowing up right next to you, this is what it was designed for + if(OM.use_armour_quadrants) + OM.take_quadrant_hit(OM.run_obj_armor(damage, damage_type, damage_flag, null, armour_penetration), OM.quadrant_impact(src)) + else + OM.take_damage(damage, damage_type, damage_flag, FALSE, TRUE) + if(OM.linked_areas) //Hope nothing precious was in that room. + var/area/A = pick(OM.linked_areas) + var/turf/T = pick(get_area_turfs(A)) + new /obj/effect/temp_visual/explosion_telegraph(T, damage) + else + for(var/obj/structure/overmap/O in orange(2, src)) //You're in range! Keep in mind this affects *all* ships, explosions don't discriminate between friend and foe + OM = O + if(OM.use_armour_quadrants) + OM.take_quadrant_hit(OM.run_obj_armor(damage, damage_type, damage_flag, null, armour_penetration), OM.quadrant_impact(src)) + else + OM.take_damage(damage, damage_type, damage_flag, FALSE, TRUE) + new /obj/effect/temp_visual/fading_overmap(get_turf(src), name, icon, icon_state, alpha) + + diff --git a/nsv13/icons/obj/munition_types.dmi b/nsv13/icons/obj/munition_types.dmi index 01728ca82b7..0ad526cc5c3 100644 Binary files a/nsv13/icons/obj/munition_types.dmi and b/nsv13/icons/obj/munition_types.dmi differ diff --git a/nsv13/icons/overmap/effects.dmi b/nsv13/icons/overmap/effects.dmi index f66b1786142..d82c978f884 100644 Binary files a/nsv13/icons/overmap/effects.dmi and b/nsv13/icons/overmap/effects.dmi differ