Skip to content

Commit

Permalink
you can now use the mortar during hijack if you are not a coward + cu…
Browse files Browse the repository at this point in the history
…stom shell warning for ghosts (#5940)

# About the pull request
lets you deploy the mortar shipside.
lets you fire a shell on a shipside mortar during hijack but do not
expect to live.

ghosts now get a warning when an OT shell is about to land. (I did not
test this and I don't know how to, I just copy pasted from CAS fire
missions)

# Explain why it's good for the game
its funny and cool and soul

# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>


https://github.com/cmss13-devs/cmss13/assets/140007537/c7f7dcb2-98d1-438c-ba00-6a57f5ad9463



https://github.com/cmss13-devs/cmss13/assets/140007537/8862d7e1-cda9-4fda-9c2b-7b5c105fe3e0


Put screenshots and videos here with an empty line between the
screenshots and the `<details>` tags.

</details>


# Changelog
:cl:
balance: You can now use the mortar while shipside during hijack, but
only once.
add: Ghosts now get a warning when a custom mortar shell is about to
land.
/:cl:
  • Loading branch information
iloveloopers committed Mar 29, 2024
1 parent 76794fd commit 052c09a
Showing 1 changed file with 114 additions and 85 deletions.
199 changes: 114 additions & 85 deletions code/modules/cm_marines/equipment/mortar/mortars.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
var/firing = FALSE
/// If set to 1, can't unanchor and move the mortar, used for map spawns and WO
var/fixed = FALSE
/// if true, blows up the shell immediately
var/ship_side = FALSE

var/obj/structure/machinery/computer/cameras/mortar/internal_camera

Expand All @@ -56,28 +58,28 @@
else
return FALSE

/obj/structure/mortar/attack_alien(mob/living/carbon/xenomorph/M)
if(islarva(M))
/obj/structure/mortar/attack_alien(mob/living/carbon/xenomorph/xeno)
if(islarva(xeno))
return XENO_NO_DELAY_ACTION

if(fixed)
to_chat(M, SPAN_XENOWARNING("\The [src]'s supports are bolted and welded into the floor. It looks like it's going to be staying there."))
to_chat(xeno, SPAN_XENOWARNING("\The [src]'s supports are bolted and welded into the floor. It looks like it's going to be staying there."))
return XENO_NO_DELAY_ACTION

if(firing)
M.animation_attack_on(src)
M.flick_attack_overlay(src, "slash")
xeno.animation_attack_on(src)
xeno.flick_attack_overlay(src, "slash")
playsound(src, "acid_hit", 25, 1)
playsound(M, "alien_help", 25, 1)
M.apply_damage(10, BURN)
M.visible_message(SPAN_DANGER("[M] tried to knock the steaming hot [src] over, but burned itself and pulled away!"),
playsound(xeno, "alien_help", 25, 1)
xeno.apply_damage(10, BURN)
xeno.visible_message(SPAN_DANGER("[xeno] tried to knock the steaming hot [src] over, but burned itself and pulled away!"),
SPAN_XENOWARNING("\The [src] is burning hot! Wait a few seconds."))
return XENO_ATTACK_ACTION

M.visible_message(SPAN_DANGER("[M] lashes at \the [src] and knocks it over!"),
xeno.visible_message(SPAN_DANGER("[xeno] lashes at \the [src] and knocks it over!"),
SPAN_DANGER("You knock \the [src] over!"))
M.animation_attack_on(src)
M.flick_attack_overlay(src, "slash")
xeno.animation_attack_on(src)
xeno.flick_attack_overlay(src, "slash")
playsound(loc, 'sound/effects/metalhit.ogg', 25)
var/obj/item/mortar_kit/MK = new /obj/item/mortar_kit(loc)
MK.name = name
Expand Down Expand Up @@ -206,40 +208,47 @@

SStgui.update_uis(src)

/obj/structure/mortar/attackby(obj/item/O, mob/user)
if(istype(O, /obj/item/mortar_shell))
var/obj/item/mortar_shell/mortar_shell = O
/obj/structure/mortar/attackby(obj/item/item, mob/user)
if(istype(item, /obj/item/mortar_shell))
var/obj/item/mortar_shell/mortar_shell = item
var/turf/turf = locate(targ_x + dial_x + offset_x, targ_y + dial_y + offset_y, z)
var/area/area = get_area(turf)
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_TRAINED))
to_chat(user, SPAN_WARNING("You don't have the training to fire [src]."))
return
if(busy)
to_chat(user, SPAN_WARNING("Someone else is currently using [src]."))
return
if(!is_ground_level(z))
to_chat(user, SPAN_WARNING("You cannot fire [src] here."))
return
if(targ_x == 0 && targ_y == 0) //Mortar wasn't set
to_chat(user, SPAN_WARNING("[src] needs to be aimed first."))
return
var/turf/T = locate(targ_x + dial_x + offset_x, targ_y + dial_y + offset_y, z)
if(!T)
to_chat(user, SPAN_WARNING("You cannot fire [src] to this target."))
return
var/area/A = get_area(T)
if(!istype(A))
to_chat(user, SPAN_WARNING("This area is out of bounds!"))
return
if(CEILING_IS_PROTECTED(A.ceiling, CEILING_PROTECTION_TIER_2) || protected_by_pylon(TURF_PROTECTION_MORTAR, T))
to_chat(user, SPAN_WARNING("You cannot hit the target. It is probably underground."))
return
if(SSticker.mode && MODE_HAS_TOGGLEABLE_FLAG(MODE_LZ_PROTECTION) && A.is_landing_zone)
to_chat(user, SPAN_WARNING("You cannot bomb the landing zone!"))
return

//Small amount of spread so that consecutive mortar shells don't all land on the same tile
var/turf/T1 = locate(T.x + pick(-1,0,0,1), T.y + pick(-1,0,0,1), T.z)
if(T1)
T = T1
if(!ship_side)
if(targ_x == 0 && targ_y == 0) //Mortar wasn't set
to_chat(user, SPAN_WARNING("[src] needs to be aimed first."))
return
if(!turf)
to_chat(user, SPAN_WARNING("You cannot fire [src] to this target."))
return
if(!istype(area))
to_chat(user, SPAN_WARNING("This area is out of bounds!"))
return
if(CEILING_IS_PROTECTED(area.ceiling, CEILING_PROTECTION_TIER_2) || protected_by_pylon(TURF_PROTECTION_MORTAR, turf))
to_chat(user, SPAN_WARNING("You cannot hit the target. It is probably underground."))
return
if(SSticker.mode && MODE_HAS_TOGGLEABLE_FLAG(MODE_LZ_PROTECTION) && area.is_landing_zone)
to_chat(user, SPAN_WARNING("You cannot bomb the landing zone!"))
return

if(!ship_side)
var/turf/T1 = locate(turf.x + pick(-1,0,0,1), turf.y + pick(-1,0,0,1), turf.z) //Small amount of spread so that consecutive mortar shells don't all land on the same tile
if(T1)
turf = T1
else
var/crash_occurred = (SSticker?.mode?.is_in_endgame)
if(crash_occurred)
var/turf/our_turf = get_turf(src)
turf = our_turf
travel_time = 0.5 SECONDS
else
to_chat(user, SPAN_RED("You realize how bad of an idea this is and quickly stop."))
return

user.visible_message(SPAN_NOTICE("[user] starts loading \a [mortar_shell.name] into [src]."),
SPAN_NOTICE("You start loading \a [mortar_shell.name] into [src]."))
Expand All @@ -259,15 +268,15 @@
mortar_shell.cause_data = create_cause_data(initial(mortar_shell.name), user, src)
mortar_shell.forceMove(src)

var/turf/G = get_turf(src)
G.ceiling_debris_check(2)
var/turf/hit_turf = get_turf(src)
hit_turf.ceiling_debris_check(2)

for(var/mob/M in range(7))
shake_camera(M, 3, 1)
for(var/mob/mob in range(7))
shake_camera(mob, 3, 1)

addtimer(CALLBACK(src, PROC_REF(handle_shell), T, mortar_shell), travel_time)
addtimer(CALLBACK(src, PROC_REF(handle_shell), hit_turf, mortar_shell), travel_time)

if(HAS_TRAIT(O, TRAIT_TOOL_WRENCH))
if(HAS_TRAIT(item, TRAIT_TOOL_WRENCH))
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_TRAINED))
to_chat(user, SPAN_WARNING("You don't have the training to undeploy [src]."))
return
Expand All @@ -287,11 +296,11 @@
user.visible_message(SPAN_NOTICE("[user] undeploys [src]."), \
SPAN_NOTICE("You undeploy [src]."))
playsound(loc, 'sound/items/Deconstruct.ogg', 25, 1)
var/obj/item/mortar_kit/M = new /obj/item/mortar_kit(loc)
M.name = src.name
var/obj/item/mortar_kit/mortar = new /obj/item/mortar_kit(loc)
mortar.name = src.name
qdel(src)

