[ZScript] Crosshair based on weapon spread

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

[ZScript] Crosshair based on weapon spread

Postby Boondorl » Mon Sep 02, 2019 2:49 pm

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?
User avatar
Boondorl
 
Joined: 12 Jul 2018

Re: [ZScript] Crosshair based on weapon spread

Postby Chipper35 » Mon Nov 11, 2019 12:44 pm

I'd love to read the answer to this! Oh: and howdy! I'm new here.
Chipper35
 
Joined: 11 Nov 2019
Location: Texas
Operating System: Windows Vista/7 32-bit
OS Test Version: No (Using Stable Public Version)

Re: [ZScript] Crosshair based on weapon spread

Postby Jarewill » Mon Nov 11, 2019 1:42 pm

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;
Jarewill
 
Joined: 21 Jul 2019

Re: [ZScript] Crosshair based on weapon spread

Postby Boondorl » Tue Nov 12, 2019 3:41 am

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.
User avatar
Boondorl
 
Joined: 12 Jul 2018


Return to Scripting

Who is online

Users browsing this forum: Alper002 and 3 guests