Skip to content

Commit

Permalink
Projectiles reorganization and cleanup, impact effects, subtle EMP tw…
Browse files Browse the repository at this point in the history
…eaks (#6741)

No gameplay changes except for EMP rebalancing.

Emps are now deterministic
Ion rifles now always hit for strength 2 instead of a probability tree
of strengths
EMP damage slightly lessened as this makes a lot of things guaranteed to
hit with strength 2 instead of 3
  • Loading branch information
silicons authored Sep 13, 2024
1 parent a61ad42 commit 16c07e9
Show file tree
Hide file tree
Showing 49 changed files with 1,259 additions and 1,273 deletions.
29 changes: 17 additions & 12 deletions citadel.dme
Original file line number Diff line number Diff line change
Expand Up @@ -4485,33 +4485,38 @@
#include "code\modules\projectiles\guns\projectile\sniper.dm"
#include "code\modules\projectiles\guns\projectile\caseless\pellet.dm"
#include "code\modules\projectiles\guns\projectile\sniper\collapsible_sniper.dm"
#include "code\modules\projectiles\projectile\arc.dm"
#include "code\modules\projectiles\projectile\helpers.dm"
#include "code\modules\projectiles\projectile\projectile-hitscan_visuals.dm"
#include "code\modules\projectiles\projectile\projectile-physics.dm"
#include "code\modules\projectiles\projectile\projectile-tracing.dm"
#include "code\modules\projectiles\projectile\projectile.dm"
#include "code\modules\projectiles\projectile\projectile_effect.dm"
#include "code\modules\projectiles\projectile\projectile_effect\detonation.dm"
#include "code\modules\projectiles\projectile\projectile_effect\detonation\legacy_emp.dm"
#include "code\modules\projectiles\projectile\projectile_effect\detonation\legacy_explosion.dm"
#include "code\modules\projectiles\projectile\subtypes\arc.dm"
#include "code\modules\projectiles\projectile\subtypes\blob.dm"
#include "code\modules\projectiles\projectile\subtypes\beam.dm"
#include "code\modules\projectiles\projectile\subtypes\bullets.dm"
#include "code\modules\projectiles\projectile\subtypes\bullets_vr.dm"
#include "code\modules\projectiles\projectile\subtypes\change.dm"
#include "code\modules\projectiles\projectile\subtypes\energy.dm"
#include "code\modules\projectiles\projectile\subtypes\energy_vr.dm"
#include "code\modules\projectiles\projectile\subtypes\explosive.dm"
#include "code\modules\projectiles\projectile\subtypes\force.dm"
#include "code\modules\projectiles\projectile\subtypes\hook.dm"
#include "code\modules\projectiles\projectile\subtypes\magic.dm"
#include "code\modules\projectiles\projectile\subtypes\magnetic.dm"
#include "code\modules\projectiles\projectile\subtypes\forcebolt.dm"
#include "code\modules\projectiles\projectile\subtypes\ion.dm"
#include "code\modules\projectiles\projectile\subtypes\pellet.dm"
#include "code\modules\projectiles\projectile\subtypes\reusable.dm"
#include "code\modules\projectiles\projectile\subtypes\scatter.dm"
#include "code\modules\projectiles\projectile\subtypes\special.dm"
#include "code\modules\projectiles\projectile\subtypes\trace.dm"
#include "code\modules\projectiles\projectile\subtypes\unsorted.dm"
#include "code\modules\projectiles\projectile\subtypes\arc\arc.dm"
#include "code\modules\projectiles\projectile\subtypes\beam\beams.dm"
#include "code\modules\projectiles\projectile\subtypes\beam\beams_vr.dm"
#include "code\modules\projectiles\projectile\subtypes\beam\blaster.dm"
#include "code\modules\projectiles\projectile\subtypes\bullet\bullets.dm"
#include "code\modules\projectiles\projectile\subtypes\bullet\bullets_vr.dm"
#include "code\modules\projectiles\projectile\subtypes\bullet\magnetic.dm"
#include "code\modules\projectiles\projectile\subtypes\bullet\reusable.dm"
#include "code\modules\projectiles\projectile\subtypes\bullet\srmrocket.dm"
#include "code\modules\projectiles\projectile\subtypes\energy\blob.dm"
#include "code\modules\projectiles\projectile\subtypes\energy\energy.dm"
#include "code\modules\projectiles\projectile\subtypes\energy\energy_vr.dm"
#include "code\modules\projectiles\projectile\subtypes\energy\hook.dm"
#include "code\modules\projectiles\targeting\targeting_client.dm"
#include "code\modules\projectiles\targeting\targeting_gun.dm"
#include "code\modules\projectiles\targeting\targeting_mob.dm"
Expand Down
3 changes: 2 additions & 1 deletion code/game/atoms/defense_old.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
/atom/proc/legacy_ex_act(severity, target)
set waitfor = FALSE

/atom/proc/emp_act(var/severity)
/atom/proc/emp_act(severity)
SHOULD_NOT_SLEEP(TRUE)
// todo: SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity)

Expand Down
3 changes: 0 additions & 3 deletions code/game/machinery/turrets/subtypes/lasertag.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
if(get_dist(src, L) > 7) //if it's too far away, why bother?
return TURRET_NOT_TARGET

if(!(L in check_trajectory(L, src))) //check if we have true line of sight
return TURRET_NOT_TARGET

if(L.lying) //Don't need to stun-lock the players
return TURRET_NOT_TARGET

Expand Down
3 changes: 2 additions & 1 deletion code/game/machinery/turrets/turret-ai_holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@
/datum/ai_holder/turret/proc/trace_trajectory(atom/target, angle)
var/obj/projectile/trace/trace = new(agent.loc)
trace.only_opacity = TRUE
trace.prepare_trace(target)
if(!trace.prepare_trace(target))
return FALSE
trace.fire(angle)
return trace.could_hit_target

Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/virtual_reality/vr_console.dm
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
visible_message("<span class='danger'>\The [src]'s internal lighting flashes rapidly, before the hatch swings open with a cloud of smoke.</span>")
smoke.set_up(severity, 0, src)
smoke.start("#202020")
go_out()
INVOKE_ASYNC(src, PROC_REF(go_out))

..(severity)

Expand Down
51 changes: 15 additions & 36 deletions code/game/objects/empulse.dm
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
// Uncomment this define to check for possible lengthy processing of emp_act()s.
// If emp_act() takes more than defined deciseconds (1/10 seconds) an admin message and log is created.
// I do not recommend having this uncommented on main server, it probably causes a bit more lag, espicially with larger EMPs.

// #define EMPDEBUG 10

/proc/empulse(turf/epicenter, first_range, second_range, third_range, fourth_range, log = FALSE)
/**
* Legacy EMP pulses
*
* Ranges are starting at 1 for 1x1, so 0 = don't affect.
*/
/proc/empulse(turf/epicenter, first_range, second_range, third_range, fourth_range, log = TRUE, message_admins = FALSE)
if(!epicenter)
return

if(!istype(epicenter, /turf))
epicenter = get_turf(epicenter.loc)

if(log)
if(message_admins)
message_admins("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")

if(first_range > 1)
var/obj/effect/overlay/pulse = new /obj/effect/overlay(epicenter)
Expand All @@ -24,52 +23,32 @@
spawn(20)
qdel(pulse)

// expand ranges
if(first_range > second_range)
second_range = first_range
if(second_range > third_range)
third_range = second_range
if(third_range > fourth_range)
fourth_range = third_range

for(var/mob/M in range(first_range, epicenter))
// this is dumb but whatever
for(var/mob/M in range(fourth_range - 1, epicenter))
SEND_SOUND(M, sound('sound/effects/EMPulse.ogg'))

for(var/atom/T in range(fourth_range, epicenter))
#ifdef EMPDEBUG
var/time = world.timeofday
#endif
for(var/atom/T in range(fourth_range - 1, epicenter))
var/distance = get_dist(epicenter, T)
if(distance < 0)
distance = 0
//Worst effects, really hurts
if(distance < first_range)
T.emp_act(1)
else if(distance == first_range)
if(prob(50))
T.emp_act(1)
else
T.emp_act(2)
//Slightly less painful
else if(distance <= second_range)
else if(distance < second_range)
T.emp_act(2)
else if(distance == second_range)
if(prob(50))
T.emp_act(2)
else
T.emp_act(3)
//Even less slightly less painful
else if(distance <= third_range)
else if(distance < third_range)
T.emp_act(3)
else if(distance == third_range)
if(prob(50))
T.emp_act(2)
else
T.emp_act(3)
//This should be more or less harmless
else if(distance <= fourth_range)
else if(distance < fourth_range)
T.emp_act(4)
#ifdef EMPDEBUG
if((world.timeofday - time) >= EMPDEBUG)
log_and_message_admins("EMPDEBUG: [T.name] - [T.type] - took [world.timeofday - time]ds to process emp_act()!")
#endif
return 1
2 changes: 1 addition & 1 deletion code/game/objects/explosion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, playsound_local), epicenter, null, rand(25, 40), 1, frequency, null, null, FALSE, 'sound/effects/creak1.ogg', null, null, null, null, 0), 5 SECONDS)
if(adminlog)
message_admins("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
log_game("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
log_game("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")

var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
Expand Down
58 changes: 30 additions & 28 deletions code/game/objects/items/weapons/implants/implant.dm
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ Implant Specifics:<BR>"}
switch(severity)
if(1)
if(prob(60))
meltdown()
INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/item/implant, meltdown))
if(2)
delay = rand(5*60*10,15*60*10) //from 5 to 15 minutes of free time
if(3)
Expand Down Expand Up @@ -294,31 +294,32 @@ Implant Specifics:<BR>"}
if (malfunction)
return
malfunction = MALFUNCTION_TEMPORARY
switch (severity)
if (4) //Weak EMP will make implant tear limbs off.
if (prob(25))
small_boom()
if (3) //Weak EMP will make implant tear limbs off.
if (prob(50))
small_boom()
if (2) //strong EMP will melt implant either making it go off, or disarming it
if (prob(70))
if (prob(75))
spawn(-1)
switch (severity)
if (4) //Weak EMP will make implant tear limbs off.
if (prob(25))
small_boom()
else
if (prob(13))
activate() //chance of bye bye
else
meltdown() //chance of implant disarming
if (1) //strong EMP will melt implant either making it go off, or disarming it
if (prob(70))
if (3) //Weak EMP will make implant tear limbs off.
if (prob(50))
small_boom()
else
if (2) //strong EMP will melt implant either making it go off, or disarming it
if (prob(70))
if (prob(75))
small_boom()
else
if (prob(13))
activate() //chance of bye bye
else
meltdown() //chance of implant disarming
if (1) //strong EMP will melt implant either making it go off, or disarming it
if (prob(70))
if (prob(50))
activate() //50% chance of bye bye
small_boom()
else
meltdown() //50% chance of implant disarming
if (prob(50))
activate() //50% chance of bye bye
else
meltdown() //50% chance of implant disarming
spawn (20)
malfunction--