if(HAS_TRAIT(O, TRAIT_TOOL_SCREWDRIVER))
if(HAS_TRAIT(item, TRAIT_TOOL_SCREWDRIVER))
if(do_after(user, 1 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
user.visible_message(SPAN_NOTICE("[user] toggles the targeting computer on [src]."), \
SPAN_NOTICE("You toggle the targeting computer on [src]."))
Expand All @@ -303,41 +312,59 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
qdel(src)

/obj/effect/mortar_effect
icon = 'icons/obj/structures/mortar.dmi'
icon_state = "mortar_ammo_custom"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_MAXIMUM

/obj/structure/mortar/proc/handle_shell(turf/target, obj/item/mortar_shell/shell)
if(protected_by_pylon(TURF_PROTECTION_MORTAR, target))
firing = FALSE
return

playsound(target, 'sound/weapons/gun_mortar_travel.ogg', 50, 1)
var/relative_dir
for(var/mob/M in range(15, target))
if(get_turf(M) == target)
relative_dir = 0
else
relative_dir = Get_Compass_Dir(M, target)
M.show_message( \
SPAN_DANGER("A SHELL IS COMING DOWN [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
SPAN_DANGER("YOU HEAR SOMETHING COMING DOWN [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
)
sleep(2.5 SECONDS) // Sleep a bit to give a message
for(var/mob/M in range(10, target))
if(get_turf(M) == target)
relative_dir = 0
else
relative_dir = Get_Compass_Dir(M, target)
M.show_message( \
SPAN_HIGHDANGER("A SHELL IS ABOUT TO IMPACT [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
SPAN_HIGHDANGER("YOU HEAR SOMETHING VERY CLOSE COMING DOWN [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
)
sleep(2 SECONDS) // Wait out the rest of the landing time
target.ceiling_debris_check(2)
if(!protected_by_pylon(TURF_PROTECTION_MORTAR, target))
shell.detonate(target)
qdel(shell)
firing = FALSE
if(ship_side)
var/turf/our_turf = get_turf(src)
shell.detonate(our_turf)
else
if(istype(shell, /obj/item/mortar_shell/custom)) // big shell warning for ghosts
var/obj/effect/effect = new /obj/effect/mortar_effect(target)
QDEL_IN(effect, 5 SECONDS)
notify_ghosts(header = "Custom Shell", message = "A custom mortar shell is about to land at [get_area(target)].", source = effect)

playsound(target, 'sound/weapons/gun_mortar_travel.ogg', 50, 1)
var/relative_dir
for(var/mob/mob in range(15, target))
if(get_turf(mob) == target)
relative_dir = 0
else
relative_dir = Get_Compass_Dir(mob, target)
mob.show_message( \
SPAN_DANGER("A SHELL IS COMING DOWN [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
SPAN_DANGER("YOU HEAR SOMETHING COMING DOWN [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
)
sleep(2.5 SECONDS) // Sleep a bit to give a message
for(var/mob/mob in range(10, target))
if(get_turf(mob) == target)
relative_dir = 0
else
relative_dir = Get_Compass_Dir(mob, target)
mob.show_message( \
SPAN_HIGHDANGER("A SHELL IS ABOUT TO IMPACT [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
SPAN_HIGHDANGER("YOU HEAR SOMETHING VERY CLOSE COMING DOWN [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
)
sleep(2 SECONDS) // Wait out the rest of the landing time
target.ceiling_debris_check(2)
if(!protected_by_pylon(TURF_PROTECTION_MORTAR, target))
shell.detonate(target)
qdel(shell)
firing = FALSE

/obj/structure/mortar/proc/can_fire_at(mob/user, test_targ_x = targ_x, test_targ_y = targ_y, test_dial_x, test_dial_y)
var/dialing = test_dial_x || test_dial_y
if(ship_side)
to_chat(user, SPAN_WARNING("You cannot aim the mortar while on a ship."))
return FALSE
if(test_dial_x + test_targ_x > world.maxx || test_dial_x + test_targ_x < 0)
to_chat(user, SPAN_WARNING("You cannot [dialing ? "dial to" : "aim at"] this coordinate, it is outside of the area of operations."))
return FALSE
Expand Down Expand Up @@ -385,21 +412,23 @@
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_TRAINED))
to_chat(user, SPAN_WARNING("You don't have the training to deploy [src]."))
return
if(!is_ground_level(deploy_turf.z))
to_chat(user, SPAN_WARNING("You cannot deploy [src] here."))
return
var/area/A = get_area(deploy_turf)
if(CEILING_IS_PROTECTED(A.ceiling, CEILING_PROTECTION_TIER_1))
var/area/area = get_area(deploy_turf)
if(CEILING_IS_PROTECTED(area.ceiling, CEILING_PROTECTION_TIER_1) && is_ground_level(deploy_turf.z))
to_chat(user, SPAN_WARNING("You probably shouldn't deploy [src] indoors."))
return
user.visible_message(SPAN_NOTICE("[user] starts deploying [src]."), \
SPAN_NOTICE("You start deploying [src]."))
playsound(deploy_turf, 'sound/items/Deconstruct.ogg', 25, 1)
if(do_after(user, 4 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
user.visible_message(SPAN_NOTICE("[user] deploys [src]."), \
SPAN_NOTICE("You deploy [src]."))
var/obj/structure/mortar/mortar = new /obj/structure/mortar(deploy_turf)
if(!is_ground_level(deploy_turf.z))
mortar.ship_side = TRUE
user.visible_message(SPAN_NOTICE("[user] deploys [src]."), \
SPAN_NOTICE("You deploy [src]. This is a bad idea."))
else
user.visible_message(SPAN_NOTICE("[user] deploys [src]."), \
SPAN_NOTICE("You deploy [src]."))
playsound(deploy_turf, 'sound/weapons/gun_mortar_unpack.ogg', 25, 1)
var/obj/structure/mortar/M = new /obj/structure/mortar(deploy_turf)
M.name = src.name
M.setDir(user.dir)
mortar.name = src.name
mortar.setDir(user.dir)
qdel(src)

0 comments on commit 052c09a

Please sign in to comment.