Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Human vs human AA tower #7013

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions code/__DEFINES/__game.dm
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,9 @@
#define TURF_PROTECTION_CAS 2
#define TURF_PROTECTION_OB 3

#define TURF_AA_PROTECTION_CAS_COVERED 4
#define TURF_AA_PROTECTION_CAS_RESTRICTED 5

/// Convert a turf protection level to a ceiling protection level
/proc/get_ceiling_protection_level(turf_protection_level)
switch(turf_protection_level)
Expand Down
27 changes: 27 additions & 0 deletions code/game/machinery/computer/dropship_weapons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@
if(CEILING_IS_PROTECTED(location_area.ceiling, CEILING_PROTECTION_TIER_1))
to_chat(user, SPAN_WARNING("Target is obscured."))
return FALSE
if (!aa_protection_check(location, user))
return FALSE

var/equipment_tag = params["equipment_id"]
for(var/obj/structure/dropship_equipment/equipment as anything in shuttle.equipments)
var/mount_point = equipment.ship_base.attach_id
Expand Down Expand Up @@ -699,6 +702,9 @@
if (protected_by_pylon(TURF_PROTECTION_CAS, TU))
to_chat(weapon_operator, SPAN_WARNING("INVALID TARGET: biological-pattern interference with signal."))
return FALSE

if (!aa_protection_check(TU, weapon_operator))
return FALSE
if(!DEW.ammo_equipped.can_fire_at(TU, weapon_operator))
return FALSE

Expand Down Expand Up @@ -801,6 +807,25 @@
update_location(weapons_operator, cas_sig)
return TRUE

/obj/structure/machinery/computer/dropship_weapons/proc/aa_protection_check(turf/target, mob/weapon_operator)
var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag)
var/obj/structure/machinery/defenses/planetary_anti_air/highest_aa = target.get_aa_with_highest_protection_level(faction)
if (!highest_aa)
return

switch(highest_aa.get_protection_level(target))
if(TURF_AA_PROTECTION_CAS_COVERED)
to_chat(weapon_operator, SPAN_WARNING("WARNING: AA protection persist in area."))
highest_aa.fire()
dropship.on_planetary_aa_interception()
return TRUE
if(TURF_AA_PROTECTION_CAS_RESTRICTED)
to_chat(weapon_operator, SPAN_WARNING("WARNING: strong AA protection persist in area. Perfoming an evasive maneuver"))
highest_aa.fire()
dropship.on_planetary_aa_interception_heavy()
return FALSE
return TRUE

/obj/structure/machinery/computer/dropship_weapons/proc/initiate_firemission(mob/user, fmId, dir, offset_x, offset_y)
set waitfor = 0
var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag)
Expand All @@ -819,6 +844,8 @@
source.y + offset_y,
source.z
)
if (!aa_protection_check(target, user))
return FALSE
var/result = firemission_envelope.execute_firemission(recorded_loc, target, dir, fmId)
if(result != FIRE_MISSION_ALL_GOOD)
to_chat(user, SPAN_WARNING("Screen beeps with an error: [firemission_envelope.mission_error]"))
Expand Down
25 changes: 25 additions & 0 deletions code/game/turfs/turf.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
var/intact_tile = 1 //used by floors to distinguish floor with/without a floortile(e.g. plating).
var/can_bloody = TRUE //Can blood spawn on this turf?
var/list/linked_pylons
var/list/linked_aa
var/obj/effect/alien/weeds/weeds

var/list/datum/automata_cell/autocells
Expand Down Expand Up @@ -386,6 +387,7 @@
// return src

var/pylons = linked_pylons
var/aa_to_copy = linked_aa

var/list/old_baseturfs = baseturfs

Expand Down Expand Up @@ -413,6 +415,7 @@
W.baseturfs = old_baseturfs

W.linked_pylons = pylons
W.linked_aa = aa_to_copy

W.hybrid_lights_affecting = old_hybrid_lights_affecting
W.dynamic_lumcount = dynamic_lumcount
Expand Down Expand Up @@ -732,6 +735,28 @@