Expand Down Expand Up @@ -538,13 +539,14 @@ the implant may become unstable and either pre-maturely inject the subject or si
return
malfunction = MALFUNCTION_TEMPORARY

activate("emp") //let's shout that this dude is dead
if(severity == 1)
if(prob(40)) //small chance of obvious meltdown
meltdown()
else if (prob(60)) //but more likely it will just quietly die
malfunction = MALFUNCTION_PERMANENT
STOP_PROCESSING(SSobj, src)
spawn(-1)
activate("emp") //let's shout that this dude is dead
if(severity == 1)
if(prob(40)) //small chance of obvious meltdown
meltdown()
else if (prob(60)) //but more likely it will just quietly die
malfunction = MALFUNCTION_PERMANENT
STOP_PROCESSING(SSobj, src)

spawn(20)
malfunction--
Expand Down
65 changes: 33 additions & 32 deletions code/game/objects/items/weapons/implants/neuralbasic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -57,39 +57,40 @@ Implant Specifics:<BR>"}
return
malfunction = MALFUNCTION_TEMPORARY

var/delay = 10 //Don't let it just get emped twice in a second to kill someone.
var/brain_location = my_brain.owner.organs_by_name[my_brain.parent_organ]
var/mob/living/L = my_brain.owner
switch(severity)
if(1)
if(prob(10))
meltdown()
else if(prob(80))
my_brain.take_damage(5)
if(!robotic_brain)
to_chat(L, "<span class='critical'>Something in your [brain_location] burns!</span>")
else
to_chat(L, "<span class='warning'>Severe fault detected in [brain_location].</span>")
if(2)
if(prob(80))
my_brain.take_damage(3)
if(!robotic_brain)
to_chat(L, "<span class='danger'>It feels like something is digging into your [brain_location]!</span>")
else
to_chat(L, "<span class='warning'>Fault detected in [brain_location].</span>")
if(3)
if(prob(60))
my_brain.take_damage(2)
if(!robotic_brain)
to_chat(L, "<span class='warning'>There is a stabbing pain in your [brain_location]!</span>")
if(4)
if(prob(40))
my_brain.take_damage(1)
if(!robotic_brain)
to_chat(L, "<span class='warning'>Your [brain_location] aches.</span>")
spawn(-1)
var/delay = 10 //Don't let it just get emped twice in a second to kill someone.
var/brain_location = my_brain.owner.organs_by_name[my_brain.parent_organ]
var/mob/living/L = my_brain.owner
switch(severity)
if(1)
if(prob(10))
meltdown()
else if(prob(80))
my_brain.take_damage(5)
if(!robotic_brain)
to_chat(L, "<span class='critical'>Something in your [brain_location] burns!</span>")
else
to_chat(L, "<span class='warning'>Severe fault detected in [brain_location].</span>")
if(2)
if(prob(80))
my_brain.take_damage(3)
if(!robotic_brain)
to_chat(L, "<span class='danger'>It feels like something is digging into your [brain_location]!</span>")
else
to_chat(L, "<span class='warning'>Fault detected in [brain_location].</span>")
if(3)
if(prob(60))
my_brain.take_damage(2)
if(!robotic_brain)
to_chat(L, "<span class='warning'>There is a stabbing pain in your [brain_location]!</span>")
if(4)
if(prob(40))
my_brain.take_damage(1)
if(!robotic_brain)
to_chat(L, "<span class='warning'>Your [brain_location] aches.</span>")

