[b20b] Breath attacks are asymmetric

Where bugs go to lie down and rest

Moderator: Moderator

Post Reply
Message
Author
Nagyhal
Wyrmic
Posts: 282
Joined: Tue Feb 15, 2011 12:01 am

[b20b] Breath attacks are asymmetric

#1 Post by Nagyhal »

Compare the two:

Image

When using my wyrmic's breath to attack foes that are adjacent, I can hit a full row of three if they are standing to the east or west, but only one if they are to the north or south.

This is has serious tactical consequences—and ugly ones, as it enforces an overly game-y response on the part of the player! It's something I run into a lot if I am attacking from a doorway, and often have to kit the foes back and into a horizontal orientation so that I can attack them all with a consecutive Fire Breath and a Death Dance, or whatever I'm trying to do.

Now, this raises the question—which design is the intended one? I favour the second in my image, as being able to hit multiple adjacent opponents with a breath attack isn't all that broken; you can, in most cases, easily run back a bit and shoot the same number of enemies from within a corridor, it just takes more time and, to me, reeks of a pathetic cowardice—hardly fitting for a barbarian warmaster who who seethes with the fury of dragons!

I'll let the community make the final call, though.

Godot
Low Yeek
Posts: 5
Joined: Sat Feb 19, 2011 8:41 am

Re: [b20b] Breath attacks are asymmetric

#2 Post by Godot »

Id rather have the one starting with 3. Wyrmics lack some melee aoes.

tiger_eye
Perspiring Physicist
Posts: 889
Joined: Thu Feb 17, 2011 5:20 am

Re: [b20b] Breath attacks are asymmetric

#3 Post by tiger_eye »

I'll field this one and I'll post a solution, so actual developers please take note! :)

To answer your question, the second image (more spots targeted) is correct. "But why aren't the north-south breath attacks like this," you ask? Well, as implemented, the cartesian plane is divided into eight Octants, and only half the octants are capable of displaying diagonals or north-south, east-west edges. This prevents double-counting. However, it is also responsible for the asymmetry that you found--and how I never notice that before, I have no idea!

I posted the main corrected file as an attachment "fov.c".

I want to cover a couple other issues I found while looking through this section of the code...

You may have noticed that the cardinal directions are brighter than the rest of the targeted area. This is, obviously, because the green targeting image is applied twice. But wait! I just said the asymmetry you noticed is because the algorithm avoids double-counting! What's going on, then? Well, the core algorithm works (mostly) correctly, but it calls the wrong functions that do the wrong things at the wrong times. Basically, when it calls a function that is supposed to check whether a specific location is obscured (or blocked) or not, this function does this as well as performing an action on that location. This, as I see it, is just plain wrong. There is a separate function that is intended to perform that action on a location as needed, but this function often does nothing at all. I'll use the cone breath as an example, but this issue occurs elsewhere(!!!!!!!!!!!!!!!).

From "game/engines/default/engine/Target.lua:display" (near line 118)

Code: Select all

       elseif self.target_type.cone and self.target_type.cone > 0 then
                core.fov.calc_beam(
                        radius_x,
                        radius_y,
                        game.level.map.w, 
                        game.level.map.h, 
                        self.target_type.cone, 
                        initial_dir, 
                        self.target_type.cone_angle, 
                        function(_, px, py)
                                self.sg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom,
                                        self.display_y + (py - game.level.map.my) * self.tile_h * Map.zoom,
                                        self.tile_w * Map.zoom,
                                        self.tile_h * Map.zoom)
                                if self.target_type.block_radius and self.target_type:block_radius(px, py) then return true end
                        end,
                        function()end,
                        nil)
        end
should be

Code: Select all

        elseif self.target_type.cone and self.target_type.cone > 0 then
                core.fov.calc_beam(
                        radius_x,
                        radius_y,
                        game.level.map.w,
                        game.level.map.h,
                        self.target_type.cone,
                        initial_dir,
                        self.target_type.cone_angle,
                        function(_, px, py)
                                if self.target_type.block_radius and self.target_type:block_radius(px, py) then return true end
                        end,
                        function(_, px, py)
                                self.sg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom,
                                self.display_y + (py - game.level.map.my) * self.tile_h * Map.zoom,
                                self.tile_w * Map.zoom,
                                self.tile_h * Map.zoom)
                        end,
                        nil)
        end
