Page 1 of 1

[ZScript] Crosshair based on weapon spread

PostPosted: Mon Sep 02, 2019 2:49 pm
by Boondorl
I'm currently trying to implement a crosshair that will adjust itself dynamically to match a weapon's spread (it uses the standard 4 individual lines whose distance widens as the spread gets larger). My weapons are using cone-based spread, so it'll need to be based on a circle instead of a rectangle. The inside edge of the lines mark the furthest point of spread in that direction. One thing I can't figure out is how to get it to actually scale properly e.g. if the weapon's spread range is -2.5 to 2.5 degrees, I need to calculate a radius based off a cone with an opening angle of 5 degrees. What would be the simplest way to do this such that it also scales with the player's FOV?

Re: [ZScript] Crosshair based on weapon spread

PostPosted: Mon Nov 11, 2019 12:44 pm
by Chipper35
I'd love to read the answer to this! Oh: and howdy! I'm new here.

Re: [ZScript] Crosshair based on weapon spread

PostPosted: Mon Nov 11, 2019 1:42 pm
by Jarewill
An incredibly cheap way to do it would be to make a new custom crosshair and change to it in the weapon's select state using A_SetCrosshair.
Example:
Code: Select allExpand view
  Select:
    SHTG A 0 A_SetCrosshair(8);
    SHTG A 1 A_Raise();
    Goto Select+1;

Re: [ZScript] Crosshair based on weapon spread

PostPosted: Tue Nov 12, 2019 3:41 am
by Boondorl
This one works ok but could probably use some optimization:
Code: Select allExpand view
int x1, y1, x2, y2; // x1 = starting x position of virtual window, y1 = starting y position of virtual window, x2 = width of virtual window, y2 = height of virtual window
[x1, y1, x2, y2] = Screen.GetViewWindow();
int width = x2 / 2;
int centerX = x1 + (x2 / 2);
int centerY = y1 + (y2 / 2);
int offset = (rw.zoomed ? rw.zoomSpread : (rw.spread + rw.spreadFactor*rw.bloom)) *  (1. / atan(1. / (width/tan(viewer.player.FOV/2.))));
         
Screen.DrawThickLine(centerX + offset, centerY, centerX + offset + 20, centerY, 3, "FF FF FF"); // DrawThickLine(starting x, starting y, ending x, ending y, thickness of line, color)
Screen.DrawThickLine(centerX - offset, centerY, centerX - offset - 20, centerY, 3, "FF FF FF");
Screen.DrawThickLine(centerX, centerY + offset, centerX, centerY + offset + 20, 3, "FF FF FF");
Screen.DrawThickLine(centerX, centerY - offset, centerX, centerY - offset - 20, 3, "FF FF FF");

rw is the player's ReadyWeapon and and the rest are properties on my custom weapon class that determine how much spread the weapon has. The spread values are stored in terms of angle offset e.g. a value of 2.5 would be a 2.5 degree horizontal and vertical offset. This formula:
Code: Select allExpand view
(1. / atan(1. / (width/tan(viewer.player.FOV/2.))))

is the important part, albeit not very efficient which is why I didn't feel fully comfortable posting the solution. This is taking the player's field of view and using it to get the number of pixels per degree and then multiplying it by the number of degrees in our spread value.