spawn(delay)
malfunction--
spawn(delay)
malfunction--

/obj/item/implant/neural/meltdown()
..()
Expand Down
8 changes: 7 additions & 1 deletion code/modules/ai/holders/polaris/ai_holder_combat.dm
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@

// This will hold a list of all mobs in a line, even those behind the target, and possibly the wall.
// By default the test projectile goes through things like glass and grilles, which is desirable as otherwise the AI won't try to shoot through windows.
var/list/hit_things = check_trajectory(AM, holder) // This isn't always reliable but its better than the previous method.
var/list/hit_things

if(isturf(holder.loc))
var/obj/projectile/trace/trace_projectile = new(holder.loc)
trace_projectile.prepare_trace(AM, TRUE)
trace_projectile.fire()
hit_things = trace_projectile.scanned_atoms

// Test to see if the primary target actually has a chance to get hit.
// We'll fire anyways if not, if we have conserve_ammo turned off.
Expand Down
12 changes: 3 additions & 9 deletions code/modules/mob/living/silicon/pai/defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,12 @@

/mob/living/silicon/pai/emp_act(severity)
// Silence for 2 minutes
// 20% chance to kill
// 33% chance to unbind
// 33% chance to change prime directive (based on severity)
// 33% chance of no additional effect
// 33% chance to unbind
// 33% chance to change prime directive (based on severity)
// 33% chance of no additional effect

src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes
to_chat(src, "<font color=green><b>Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete.</b></font>")
if(prob(20))
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("<font color='red'>A shower of sparks spray from [src]'s inner workings.</font>", 3, "<font color='red'>You hear and smell the ozone hiss of electrical sparks being expelled violently.</font>", 2)
return src.death(0)

switch(pick(1,2,3))
if(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
/// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components
/obj/item/modular_computer/emp_act(severity)
. = ..()
take_damage_legacy(rand(100,200) / severity, 50 / severity, 0)
spawn(-1)
take_damage_legacy(rand(100,200) / severity, 50 / severity, 0)

/**
* "Stun" weapons can cause minor damage to components (short-circuits?)
Expand Down
Loading

0 comments on commit 16c07e9

Please sign in to comment.