return protection_level

/turf/proc/get_aa_with_highest_protection_level(faction)
var/obj/structure/machinery/defenses/planetary_anti_air/highest_aa = null
var/protection_level = TURF_PROTECTION_NONE

for (var/obj/structure/machinery/defenses/planetary_anti_air/planetary_aa in linked_aa)
if (!(faction in planetary_aa.faction_group))
var/protection_lvl = planetary_aa.get_protection_level(src)
if(protection_lvl > protection_level)
protection_level = protection_lvl
highest_aa = planetary_aa
return highest_aa

/turf/proc/get_aa_protection_level(faction)
var/protection_level = TURF_PROTECTION_NONE
for (var/obj/structure/machinery/defenses/planetary_anti_air/planetary_aa in linked_aa)
if (!(faction in planetary_aa.faction_group))
var/protection_lvl = planetary_aa.get_protection_level(src)
if(protection_lvl > protection_level)
protection_level = protection_lvl

return protection_level

GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
/turf/open/space,
/turf/baseturf_bottom,
Expand Down
266 changes: 266 additions & 0 deletions code/modules/defenses/aa_tower.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
#define DROPSIP_TIME_REDUCTION_IF_IN_AA_ZONE 0.9

/obj/structure/machinery/defenses/planetary_anti_air
name = "\improper Planetary AA"
desc = "\improper The Planetary AA provides cover from aerial attacks"
icon = 'icons/obj/structures/machinery/defenses/aa_tower.dmi'
icon_state = ""
can_be_near_defense = TRUE
defense_icon = null
faction_group = FACTION_LIST_MARINE
bound_width = 32
bound_height = 32
pixel_x = -15
pixel_y = -8
hack_time = 300
disassemble_time = 150
health = 500
health_max = 500
anchored = FALSE
placed = FALSE
static = TRUE
encryptable = FALSE
var/luminosity_strength = 2
var/anchor_time = 40

//CAS cant operate in area
var/restricted_range = 20
//CAS can operate but will get some effects
var/covered_range = 40

var/list/linked_turfs_restricted = list()
var/list/linked_turfs_covered = list()

var/last_fired = 0
var/fire_delay = 30

/obj/structure/machinery/defenses/planetary_anti_air/proc/fire()
if(!(world.time - last_fired >= fire_delay) || !turned_on || health <= 0)
return

playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
sleep(3)
visible_message("[icon2html(src, viewers(src))] [SPAN_WARNING("The [name] fires projectiles into air!")]")
playsound(loc, 'sound/weapons/vehicles/autocannon_fire.ogg', 50, 1)
sleep(0.5)
playsound(loc, 'sound/weapons/vehicles/autocannon_fire.ogg', 50, 1)
last_fired = world.time

/obj/structure/machinery/defenses/planetary_anti_air/get_examine_text(mob/user)
var/message = ""
if (health <= 0)
message += "It appears to be completely broken."
return list(message)
if(stat == DEFENSE_DAMAGED)
message += "It does not appear to be working.\n"
if(ishuman(user))
if (FACTION_UPP in faction_group)
message += SPAN_INFO("It is currently allied to [FACTION_UPP].") + "\n"
if (FACTION_MARINE in faction_group)
message += SPAN_INFO("It is currently allied to [FACTION_MARINE].") + "\n"
message += SPAN_INFO("It has [SPAN_HELPFUL("[health]/[health_max]")] health.")
return list(message)

/obj/structure/machinery/defenses/planetary_anti_air/attackby(obj/item/object as obj, mob/user as mob)
if(QDELETED(object))
return

