Skip to content

Round hailstorm#3

Draft
Shinthoras0815 wants to merge 2 commits intomasterfrom
round-hailstorm
Draft

Round hailstorm#3
Shinthoras0815 wants to merge 2 commits intomasterfrom
round-hailstorm

Conversation

@Shinthoras0815
Copy link
Owner

fire shots in in a round circle with small randomization

fire shots in in a round circle with small randomization
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reworks the ShFL_Hail firing logic so that hailstorm shots are emitted in concentric rings around the firing direction with small randomization, rather than simple random spread around a point.

Changes:

  • Replaces the previous ShFL_Hail loop with ring-based geometry: computing ring count, shots per ring, and per-shot azimuth/polar deviations around angle_xy.
  • Offsets the starting position forward along the firing direction before spawning each projectile, to create a circular “hail” pattern in front of the caster.
  • Adds detailed JUSTLOG debugging for hailstorm setup and each projectile (angles, velocities, and creation status).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3310 to +3337
long ring_count = effect_amount / 6; // Dynamically calculate the number of rings (minimum 1 ring)
if (ring_count < 1) ring_count = 1;
long shots_per_ring = effect_amount / ring_count; // Number of projectiles per ring

shot_set_start_pos(firing, shotst, &pos1);

// Debugging: Log basic values
JUSTLOG("EffectAmount: %ld, RingCount: %ld, ShotsPerRing: %ld",
effect_amount, ring_count, shots_per_ring);

// Calculate offset in the firing direction
struct ComponentVector start_offset;
long forward_distance = 256; // Distance in the firing direction
angles_to_vector(angle_xy, 0, forward_distance, &start_offset);

// Adjust start position by adding the calculated offset
struct Coord3d offset_pos = pos1;
offset_pos.x.val += start_offset.x;
offset_pos.y.val += start_offset.y;
offset_pos.z.val += start_offset.z;