The third-to-last argument is the function intended to check if a location is blocked. The second to last argument is the function to perform an action on that location, but here it was defined as "function()end"--doing nothing! Using the code I provided prevents the extra-highlighted lines in cardinal directions.

Another issue is that the cone (aka beam) algorithm doesn't work correctly if the angle is less than 45 degrees (which it isn't right now in the game, but it could be in principle). This is a straightforward fix in "src/fov/fov.c:FOV_DEFINE_OCTANT" (near line 221), change

Code: Select all

        if (!apply_diag && dy1 == dx) {                                                         \
            /* We do diagonal lines on every second octant, so they don't get done twice. */    \
            --dy1;                                                                              \
        }  
to

Code: Select all

        if (!apply_diag && dy1 == dx) {                                                         \
            /* We do diagonal lines on every second octant, so they don't get done twice. */    \
            --dy1;                                                                              \
                                                                                                \
            /* But, we still need to check if we can see past it if the slopes are similar */   \
            if (dy1 < dy0) {                                                                    \
                if (settings->opaque(data->map, x, y)) {                                        \
                    return;                                                                     \
                }                                                                               \
                prev_blocked = 0;                                                               \
            }                                                                                   \
        }  
I made several more changes to this file (and these functions), so you should probably just download the attached "fov.c" file if you're a developer.

Here are examples I made using these corrections. No more asymmetry! No more lines!
cut_west.png
cut_west.png (176.22 KiB) Viewed 2534 times
cut_south.png
cut_south.png (138.08 KiB) Viewed 2534 times
Attachments
fov.c
(20.58 KiB) Downloaded 153 times
darkgod wrote:OMFG tiger eye you are my hero!

yufra
Perspiring Physicist
Posts: 1332
Joined: Tue Jul 13, 2010 2:53 pm

Re: [b20b] Breath attacks are asymmetric

#4 Post by yufra »

Whoah, thanks tiger_eye! You should stop by IRC, but be warned you may never leave. :wink:
<DarkGod> lets say it's intended

tiger_eye
Perspiring Physicist
Posts: 889
Joined: Thu Feb 17, 2011 5:20 am

Re: [b20b] Breath attacks are asymmetric

#5 Post by tiger_eye »

8)

darkgod
Master of Eyal
Posts: 10750
Joined: Wed Jul 24, 2002 9:26 pm
Location: Angolwen
Contact:

Re: [b20b] Breath attacks are asymmetric

#6 Post by darkgod »

Yes indeed big thanks, and do come over on irc :)
[tome] joylove: You can't just release an expansion like one would release a Kraken XD
--
[tome] phantomfrettchen: your ability not to tease anyone is simply stunning ;)

Nagyhal
Wyrmic
Posts: 282
Joined: Tue Feb 15, 2011 12:01 am

Re: [b20b] Breath attacks are asymmetric

#7 Post by Nagyhal »

tiger_eye posted:
[A whole lotta awesome]
Thank you dearly.

I shall study the changes you made and strive to learn from your wise deeds.

tiger_eye
Perspiring Physicist
Posts: 889
Joined: Thu Feb 17, 2011 5:20 am

Re: [b20b] Breath attacks are asymmetric

#8 Post by tiger_eye »

Be careful, though, you may get dizzy while looking at all the MACRO awesomeness in "fov/fov.c" :wink:
Let me know if you have any other thoughts or questions about my changes.

yufra
Perspiring Physicist
Posts: 1332
Joined: Tue Jul 13, 2010 2:53 pm

Re: [b20b] Breath attacks are asymmetric

#9 Post by yufra »

tiger_eye wrote:Be careful, though, you may get dizzy while looking at all the MACRO awesomeness in "fov/fov.c" :wink:
The quadrant macro definitions is indeed awesome. :wink:
<DarkGod> lets say it's intended

Post Reply