if(HAS_TRAIT(object, TRAIT_TOOL_MULTITOOL))
if(!friendly_faction(user.faction))
to_chat(user, SPAN_WARNING("This doesn't seem safe..."))
var/additional_shock = 1
if(!do_after(user, hack_time * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD, src))
additional_shock++
if(prob(50))
var/mob/living/carbon/human/user_human = user
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_NOVICE))
if(turned_on)
additional_shock++
user_human.electrocute_act(40, src, additional_shock)//god damn Hans...
setDir(get_dir(src, user_human))//Make sure he died
power_off()
power_on()
return
else
user_human.electrocute_act(20, src)//god bless him for stupid move
return
if(additional_shock >= 2)
return
LAZYCLEARLIST(faction_group)
for(var/i in user.faction_group)
LAZYADD(faction_group, i)
to_chat(user, SPAN_WARNING("You've hacked \the [src], it's now ours!"))
return

if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_NOVICE))
to_chat(user, SPAN_WARNING("You don't have the training to do this."))
return

if(static)
to_chat(user, SPAN_WARNING("\The [src] is bolted to the ground!"))
return

user.visible_message(SPAN_NOTICE("[user] begins disassembling \the [src]."), SPAN_NOTICE("You begin disassembling \the [src]."))

if(!do_after(user, disassemble_time * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD, src))
return

if(health < health_max * 0.25) //repeat check
to_chat(user, SPAN_WARNING("\The [src] is too damaged to pick up!"))
return

user.visible_message(SPAN_NOTICE("[user] disassembles [src]."), SPAN_NOTICE("You disassemble [src]."))

playsound(loc, 'sound/mecha/mechmove04.ogg', 30, 1)
var/turf/turf_under_aa = get_turf(src)
power_off()
HD.forceMove(turf_under_aa)
transfer_label_component(HD)
HD.dropped = 1
HD.update_icon()
placed = 0
forceMove(HD)

return

if(HAS_TRAIT(object, TRAIT_TOOL_WRENCH))
if(anchored)
if(turned_on)
to_chat(user, SPAN_WARNING("[src] is currently active. You need to deactivate it first."))
return
user.visible_message(SPAN_NOTICE("[user] begins unanchoring [src] from the ground."),
SPAN_NOTICE("You begin unanchoring [src] from the ground."))

if(!do_after(user, anchor_time * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD, src))
return
user.visible_message(SPAN_NOTICE("[user] unanchors [src] from the ground."),
SPAN_NOTICE("You unanchor [src] from the ground."))
anchored = FALSE
playsound(loc, 'sound/items/Ratchet.ogg', 25, 1)
return
else
var/turf/turf_under_aa = get_turf(src)
var/area/area = get_area(turf_under_aa)
if(CEILING_IS_PROTECTED(area.ceiling, CEILING_PROTECTION_TIER_1) || !is_ground_level(turf_under_aa.z))
to_chat(user, SPAN_RED("You realize how bad of an idea this is and quickly stop."))
return

var/turf/open/floor = get_turf(src)
if(!floor.allow_construction)
to_chat(user, SPAN_WARNING("You cannot secure \the [src] here, find a more secure surface!"))
return FALSE
user.visible_message(SPAN_NOTICE("[user] begins securing [src] to the ground."),
SPAN_NOTICE("You begin securing [src] to the ground."))

if(!do_after(user, anchor_time * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD, src))
return
user.visible_message(SPAN_NOTICE("[user] secures [src] to the ground."),
SPAN_NOTICE("You secure [src] to the ground."))
anchored = TRUE
playsound(loc, 'sound/items/Ratchet.ogg', 25, 1)
return

if(iswelder(object))
if(!HAS_TRAIT(object, TRAIT_TOOL_BLOWTORCH))
to_chat(user, SPAN_WARNING("You need a stronger blowtorch!"))
return
var/obj/item/tool/weldingtool/WT = object
if(health < 0)
to_chat(user, SPAN_WARNING("[src]'s internal circuitry is ruined, there's no way you can salvage this on the go."))
return

if(health >= health_max)
to_chat(user, SPAN_WARNING("[src] isn't in need of repairs."))
return