for (i = 1; i <= ring_count; i++) // Loop through the rings
{
long i;
shot_set_start_pos(firing, shotst, &pos1);
for (i = 0; i < shotst->effect_amount; i++)
long current_radius = (max_radius * i) / ring_count; // Radius of the current ring
JUSTLOG("Ring %ld: Current Radius: %ld", i, current_radius);

long azimuth_offset = 1024 / (2 * shots_per_ring);
// Add rotation for every second ring for more randomness
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shots_per_ring can become zero when effect_amount is zero (since ring_count is forced to at least 1), but it is then used as a divisor when computing azimuth_offset (1024 / (2 * shots_per_ring)), which will cause a division-by-zero crash if a Hail shot is ever configured with EffectAmount = 0. Consider guarding against effect_amount <= 0 up front (e.g. early-return or forcing at least one shot) or ensuring shots_per_ring is clamped to at least 1 before it is used in any division.

Copilot uses AI. Check for mistakes.
Comment on lines +3316 to +3393
// Debugging: Log basic values
JUSTLOG("EffectAmount: %ld, RingCount: %ld, ShotsPerRing: %ld",
effect_amount, ring_count, shots_per_ring);

// Calculate offset in the firing direction
struct ComponentVector start_offset;
long forward_distance = 256; // Distance in the firing direction
angles_to_vector(angle_xy, 0, forward_distance, &start_offset);

// Adjust start position by adding the calculated offset
struct Coord3d offset_pos = pos1;
offset_pos.x.val += start_offset.x;
offset_pos.y.val += start_offset.y;
offset_pos.z.val += start_offset.z;

for (i = 1; i <= ring_count; i++) // Loop through the rings
{
long i;
shot_set_start_pos(firing, shotst, &pos1);
for (i = 0; i < shotst->effect_amount; i++)
long current_radius = (max_radius * i) / ring_count; // Radius of the current ring
JUSTLOG("Ring %ld: Current Radius: %ld", i, current_radius);

long azimuth_offset = 1024 / (2 * shots_per_ring);
// Add rotation for every second ring for more randomness
long ring_rotation = (i % 2 == 0) ? (azimuth_offset) : 0;

for (j = 0; j < shots_per_ring; j++) // Loop through the angles
{
if (shotst->speed_deviation)
{
speed = (short)(shotst->speed - (shotst->speed_deviation/2) + (CREATURE_RANDOM(firing, shotst->speed_deviation)));
// Calculate the azimuth angle with optional rotation for the ring
long azimuth_angle = ((1024 * j) / shots_per_ring) + ring_rotation;
azimuth_angle %= 1024; // Ensure the angle stays within 0–1024

long max_deviation = current_radius / 10; // Maximum deviation for spread

// Symmetrical polar angle calculation
long adjusted_angle_xy = angle_xy + ((LbCosL(azimuth_angle) * max_deviation) >> 16);
long adjusted_angle_z = ((LbSinL(azimuth_angle) * max_deviation) >> 16);

// Add random deviation
long random_azimuth_deviation = CREATURE_RANDOM(firing, 20) - 10; // Range: -10 to +10
long random_polar_deviation = CREATURE_RANDOM(firing, 20) - 10; // Range: -10 to +10

adjusted_angle_xy += random_azimuth_deviation;
adjusted_angle_z += random_polar_deviation;

// Ensure symmetry: Invert polar angle for lower half
if (j % 2 == 1) {
adjusted_angle_z = -adjusted_angle_z;
}
else

// Debugging: Log the calculated angles
JUSTLOG("Ring %ld, Shot %ld: Azimuth=%ld, Adjusted XY=%ld, Adjusted Z=%ld, Random Azimuth=%ld, Random Polar=%ld",
i, j, azimuth_angle, adjusted_angle_xy, adjusted_angle_z, random_azimuth_deviation, random_polar_deviation);

// Create a new projectile
struct Coord3d shot_pos = offset_pos;

tmptng = create_thing(&shot_pos, TCls_Shot, shot_model, firing->owner, -1);
if (thing_is_invalid(tmptng))
{
speed = shotst->speed;
JUSTLOG("Failed to create shot %ld,%ld", i, j);
break;
}
tmptng = create_thing(&pos1, TCls_Shot, shot_model, firing->owner, -1);
if (thing_is_invalid(tmptng))
break;

shotng = tmptng;
shotng->shot.hit_type = hit_type;
shotng->move_angle_xy = (short)((angle_xy + CREATURE_RANDOM(firing, 2 * shotst->spread_xy + 1) - shotst->spread_xy) & LbFPMath_AngleMask);
shotng->move_angle_z = (short)((angle_yz + CREATURE_RANDOM(firing, 2 * shotst->spread_z + 1) - shotst->spread_z) & LbFPMath_AngleMask);
angles_to_vector(shotng->move_angle_xy, shotng->move_angle_z, speed, &cvect);

// Set the projectile's direction based on calculated angles
angles_to_vector(adjusted_angle_xy, adjusted_angle_z, shotst->speed, &cvect);
JUSTLOG("Shot %ld,%ld: Adding velocity x=%d, y=%d, z=%d",
i, j, cvect.x, cvect.y, cvect.z);
shotng->veloc_push_add.x.val += cvect.x;
shotng->veloc_push_add.y.val += cvect.y;
shotng->veloc_push_add.z.val += cvect.z;

// Set additional projectile properties
shotng->state_flags |= TF1_PushAdd;
shotng->shot.damage = damage;
shotng->health = shotst->health;
shotng->parent_idx = firing->index;
JUSTLOG("Shot %ld,%ld: Created", i, j);
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple JUSTLOG calls inside the nested Hail loops (for each ring and for each shot), which will generate a very large amount of logging every time this attack is used and can noticeably impact performance and log readability. Since the comments mark these as debugging logs, it would be better to either remove them, guard them with a higher debug level, or wrap them in a conditional so they can be disabled in normal gameplay builds.

Copilot uses AI. Check for mistakes.
Comment on lines +3389 to +3393
// Set additional projectile properties
shotng->state_flags |= TF1_PushAdd;
shotng->shot.damage = damage;
shotng->health = shotst->health;
shotng->parent_idx = firing->index;
JUSTLOG("Shot %ld,%ld: Created", i, j);
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Hail branch creates multiple shots but never sets shotng->parent_idx for them, unlike the Beam/Breathe cases and the default/Volley/Lizard path which all assign the shooter as parent. For Hail shots this leaves parent_idx equal to the shot’s own index, which will break shooter-based logic in thing_shots.c (kill attribution, effects, etc.). To keep Hail consistent and avoid misattribution, set shotng->parent_idx = firing->index for each created projectile inside this loop (or factor out a helper so all fire_logic branches initialize shot parent consistently).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant