NS/main/source/cl_dll/util.cpp
pierow 0e88d368b9 HL25 fixes
-Add new widescreen method and exploit prevention
-disable old widescreen method and exploit prevention
-force sv_rollangle 0
-add sv_widescreenclamp to limit fov expansion to 16:9
2023-11-27 16:01:49 -05:00

344 lines
7.9 KiB
C++

/***
*
* Copyright (c) 1999, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//
// util.cpp
//
// implementation of class-less helper functions
//
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <unordered_map>
#include "hud.h"
#include "cl_util.h"
#include "common/cl_entity.h"
#include <string.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
#include "pm_shared/pm_defs.h"
#include "pm_shared/pm_shared.h"
#include "pm_shared/pm_movevars.h"
extern playermove_t *pmove;
extern float HUD_GetFOV( void );
vec3_t vec3_origin( 0, 0, 0 );
extern vec3_t v_angles;
std::unordered_map<const char*, std::string> LocalizationMap;
//double sqrt(double x);
//
//float Length(const float *v)
//{
// int i;
// float length;
//
// length = 0;
// for (i=0 ; i< 3 ; i++)
// length += v[i]*v[i];
// length = sqrt (length); // FIXME
//
// return length;
//}
//
//void VectorAngles( const float *forward, float *angles )
//{
// float tmp, yaw, pitch;
//
// if (forward[1] == 0 && forward[0] == 0)
// {
// yaw = 0;
// if (forward[2] > 0)
// pitch = 90;
// else
// pitch = 270;
// }
// else
// {
// yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
// if (yaw < 0)
// yaw += 360;
//
// tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);
// pitch = (atan2(forward[2], tmp) * 180 / M_PI);
// if (pitch < 0)
// pitch += 360;
// }
//
// angles[0] = pitch;
// angles[1] = yaw;
// angles[2] = 0;
//}
//
//float VectorNormalize (float *v)
//{
// float length, ilength;
//
// length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
// length = sqrt (length); // FIXME
//
// if (length)
// {
// ilength = 1/length;
// v[0] *= ilength;
// v[1] *= ilength;
// v[2] *= ilength;
// }
//
// return length;
//
//}
//
//void VectorInverse ( float *v )
//{
// v[0] = -v[0];
// v[1] = -v[1];
// v[2] = -v[2];
//}
//
//void VectorScale (const float *in, float scale, float *out)
//{
// out[0] = in[0]*scale;
// out[1] = in[1]*scale;
// out[2] = in[2]*scale;
//}
//
//void VectorMA (const float *veca, float scale, const float *vecb, float *vecc)
//{
// vecc[0] = veca[0] + scale*vecb[0];
// vecc[1] = veca[1] + scale*vecb[1];
// vecc[2] = veca[2] + scale*vecb[2];
//}
int ScreenHeight()
{
// CGC: Replace code when ready to fix overview map
//int theViewport[4];
//gHUD.GetViewport(theViewport);
//return theViewport[3];
return gHUD.m_scrinfo.iHeight;
}
// ScreenWidth returns the width of the screen, in pixels
//#define ScreenWidth ( int theViewport[4]; gHUD.GetViewport(theViewport); return theViewport[2]; )
int ScreenWidth()
{
//int theViewport[4];
//gHUD.GetViewport(theViewport);
//return theViewport[2];
return gHUD.m_scrinfo.iWidth;
}
/*
HSPRITE SPR_Load(const char* inSpriteName)
{
HSPRITE theSpriteHandle = gEngfuncs.pfnSPR_Load(inSpriteName);
// Check for "Can't allocate 128 HUD sprites" crash
ASSERT(theSpriteHandle < 128);
return theSpriteHandle;
}*/
//-----------------------------------------------------------------------------
// Purpose:
// Given a field of view and mouse/screen positions as well as the current
// render origin and angles, returns a unit vector through the mouse position
// that can be used to trace into the world under the mouse click pixel.
// Input : fov -
// mousex -
// mousey -
// screenwidth -
// screenheight -
// vecRenderAngles -
// c_x -
// vpn -
// vup -
// 360.0 -
//-----------------------------------------------------------------------------
void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay )
{
float dx, dy;
float c_x, c_y;
float dist;
Vector vpn, vup, vright;
// char gDebugMessage[256];
//float fovDegrees = gHUD.m_wsFOV;
bool wideScreen = CVAR_GET_FLOAT("gl_widescreen_yfov");
float fovDegrees = gHUD.m_iFOV;
//Adjust for widescreen FOV
if (wideScreen)
{
fovDegrees = atanf(tan(gHUD.m_iFOV * M_PI / 360) * 0.75f * ScreenWidth() / ScreenHeight()) * 360 / M_PI;
}
//cl_entity_s* theLocalEntity = gEngfuncs.GetLocalPlayer();
//Vector vecRenderOrigin = theLocalEntity->origin;
//Vector vecRenderAngles = theLocalEntity->angles;
//Vector vecRenderAngles;
vec3_t vecRenderAngles;
//gEngfuncs.GetViewAngles((float*)vecRenderAngles);
VectorCopy(v_angles, vecRenderAngles);
//vec3_t theForward, theRight, theUp;
//AngleVectors(v_angles, theForward, theRight, theUp);
//ASSERT(v_angles.x == vecRenderAngles.x);
//ASSERT(v_angles.y == vecRenderAngles.y);
//ASSERT(v_angles.z == vecRenderAngles.z);
c_x = ScreenWidth() / 2;
c_y = ScreenHeight() / 2;
dx = (float)mousex - c_x;
// Invert Y
dy = c_y - (float)mousey;
// sprintf(gDebugMessage, "inMouseX/Y: %d/%d, dx/dy = %d/%d", (int)mousex, (int)mousey, (int)dx, (int)dy);
// CenterPrint(gDebugMessage);
// Convert view plane distance
dist = c_x / tan( M_PI * fovDegrees / 360.0 );
// Decompose view angles
AngleVectors( vecRenderAngles, vpn, vright, vup );
// Offset forward by view plane distance, and then by pixel offsets
outVecPickingRay = vpn * dist + vright * ( dx ) + vup * ( dy );
//sprintf(gDebugMessage, "outVecPickingRay: %.0f, %.0f, %.0f", outVecPickingRay.x, outVecPickingRay.y, outVecPickingRay.z);
//CenterPrint(gDebugMessage);
// Convert to unit vector
VectorNormalize( outVecPickingRay );
}
void FillRGBAClipped(vgui::Panel* inPanel, int inStartX, int inStartY, int inWidth, int inHeight, int r, int g, int b, int a)
{
int thePanelXPos, thePanelYPos;
inPanel->getPos(thePanelXPos, thePanelYPos);
int thePanelWidth, thePanelHeight;
inPanel->getSize(thePanelWidth, thePanelHeight);
// Clip starting point
inStartX = min(max(0, inStartX), thePanelWidth-1);
inStartY = min(max(0, inStartY), thePanelHeight-1);
// Clip width if it goes too far
ASSERT(inWidth >= 0);
ASSERT(inHeight >= 0);
if(inStartX + inWidth >= thePanelWidth)
{
inWidth = max(0, thePanelWidth - inStartX);
}
if(inStartY + inHeight >= thePanelHeight)
{
inHeight = max(0, thePanelHeight - inStartY);
}
// Now we can draw
FillRGBA(inStartX, inStartY, inWidth, inHeight, r, g, b, a);
}
AVHHSPRITE LoadSprite(const char *pszName)
{
int i;
char sz[256];
if (ScreenWidth() < 640)
i = 320;
else
i = 640;
sprintf(sz, pszName, i);
return SPR_Load(sz);
}
void FlushLocalization()
{
LocalizationMap.clear();
}
bool LocalizeString(const char* inMessage, string& outputString)
{
#define kMaxLocalizedStringLength 1024
// Don't localize empty strings
if (!strcmp(inMessage, ""))
{
return false;
}
bool theSuccess = false;
char theInputString[kMaxLocalizedStringLength];
char theOutputString[kMaxLocalizedStringLength];
if(*inMessage != '#')
{
sprintf(theInputString, "#%s", inMessage);
}
else
{
sprintf(theInputString, "%s", inMessage);
}
std::unordered_map<const char*, std::string>::const_iterator FoundLocalization = LocalizationMap.find(theInputString);
if (FoundLocalization != LocalizationMap.end())
{
outputString = FoundLocalization->second;
return true;
}
if((CHudTextMessage::LocaliseTextString(theInputString, theOutputString, kMaxLocalizedStringLength) != NULL))
{
outputString = theOutputString;
if(theOutputString[0] != '#')
{
theSuccess = true;
}
else
{
string theTempString = theOutputString;
theTempString = theTempString.substr(1, theTempString.length());
outputString = theTempString;
}
LocalizationMap[inMessage] = outputString;
}
else
{
outputString = string("err: ") + theInputString;
}
return theSuccess;
}