if(WT.remove_fuel(0, user))
user.visible_message(SPAN_NOTICE("[user] begins repairing [src]."),
SPAN_NOTICE("You begin repairing [src]."))
if(do_after(user, 40 * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_FRIENDLY, src))
user.visible_message(SPAN_NOTICE("[user] repairs [src]."),
SPAN_NOTICE("You repair [src]."))
if(stat == DEFENSE_DAMAGED)
stat &= ~DEFENSE_DAMAGED
update_health(-50)
playsound(loc, 'sound/items/Welder2.ogg', 25, 1)
return
return

return TRUE

/obj/structure/machinery/defenses/planetary_anti_air/update_icon()
if(turned_on)
if (FACTION_UPP in faction_group)
icon_state = "aa_upp"
else
icon_state = "aa_uscm"
else if(health <= 0)
icon_state = "aa_destroyed"
else
icon_state = "aa_off"

/obj/structure/machinery/defenses/planetary_anti_air/upp
icon = 'icons/obj/structures/machinery/defenses/aa_tower.dmi'
icon_state = "aa_upp"
faction_group = FACTION_LIST_UPP

/obj/structure/machinery/defenses/planetary_anti_air/proc/get_protection_level(turf/turf_to_check)
if (turf_to_check in linked_turfs_restricted)
return TURF_AA_PROTECTION_CAS_RESTRICTED
if (turf_to_check in linked_turfs_covered)
return TURF_AA_PROTECTION_CAS_COVERED
return TURF_PROTECTION_NONE

/obj/structure/machinery/defenses/planetary_anti_air/power_on_action(mob/user)
var/turf/turf_under_aa = get_turf(src)
var/area/area = get_area(turf_under_aa)

if(CEILING_IS_PROTECTED(area.ceiling, CEILING_PROTECTION_TIER_1))
to_chat(user, SPAN_RED("[name] must be in the open air."))
return
if(!is_ground_level(turf_under_aa.z))
to_chat(user, SPAN_RED("You realize how bad of an idea this is and quickly stop."))
return

set_light(luminosity_strength)
visible_message("[icon2html(src, viewers(src))] [SPAN_NOTICE("The [name] hums to life and emits several beeps.")]")

for(var/turf/turf_in_big_range as anything in RANGE_TURFS(covered_range, loc))
LAZYADD(turf_in_big_range.linked_aa, src)
linked_turfs_covered += turf_in_big_range
for(var/turf/turf_in_close_range as anything in RANGE_TURFS(restricted_range, loc))
linked_turfs_restricted += turf_in_close_range

/obj/structure/machinery/defenses/planetary_anti_air/proc/remove_protected_area()
for(var/turf/turf_in_big_range as anything in RANGE_TURFS(covered_range, loc))
LAZYREMOVE(turf_in_big_range.linked_aa, src)
linked_turfs_covered -= turf_in_big_range
for(var/turf/turf_in_close_range as anything in RANGE_TURFS(restricted_range, loc))
linked_turfs_restricted -= turf_in_close_range

/obj/structure/machinery/defenses/planetary_anti_air/power_off_action(mob/user)
set_light(0)
visible_message("[icon2html(src, viewers(src))] [SPAN_NOTICE("The [name] powers down and goes silent.")]")
remove_protected_area()

/obj/structure/machinery/defenses/planetary_anti_air/Destroy()
remove_protected_area()
update_icon()
. = ..()

/obj/structure/machinery/defenses/planetary_anti_air/destroyed_action()
remove_protected_area()
visible_message("[icon2html(src, viewers(src))] [SPAN_WARNING("The [name] starts spitting out sparks and smoke!")]")
playsound(loc, 'sound/mecha/critdestrsyndi.ogg', 25, 1)
sleep(10)
cell_explosion(loc, 20, 20, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, create_cause_data("AA tower explosion"))
update_icon()

/obj/structure/machinery/defenses/planetary_anti_air/damaged_action(damage)
if(health < health_max * 0.15)
visible_message(SPAN_DANGER("[icon2html(src, viewers(src))] The [name] cracks and breaks apart!"))
stat |= DEFENSE_DAMAGED
turned_on = FALSE
remove_protected_area()
set_light(0)
update_icon()
Loading
Loading