Merge pull request #3803 from shawns-valve/master

SDK changes to match Half-Life 25th Anniversary update
This commit is contained in:
shawns-valve 2024-08-26 22:41:28 -07:00 committed by GitHub
commit b59688c56d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
359 changed files with 44526 additions and 24224 deletions

View file

@ -1,7 +1,7 @@
Half Life 1 SDK LICENSE Half Life 1 SDK LICENSE
====================== ======================
Half Life 1 SDK Copyright© Valve Corp. Half Life 1 SDK Copyright © Valve Corp.
THIS DOCUMENT DESCRIBES A CONTRACT BETWEEN YOU AND VALVE CORPORATION (“Valve”). PLEASE READ IT BEFORE DOWNLOADING OR USING THE HALF LIFE 1 SDK (“SDK”). BY DOWNLOADING AND/OR USING THE SOURCE ENGINE SDK YOU ACCEPT THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE PLEASE DONT DOWNLOAD OR USE THE SDK. THIS DOCUMENT DESCRIBES A CONTRACT BETWEEN YOU AND VALVE CORPORATION (“Valve”). PLEASE READ IT BEFORE DOWNLOADING OR USING THE HALF LIFE 1 SDK (“SDK”). BY DOWNLOADING AND/OR USING THE SOURCE ENGINE SDK YOU ACCEPT THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE PLEASE DONT DOWNLOAD OR USE THE SDK.
@ -37,7 +37,7 @@ If it has not been reported, create a new issue with at least the following info
- a detailed description of the issue, including any output from the command line; - a detailed description of the issue, including any output from the command line;
- steps for reproducing the issue; - steps for reproducing the issue;
- your system information.\*; and - your system information.\*; and
- the `version` output from the ingame console. - the `version` output from the in-game console.
Please place logs either in a code block (press `M` in your browser for a GFM cheat sheet) or a [gist](https://gist.github.com). Please place logs either in a code block (press `M` in your browser for a GFM cheat sheet) or a [gist](https://gist.github.com).
@ -55,3 +55,13 @@ There are basic rules of conduct that should be followed at all times by everyon
- Do not repeatedly update an open issue remarking that the issue persists. - Do not repeatedly update an open issue remarking that the issue persists.
Remember: Just because the issue you reported was reported here does not mean that it is an issue with Half-Life. As well, should your issue not be resolved immediately, it does not mean that a resolution is not being researched or tested. Patience is always appreciated. Remember: Just because the issue you reported was reported here does not mean that it is an issue with Half-Life. As well, should your issue not be resolved immediately, it does not mean that a resolution is not being researched or tested. Patience is always appreciated.
Building the SDK code
-------
Visual Studio 2019 is required to build mod DLLs on Windows. In the Visual Studio installer, install "Desktop development with C++" under "Workloads" and "C++ MFC for latest v142 build tools (x86 & x64)" under "Individual components". VS2019 projects can be found in the `projects\vs2019` folder.
Tools have not yet been updated for VS2019, but can be built using the VS2010 projects in the `projects\vs2010` folder. See the `readme.txt` file there.
Linux binaries are built using Makefiles found in the `linux` folder, and are expected to be built / run in the Steam Runtime "scout" environment. You will need to set the environment variables VALVE_NO_AUTO_P4=1 and USE_STEAM_RUNTIME=1 while building.

View file

@ -74,10 +74,15 @@ void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon )
{ {
int i, iRes; int i, iRes;
if (ScreenWidth < 640)
iRes = 320; if (ScreenWidth > 2560 && ScreenHeight > 1600)
else iRes = 2560;
else if (ScreenWidth >= 1280 && ScreenHeight > 720)
iRes = 1280;
else if (ScreenWidth >= 640)
iRes = 640; iRes = 640;
else
iRes = 320;
char sz[128]; char sz[128];
@ -325,16 +330,17 @@ int CHudAmmo::VidInit(void)
// If we've already loaded weapons, let's get new sprites // If we've already loaded weapons, let's get new sprites
gWR.LoadAllWeaponSprites(); gWR.LoadAllWeaponSprites();
if (ScreenWidth >= 640) int nScale = 1;
{
giABWidth = 20; if (ScreenWidth > 2560 && ScreenHeight > 1600)
giABHeight = 4; nScale = 4;
} else if (ScreenWidth >= 1280 && ScreenHeight > 720)
else nScale = 3;
{ else if (ScreenWidth >= 640)
giABWidth = 10; nScale = 2;
giABHeight = 2;
} giABWidth = 10 * nScale;
giABHeight = 2 * nScale;
return 1; return 1;
} }
@ -641,7 +647,9 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
WEAPON Weapon; WEAPON Weapon;
strcpy( Weapon.szName, READ_STRING() ); strncpy( Weapon.szName, READ_STRING(), MAX_WEAPON_NAME );
Weapon.szName[ sizeof(Weapon.szName) - 1 ] = '\0';
Weapon.iAmmoType = (int)READ_CHAR(); Weapon.iAmmoType = (int)READ_CHAR();
Weapon.iMax1 = READ_BYTE(); Weapon.iMax1 = READ_BYTE();
@ -659,6 +667,27 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
Weapon.iFlags = READ_BYTE(); Weapon.iFlags = READ_BYTE();
Weapon.iClip = 0; Weapon.iClip = 0;
if (Weapon.iId < 0 || Weapon.iId >= MAX_WEAPONS)
return 0;
if (Weapon.iSlot < 0 || Weapon.iSlot >= MAX_WEAPON_SLOTS+1)
return 0;
if (Weapon.iSlotPos < 0 || Weapon.iSlotPos >= MAX_WEAPON_POSITIONS+1)
return 0;
if (Weapon.iAmmoType < -1 || Weapon.iAmmoType >= MAX_AMMO_TYPES)
return 0;
if (Weapon.iAmmo2Type < -1 || Weapon.iAmmo2Type >= MAX_AMMO_TYPES)
return 0;
if (Weapon.iAmmoType >= 0 && Weapon.iMax1 == 0)
return 0;
if (Weapon.iAmmo2Type >= 0 && Weapon.iMax2 == 0)
return 0;
gWR.AddWeapon( &Weapon ); gWR.AddWeapon( &Weapon );
return 1; return 1;
@ -862,7 +891,7 @@ int CHudAmmo::Draw(float flTime)
AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
a = (int) max( MIN_ALPHA, m_fFade ); a = max<int>( MIN_ALPHA, m_fFade );
if (m_fFade > 0) if (m_fFade > 0)
m_fFade -= (gHUD.m_flTimeDelta * 20); m_fFade -= (gHUD.m_flTimeDelta * 20);
@ -871,8 +900,8 @@ int CHudAmmo::Draw(float flTime)
ScaleColors(r, g, b, a ); ScaleColors(r, g, b, a );
// Does this weapon have a clip?
y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2; y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2;
y += (int)(gHUD.m_iFontHeight * 0.2f);
// Does weapon have any ammo at all? // Does weapon have any ammo at all?
if (m_pWeapon->iAmmoType > 0) if (m_pWeapon->iAmmoType > 0)
@ -1191,7 +1220,7 @@ client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes
while(i--) while(i--)
{ {
if ((!strcmp(psz, p->szName)) && (p->iRes == iRes)) if ((p->iRes == iRes) && (!strcmp(psz, p->szName)))
return p; return p;
p++; p++;
} }

View file

@ -61,7 +61,7 @@ int CHudAmmoSecondary :: Draw(float flTime)
// draw secondary ammo icons above normal ammo readout // draw secondary ammo icons above normal ammo readout
int a, x, y, r, g, b, AmmoWidth; int a, x, y, r, g, b, AmmoWidth;
UnpackRGB( r, g, b, RGB_YELLOWISH ); UnpackRGB( r, g, b, RGB_YELLOWISH );
a = (int) max( MIN_ALPHA, m_fFade ); a = max<int>( MIN_ALPHA, m_fFade );
if (m_fFade > 0) if (m_fFade > 0)
m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons
ScaleColors( r, g, b, a ); ScaleColors( r, g, b, a );

View file

@ -126,11 +126,11 @@ int HistoryResource :: DrawAmmoHistory( float flTime )
int r, g, b; int r, g, b;
UnpackRGB(r,g,b, RGB_YELLOWISH); UnpackRGB(r,g,b, RGB_YELLOWISH);
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
ScaleColors(r, g, b, min(scale, 255) ); ScaleColors(r, g, b, min<int>(scale, 255) );
// Draw the pic // Draw the pic
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
int xpos = ScreenWidth - 24; int xpos = ScreenWidth - (rcPic.right - rcPic.left) - 4;
if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic
{ // the dll has to make sure it has sent info the weapons you need { // the dll has to make sure it has sent info the weapons you need
SPR_Set( *spr, r, g, b ); SPR_Set( *spr, r, g, b );
@ -154,7 +154,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime )
UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
ScaleColors(r, g, b, min(scale, 255) ); ScaleColors(r, g, b, min<int>(scale, 255) );
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left);
@ -172,7 +172,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime )
UnpackRGB(r,g,b, RGB_YELLOWISH); UnpackRGB(r,g,b, RGB_YELLOWISH);
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
ScaleColors(r, g, b, min(scale, 255) ); ScaleColors(r, g, b, min<int>(scale, 255) );
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
int xpos = ScreenWidth - (rect.right - rect.left) - 10; int xpos = ScreenWidth - (rect.right - rect.left) - 10;

View file

@ -134,7 +134,11 @@ int CHudBattery::Draw(float flTime)
int iOffset = (m_prc1->bottom - m_prc1->top)/6; int iOffset = (m_prc1->bottom - m_prc1->top)/6;
y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
x = ScreenWidth/5;
int width = (m_prc1->right - m_prc1->left);
// this used to just be ScreenWidth/5 but that caused real issues at higher resolutions. Instead, base it on the width of this sprite.
x = 3 * width;
// make sure we have the right sprite handles // make sure we have the right sprite handles
if ( !m_hSprite1 ) if ( !m_hSprite1 )
@ -151,7 +155,8 @@ int CHudBattery::Draw(float flTime)
SPR_DrawAdditive( 0, x, y - iOffset + (rc.top - m_prc2->top), &rc); SPR_DrawAdditive( 0, x, y - iOffset + (rc.top - m_prc2->top), &rc);
} }
x += (m_prc1->right - m_prc1->left); x += width;
y += (int)(gHUD.m_iFontHeight * 0.2f);
x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b); x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b);
return 1; return 1;

View file

@ -1,648 +0,0 @@
# Microsoft Developer Studio Project File - Name="cl_dll" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=cl_dll - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "cl_dll.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "cl_dll.mak" CFG="cl_dll - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "cl_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "cl_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "cl_dll - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Release"
# PROP Intermediate_Dir ".\Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /W3 /GR /GX /Zi /O2 /I "..\dlls" /I "." /I "..\tfc" /I "..\public" /I "..\common" /I "..\pm_shared" /I "..\engine" /I "..\utils\vgui\include" /I "..\game_shared" /I "..\external" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "CLIENT_DLL" /D "CLIENT_WEAPONS" /D "HL_DLL" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ..\utils\vgui\lib\win32_vc6\vgui.lib wsock32.lib ..\lib\public\sdl2.lib /nologo /base:"0x01900000" /subsystem:windows /dll /map /debug /machine:I386 /nodefaultlib:"LIBCMTD" /nodefaultlib:"LIBCD" /out:".\Release\client.dll"
# SUBTRACT LINK32 /pdb:none
# Begin Custom Build
InputDir=.\Release
ProjDir=.
InputPath=.\Release\client.dll
InputName=client
SOURCE="$(InputPath)"
BuildCmds= \
call ..\filecopy.bat $(InputDir)\$(InputName).dll $(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).dll \
call ..\filecopy.bat $(InputDir)\$(InputName).pdb $(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).pdb \
"$(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).pdb" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "cl_dll - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Debug"
# PROP BASE Intermediate_Dir ".\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GR /GX /ZI /Od /I "..\dlls" /I "." /I "..\tfc" /I "..\public" /I "..\common" /I "..\pm_shared" /I "..\engine" /I "..\utils\vgui\include" /I "..\game_shared" /I "..\external" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "CLIENT_DLL" /D "CLIENT_WEAPONS" /D "_WINDLL" /D "HL_DLL" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ..\utils\vgui\lib\win32_vc6\vgui.lib wsock32.lib ..\lib\public\sdl2.lib /nologo /base:"0x01900000" /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\client.dll"
# SUBTRACT LINK32 /pdb:none
# Begin Custom Build
InputDir=.\Debug
ProjDir=.
InputPath=.\Debug\client.dll
InputName=client
SOURCE="$(InputPath)"
BuildCmds= \
call ..\filecopy.bat $(InputDir)\$(InputName).dll $(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).dll \
call ..\filecopy.bat $(InputDir)\$(InputName).pdb $(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).pdb \
"$(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(ProjDir)\..\..\game\mod\cl_dlls\$(InputName).pdb" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ENDIF
# Begin Target
# Name "cl_dll - Win32 Release"
# Name "cl_dll - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
# Begin Group "hl"
# PROP Default_Filter "*.cpp"
# Begin Source File
SOURCE=..\dlls\crossbow.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\crowbar.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\egon.cpp
# End Source File
# Begin Source File
SOURCE=.\ev_hldm.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\gauss.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\handgrenade.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_baseentity.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_events.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_objects.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_weapons.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\wpn_shared\hl_wpn_glock.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\hornetgun.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\mp5.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\python.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\rpg.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\satchel.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\shotgun.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\squeakgrenade.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\tripmine.cpp
# End Source File
# End Group
# Begin Source File
SOURCE=.\ammo.cpp
# End Source File
# Begin Source File
SOURCE=.\ammo_secondary.cpp
# End Source File
# Begin Source File
SOURCE=.\ammohistory.cpp
# End Source File
# Begin Source File
SOURCE=.\battery.cpp
# End Source File
# Begin Source File
SOURCE=.\cdll_int.cpp
# End Source File
# Begin Source File
SOURCE=.\com_weapons.cpp
# End Source File
# Begin Source File
SOURCE=.\death.cpp
# End Source File
# Begin Source File
SOURCE=.\demo.cpp
# End Source File
# Begin Source File
SOURCE=.\entity.cpp
!IF "$(CFG)" == "cl_dll - Win32 Release"
!ELSEIF "$(CFG)" == "cl_dll - Win32 Debug"
# ADD CPP /MT
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\ev_common.cpp
# End Source File
# Begin Source File
SOURCE=.\events.cpp
# End Source File
# Begin Source File
SOURCE=.\flashlight.cpp
# End Source File
# Begin Source File
SOURCE=.\GameStudioModelRenderer.cpp
# End Source File
# Begin Source File
SOURCE=.\geiger.cpp
# End Source File
# Begin Source File
SOURCE=.\health.cpp
# End Source File
# Begin Source File
SOURCE=.\hud.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_bench.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_benchtrace.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_msg.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_redraw.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_servers.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_spectator.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_update.cpp
# End Source File
# Begin Source File
SOURCE=.\in_camera.cpp
# End Source File
# Begin Source File
SOURCE=.\input.cpp
# End Source File
# Begin Source File
SOURCE=.\inputw32.cpp
# End Source File
# Begin Source File
SOURCE=..\public\interface.cpp
# End Source File
# Begin Source File
SOURCE=.\interpolation.cpp
# End Source File
# Begin Source File
SOURCE=.\menu.cpp
# End Source File
# Begin Source File
SOURCE=.\message.cpp
# End Source File
# Begin Source File
SOURCE=..\common\parsemsg.cpp
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_debug.c
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_math.c
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_shared.c
# End Source File
# Begin Source File
SOURCE=.\saytext.cpp
# End Source File
# Begin Source File
SOURCE=.\status_icons.cpp
# End Source File
# Begin Source File
SOURCE=.\statusbar.cpp
# End Source File
# Begin Source File
SOURCE=.\studio_util.cpp
# End Source File
# Begin Source File
SOURCE=.\StudioModelRenderer.cpp
# End Source File
# Begin Source File
SOURCE=.\text_message.cpp
# End Source File
# Begin Source File
SOURCE=.\train.cpp
# End Source File
# Begin Source File
SOURCE=.\tri.cpp
# End Source File
# Begin Source File
SOURCE=.\util.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_checkbutton2.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ClassMenu.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ControlConfigPanel.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_CustomObjects.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_grid.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_helpers.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_int.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_listbox.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_loadtga.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_MOTDWindow.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_SchemeManager.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ScorePanel.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_scrollbar2.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ServerBrowser.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_slider2.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_SpectatorPanel.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_TeamFortressViewport.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_TeamMenu.cpp
# End Source File
# Begin Source File
SOURCE=.\view.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_banmgr.cpp
# End Source File
# Begin Source File
SOURCE=.\voice_status.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\ammo.h
# End Source File
# Begin Source File
SOURCE=.\ammohistory.h
# End Source File
# Begin Source File
SOURCE=.\camera.h
# End Source File
# Begin Source File
SOURCE=.\cl_dll.h
# End Source File
# Begin Source File
SOURCE=.\cl_util.h
# End Source File
# Begin Source File
SOURCE=.\com_weapons.h
# End Source File
# Begin Source File
SOURCE=.\demo.h
# End Source File
# Begin Source File
SOURCE=.\ev_hldm.h
# End Source File
# Begin Source File
SOURCE=.\eventscripts.h
# End Source File
# Begin Source File
SOURCE=.\GameStudioModelRenderer.h
# End Source File
# Begin Source File
SOURCE=.\health.h
# End Source File
# Begin Source File
SOURCE=.\hud.h
# End Source File
# Begin Source File
SOURCE=.\hud_servers.h
# End Source File
# Begin Source File
SOURCE=.\hud_servers_priv.h
# End Source File
# Begin Source File
SOURCE=.\hud_spectator.h
# End Source File
# Begin Source File
SOURCE=.\in_defs.h
# End Source File
# Begin Source File
SOURCE=.\interpolation.h
# End Source File
# Begin Source File
SOURCE=.\kbutton.h
# End Source File
# Begin Source File
SOURCE=..\common\parsemsg.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_debug.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_defs.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_info.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_materials.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_movevars.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_shared.h
# End Source File
# Begin Source File
SOURCE=.\StudioModelRenderer.h
# End Source File
# Begin Source File
SOURCE=.\tri.h
# End Source File
# Begin Source File
SOURCE=.\util_vector.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ControlConfigPanel.h
# End Source File
# Begin Source File
SOURCE=.\vgui_int.h
# End Source File
# Begin Source File
SOURCE=.\vgui_SchemeManager.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ScorePanel.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_scrollbar2.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ServerBrowser.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_slider2.h
# End Source File
# Begin Source File
SOURCE=.\vgui_SpectatorPanel.h
# End Source File
# Begin Source File
SOURCE=.\view.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_banmgr.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_status.h
# End Source File
# Begin Source File
SOURCE=.\wrect.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=..\lib\public\game_controls.lib
# End Source File
# End Target
# End Project

View file

@ -83,6 +83,7 @@ inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int fl
#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) #define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
#define ServerCmd (*gEngfuncs.pfnServerCmd) #define ServerCmd (*gEngfuncs.pfnServerCmd)
#define EngineClientCmd (*gEngfuncs.pfnClientCmd) #define EngineClientCmd (*gEngfuncs.pfnClientCmd)
#define EngineFilteredClientCmd (*gEngfuncs.pfnFilteredClientCmd)
#define SetCrosshair (*gEngfuncs.pfnSetCrosshair) #define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
#define AngleVectors (*gEngfuncs.pfnAngleVectors) #define AngleVectors (*gEngfuncs.pfnAngleVectors)
@ -162,8 +163,6 @@ inline int safe_sprintf( char *dst, int len_dst, const char *format, ...)
inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); } inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); }
inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); } inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); }
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define fabs(x) ((x) > 0 ? (x) : 0 - (x)) #define fabs(x) ((x) > 0 ? (x) : 0 - (x))
void ScaleColors( int &r, int &g, int &b, int a ); void ScaleColors( int &r, int &g, int &b, int a );

View file

@ -73,7 +73,7 @@ int CHudDeathNotice :: Init( void )
HOOK_MESSAGE( DeathMsg ); HOOK_MESSAGE( DeathMsg );
CVAR_CREATE( "hud_deathnotice_time", "6", 0 ); CVAR_CREATE( "hud_deathnotice_time", "6", FCVAR_ARCHIVE );
return 1; return 1;
} }
@ -94,7 +94,12 @@ int CHudDeathNotice :: VidInit( void )
int CHudDeathNotice :: Draw( float flTime ) int CHudDeathNotice :: Draw( float flTime )
{ {
int x, y, r, g, b; int x, y, r, g, b, texty;
int gap = 20;
wrect_t& sprite = gHUD.GetSpriteRect(m_HUD_d_skull);
gap = sprite.bottom - sprite.top;
for ( int i = 0; i < MAX_DEATHNOTICES; i++ ) for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
{ {
@ -115,10 +120,12 @@ int CHudDeathNotice :: Draw( float flTime )
if ( gViewPort && gViewPort->AllowedToPrintText() ) if ( gViewPort && gViewPort->AllowedToPrintText() )
{ {
// Draw the death notice // Draw the death notice
y = DEATHNOTICE_TOP + 2 + (20 * i); //!!! y = DEATHNOTICE_TOP + 2 + (gap * i);
texty = y + 4;
int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId; int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left); x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left) - 4;
if ( !rgDeathNoticeList[i].iSuicide ) if ( !rgDeathNoticeList[i].iSuicide )
{ {
@ -127,7 +134,7 @@ int CHudDeathNotice :: Draw( float flTime )
// Draw killers name // Draw killers name
if ( rgDeathNoticeList[i].KillerColor ) if ( rgDeathNoticeList[i].KillerColor )
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] ); gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller ); x = 5 + DrawConsoleString( x, texty, rgDeathNoticeList[i].szKiller );
} }
r = 255; g = 80; b = 0; r = 255; g = 80; b = 0;
@ -147,7 +154,7 @@ int CHudDeathNotice :: Draw( float flTime )
{ {
if ( rgDeathNoticeList[i].VictimColor ) if ( rgDeathNoticeList[i].VictimColor )
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] ); gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim ); x = DrawConsoleString( x, texty, rgDeathNoticeList[i].szVictim );
} }
} }
} }

View file

@ -97,6 +97,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
{ {
// hit the world, try to play sound based on texture material type // hit the world, try to play sound based on texture material type
char chTextureType = CHAR_TEX_CONCRETE; char chTextureType = CHAR_TEX_CONCRETE;
cl_entity_t *cl_entity = NULL;
float fvol; float fvol;
float fvolbar; float fvolbar;
char *rgsz[4]; char *rgsz[4];
@ -115,12 +116,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
chTextureType = 0; chTextureType = 0;
// Player // Player
if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) if ( entity == 0 )
{
// hit body
chTextureType = CHAR_TEX_FLESH;
}
else if ( entity == 0 )
{ {
// get texture from entity or world (world is ent(0)) // get texture from entity or world (world is ent(0))
pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd );
@ -149,6 +145,20 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
chTextureType = PM_FindTextureType( szbuffer ); chTextureType = PM_FindTextureType( szbuffer );
} }
} }
else
{
// JoshA: Look up the entity and find the EFLAG_FLESH_SOUND flag.
// This broke at some point then TF:C added prediction.
//
// It used to use Classify of pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE
// to determine what sound to play, but that's server side and isn't available on the client
// and got lost in the translation to that.
// Now the server will replicate that state via an eflag.
cl_entity = gEngfuncs.GetEntityByIndex( entity );
if ( cl_entity && !!( cl_entity->curstate.eflags & EFLAG_FLESH_SOUND ) )
chTextureType = CHAR_TEX_FLESH;
}
switch (chTextureType) switch (chTextureType)
{ {
@ -400,7 +410,16 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); // JoshA: Changed from PM_STUDIO_BOX to PM_NORMAL in prediction code as otherwise if you hit an NPC or player's
// bounding box but not one of their hitboxes, the shot won't hit on the server but it will
// play a hit sound on the client and not make a decal (as if it hit the NPC/player).
// We should mirror the way the server does the test here as close as possible.
//
// I initially thought I was just fixing some stupid Half-Life bug but no,
// this is *the* root cause of all the ghost shot bad prediction bugs in Half-Life Deathmatch!
//
// Also... CStrike was always using PM_NORMAL for all of these so it didn't have the problem.
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr );
tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
@ -912,7 +931,7 @@ void EV_FireGauss( event_args_t *args )
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_NORMAL, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates(); gEngfuncs.pEventAPI->EV_PopPMStates();
@ -1034,7 +1053,7 @@ void EV_FireGauss( event_args_t *args )
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_NORMAL, -1, &beam_tr );
if ( !beam_tr.allsolid ) if ( !beam_tr.allsolid )
{ {
@ -1043,7 +1062,7 @@ void EV_FireGauss( event_args_t *args )
// trace backwards to find exit point // trace backwards to find exit point
gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_NORMAL, -1, &beam_tr );
VectorSubtract( beam_tr.endpos, tr.endpos, delta ); VectorSubtract( beam_tr.endpos, tr.endpos, delta );
@ -1239,7 +1258,7 @@ void EV_FireCrossbow2( event_args_t *args )
// Now add in all of the players. // Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr );
//We hit something //We hit something
if ( tr.fraction < 1.0 ) if ( tr.fraction < 1.0 )
@ -1444,7 +1463,7 @@ void EV_EgonFire( event_args_t *args )
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates(); gEngfuncs.pEventAPI->EV_PopPMStates();

View file

@ -68,10 +68,14 @@ int CHudGeiger::Draw (float flTime)
int rg[3]; int rg[3];
int i; int i;
if (m_iGeigerRange <= 800 && m_iGeigerRange > 0) if (m_iGeigerRange < 1000 && m_iGeigerRange > 0)
{ {
// peicewise linear is better than continuous formula for this // peicewise linear is better than continuous formula for this
if (m_iGeigerRange > 600) if (m_iGeigerRange > 800)
{
pct = 0; //Con_Printf ( "range > 800\n");
}
else if (m_iGeigerRange > 600)
{ {
pct = 2; pct = 2;
flvol = 0.4; //Con_Printf ( "range > 600\n"); flvol = 0.4; //Con_Printf ( "range > 600\n");

View file

@ -217,6 +217,7 @@ int CHudHealth::Draw(float flTime)
SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross)); SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross));
x = CrossWidth + HealthWidth / 2; x = CrossWidth + HealthWidth / 2;
y += (int)(gHUD.m_iFontHeight * 0.2f);
x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b); x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b);
@ -307,49 +308,49 @@ int CHudHealth::DrawPain(float flTime)
if (m_fAttackFront > 0.4) if (m_fAttackFront > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackFront, 0.5 ); shade = a * max( m_fAttackFront, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2; x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2;
y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3; y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3;
SPR_DrawAdditive(0, x, y, NULL); SPR_DrawAdditive(0, x, y, NULL);
m_fAttackFront = max( 0, m_fAttackFront - fFade ); m_fAttackFront = max( 0.0f, m_fAttackFront - fFade );
} else } else
m_fAttackFront = 0; m_fAttackFront = 0;
if (m_fAttackRight > 0.4) if (m_fAttackRight > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackRight, 0.5 ); shade = a * max( m_fAttackRight, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2; x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2;
y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2; y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2;
SPR_DrawAdditive(1, x, y, NULL); SPR_DrawAdditive(1, x, y, NULL);
m_fAttackRight = max( 0, m_fAttackRight - fFade ); m_fAttackRight = max( 0.0f, m_fAttackRight - fFade );
} else } else
m_fAttackRight = 0; m_fAttackRight = 0;
if (m_fAttackRear > 0.4) if (m_fAttackRear > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackRear, 0.5 ); shade = a * max( m_fAttackRear, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2; x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2;
y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2; y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2;
SPR_DrawAdditive(2, x, y, NULL); SPR_DrawAdditive(2, x, y, NULL);
m_fAttackRear = max( 0, m_fAttackRear - fFade ); m_fAttackRear = max( 0.0f, m_fAttackRear - fFade );
} else } else
m_fAttackRear = 0; m_fAttackRear = 0;
if (m_fAttackLeft > 0.4) if (m_fAttackLeft > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackLeft, 0.5 ); shade = a * max( m_fAttackLeft, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
@ -357,7 +358,7 @@ int CHudHealth::DrawPain(float flTime)
y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2; y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2;
SPR_DrawAdditive(3, x, y, NULL); SPR_DrawAdditive(3, x, y, NULL);
m_fAttackLeft = max( 0, m_fAttackLeft - fFade ); m_fAttackLeft = max( 0.0f, m_fAttackLeft - fFade );
} else } else
m_fAttackLeft = 0; m_fAttackLeft = 0;

View file

@ -86,7 +86,9 @@ void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const c
int CBaseToggle::Restore( class CRestore & ) { return 1; } int CBaseToggle::Restore( class CRestore & ) { return 1; }
int CBaseToggle::Save( class CSave & ) { return 1; } int CBaseToggle::Save( class CSave & ) { return 1; }
void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { } void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { }
void CBaseToggle::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { }
void CBaseToggle::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { }
void CBaseToggle::SentenceStop( void ) { }
// CGrenade Stubs // CGrenade Stubs
void CGrenade::BounceSound( void ) { } void CGrenade::BounceSound( void ) { }
void CGrenade::Explode( Vector, Vector ) { } void CGrenade::Explode( Vector, Vector ) { }
@ -206,9 +208,6 @@ BOOL CBaseMonster :: FindLateralCover ( const Vector &vecThreat, const Vector &v
Vector CBaseMonster :: ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; } Vector CBaseMonster :: ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; }
BOOL CBaseMonster :: FacingIdeal( void ) { return FALSE; } BOOL CBaseMonster :: FacingIdeal( void ) { return FALSE; }
BOOL CBaseMonster :: FCanActiveIdle ( void ) { return FALSE; } BOOL CBaseMonster :: FCanActiveIdle ( void ) { return FALSE; }
void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { }
void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { }
void CBaseMonster::SentenceStop( void ) { }
void CBaseMonster::CorpseFallThink( void ) { } void CBaseMonster::CorpseFallThink( void ) { }
void CBaseMonster :: MonsterInitDead( void ) { } void CBaseMonster :: MonsterInitDead( void ) { }
BOOL CBaseMonster :: BBoxFlat ( void ) { return TRUE; } BOOL CBaseMonster :: BBoxFlat ( void ) { return TRUE; }

View file

@ -811,6 +811,8 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
player.m_afButtonPressed = buttonsChanged & cmd->buttons; player.m_afButtonPressed = buttonsChanged & cmd->buttons;
// The ones not down are "released" // The ones not down are "released"
player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); player.m_afButtonReleased = buttonsChanged & (~cmd->buttons);
player.pev->v_angle = cmd->viewangles;
player.pev->origin = from->client.origin;
// Set player variables that weapons code might check/alter // Set player variables that weapons code might check/alter
player.pev->button = cmd->buttons; player.pev->button = cmd->buttons;

View file

@ -81,7 +81,8 @@ static CHLVoiceStatusHelper g_VoiceStatusHelper;
extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount); extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
extern cvar_t *sensitivity; extern float IN_GetMouseSensitivity();
cvar_t *cl_lw = NULL; cvar_t *cl_lw = NULL;
void ShutdownInput (void); void ShutdownInput (void);
@ -326,8 +327,9 @@ void CHud :: Init( void )
m_iLogo = 0; m_iLogo = 0;
m_iFOV = 0; m_iFOV = 0;
CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 ); CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", FCVAR_ARCHIVE );
default_fov = CVAR_CREATE( "default_fov", "90", 0 ); CVAR_CREATE( "cl_autowepswitch", "1", FCVAR_USERINFO|FCVAR_ARCHIVE );
default_fov = CVAR_CREATE( "default_fov", "90", FCVAR_ARCHIVE );
m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE );
m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE );
cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
@ -371,6 +373,9 @@ void CHud :: Init( void )
ServersInit(); ServersInit();
MsgFunc_ResetHUD(0, 0, NULL ); MsgFunc_ResetHUD(0, 0, NULL );
gEngfuncs.pfnClientCmd("richpresence_gamemode\n"); // reset
gEngfuncs.pfnClientCmd("richpresence_update\n");
} }
// CHud destructor // CHud destructor
@ -425,10 +430,15 @@ void CHud :: VidInit( void )
m_hsprLogo = 0; m_hsprLogo = 0;
m_hsprCursor = 0; m_hsprCursor = 0;
if (ScreenWidth < 640) if (ScreenWidth > 2560 && ScreenHeight > 1600)
m_iRes = 320; m_iRes = 2560;
else else if (ScreenWidth >= 1280 && ScreenHeight > 720)
m_iRes = 1280;
else if (ScreenWidth >= 640)
m_iRes = 640; m_iRes = 640;
else
m_iRes = 320;
// Only load this once // Only load this once
if ( !m_pSpriteList ) if ( !m_pSpriteList )
@ -653,7 +663,7 @@ int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
else else
{ {
// set a new sensitivity that is proportional to the change from the FOV default // set a new sensitivity that is proportional to the change from the FOV default
m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); m_flMouseSensitivity = IN_GetMouseSensitivity() * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
} }
return 1; return 1;

View file

@ -438,6 +438,7 @@ private:
int m_HUD_title_life; int m_HUD_title_life;
int m_HUD_title_half; int m_HUD_title_half;
bool m_bEndAfterMessage;
}; };
// //

View file

@ -146,8 +146,8 @@ int CHudBenchmark::MsgFunc_Bench(const char *pszName, int iSize, void *pbuf)
m_fReceiveTime = gHUD.m_flTime; m_fReceiveTime = gHUD.m_flTime;
m_StoredLatency = ( m_fReceiveTime - m_fSendTime ); m_StoredLatency = ( m_fReceiveTime - m_fSendTime );
m_StoredLatency = min( 1.0, m_StoredLatency ); m_StoredLatency = min( 1.0f, m_StoredLatency );
m_StoredLatency = max( 0.0, m_StoredLatency ); m_StoredLatency = max( 0.0f, m_StoredLatency );
m_StoredPacketLoss = 0.0; m_StoredPacketLoss = 0.0;
@ -286,8 +286,8 @@ void CHudBenchmark::Think( void )
float switch_time; float switch_time;
float total_time; float total_time;
latency = max( 0.0, latency ); latency = max( 0.0f, latency );
latency = min( 1.0, latency ); latency = min( 1.0f, latency );
total_time = Bench_GetSwitchTime(); total_time = Bench_GetSwitchTime();
total_time -= 2.0; total_time -= 2.0;
@ -341,8 +341,8 @@ void CHudBenchmark::Think( void )
// Only takes 1/2 time to get up to maximum speed // Only takes 1/2 time to get up to maximum speed
frac *= 2.0; frac *= 2.0;
frac = max( 0.0, frac ); frac = max( 0.0f, frac );
frac = min( 1.0, frac ); frac = min( 1.0f, frac );
m_nObjects = (int)(NUM_BENCH_OBJ * frac); m_nObjects = (int)(NUM_BENCH_OBJ * frac);
} }

View file

@ -101,6 +101,13 @@ int CHud :: MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf )
BEGIN_READ( pbuf, iSize ); BEGIN_READ( pbuf, iSize );
m_Teamplay = READ_BYTE(); m_Teamplay = READ_BYTE();
if ( m_Teamplay )
gEngfuncs.pfnClientCmd("richpresence_gamemode Teamplay\n");
else
gEngfuncs.pfnClientCmd("richpresence_gamemode\n"); // reset
gEngfuncs.pfnClientCmd("richpresence_update\n");
return 1; return 1;
} }

View file

@ -36,7 +36,7 @@ extern int g_iVisibleMouse;
float HUD_GetFOV( void ); float HUD_GetFOV( void );
extern cvar_t *sensitivity; extern float IN_GetMouseSensitivity();
// Think // Think
void CHud::Think(void) void CHud::Think(void)
@ -75,13 +75,13 @@ void CHud::Think(void)
else else
{ {
// set a new sensitivity that is proportional to the change from the FOV default // set a new sensitivity that is proportional to the change from the FOV default
m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)default_fov->value) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); m_flMouseSensitivity = IN_GetMouseSensitivity() * ( (float)newfov / (float) max<int>( default_fov->value, 90 ) ) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
} }
// think about default fov // think about default fov
if ( m_iFOV == 0 ) if ( m_iFOV == 0 )
{ // only let players adjust up in fov, and only if they are not overriden by something else { // only let players adjust up in fov, and only if they are not overriden by something else
m_iFOV = max( default_fov->value, 90 ); m_iFOV = max<int>( default_fov->value, 90 );
} }
if ( gEngfuncs.IsSpectateOnly() ) if ( gEngfuncs.IsSpectateOnly() )

View file

@ -1,4 +1,4 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ //========= Copyright <EFBFBD> 1996-2001, Valve LLC, All rights reserved. ============
// //
// Purpose: // Purpose:
// //
@ -210,7 +210,8 @@ void UTIL_StringToVector( float * pVector, const char *pString )
char *pstr, *pfront, tempString[128]; char *pstr, *pfront, tempString[128];
int j; int j;
strcpy( tempString, pString ); strncpy( tempString, pString, sizeof( tempString ) );
tempString[ sizeof( tempString ) - 1 ] = '\0';
pstr = pfront = tempString; pstr = pfront = tempString;
for ( j = 0; j < 3; j++ ) for ( j = 0; j < 3; j++ )
@ -812,7 +813,7 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
break; break;
case DRC_CMD_STUFFTEXT: case DRC_CMD_STUFFTEXT:
EngineClientCmd( READ_STRING() ); EngineFilteredClientCmd( READ_STRING() );
break; break;
case DRC_CMD_CAMPATH: case DRC_CMD_CAMPATH:

View file

@ -23,6 +23,7 @@
#include "view.h" #include "view.h"
#include "Exports.h" #include "Exports.h"
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_mouse.h> #include <SDL2/SDL_mouse.h>
#include <SDL2/SDL_gamecontroller.h> #include <SDL2/SDL_gamecontroller.h>
@ -55,8 +56,6 @@ extern cvar_t *cl_pitchspeed;
extern cvar_t *cl_movespeedkey; extern cvar_t *cl_movespeedkey;
static double s_flRawInputUpdateTime = 0.0f;
static bool m_bRawInput = false;
static bool m_bMouseThread = false; static bool m_bMouseThread = false;
extern globalvars_t *gpGlobals; extern globalvars_t *gpGlobals;
@ -78,6 +77,13 @@ static cvar_t *m_customaccel_exponent;
// if threaded mouse is enabled then the time to sleep between polls // if threaded mouse is enabled then the time to sleep between polls
static cvar_t *m_mousethread_sleep; static cvar_t *m_mousethread_sleep;
static cvar_t* m_rawinput = nullptr;
static bool IN_UseRawInput()
{
return m_rawinput ? ( m_rawinput->value != 0 ) : false;
}
int mouse_buttons; int mouse_buttons;
int mouse_oldbuttonstate; int mouse_oldbuttonstate;
POINT current_pos; POINT current_pos;
@ -138,6 +144,7 @@ cvar_t *joy_advaxisz;
cvar_t *joy_advaxisr; cvar_t *joy_advaxisr;
cvar_t *joy_advaxisu; cvar_t *joy_advaxisu;
cvar_t *joy_advaxisv; cvar_t *joy_advaxisv;
cvar_t *joy_supported;
cvar_t *joy_forwardthreshold; cvar_t *joy_forwardthreshold;
cvar_t *joy_sidethreshold; cvar_t *joy_sidethreshold;
cvar_t *joy_pitchthreshold; cvar_t *joy_pitchthreshold;
@ -149,7 +156,7 @@ cvar_t *joy_yawsensitivity;
cvar_t *joy_wwhack1; cvar_t *joy_wwhack1;
cvar_t *joy_wwhack2; cvar_t *joy_wwhack2;
int joy_avail, joy_advancedinit, joy_haspov; int joy_avail = 0, joy_advancedinit, joy_haspov;
#ifdef _WIN32 #ifdef _WIN32
DWORD s_hMouseThreadId = 0; DWORD s_hMouseThreadId = 0;
@ -158,6 +165,7 @@ HANDLE s_hMouseQuitEvent = 0;
HANDLE s_hMouseDoneQuitEvent = 0; HANDLE s_hMouseDoneQuitEvent = 0;
#endif #endif
/* /*
=========== ===========
Force_CenterView_f Force_CenterView_f
@ -344,6 +352,28 @@ void IN_GetMousePos( int *mx, int *my )
gEngfuncs.GetMousePosition( mx, my ); gEngfuncs.GetMousePosition( mx, my );
} }
/*
===========
IN_GetMouseSensitivity
Get mouse sensitivity with sanitization
===========
*/
float IN_GetMouseSensitivity()
{
// Absurdly high sensitivity values can cause the game to hang, so clamp
if ( sensitivity->value > 10000.0 )
{
gEngfuncs.Cvar_SetValue( "sensitivity", 10000.0 );
}
else if ( sensitivity->value < 0.01 )
{
gEngfuncs.Cvar_SetValue( "sensitivity", 0.01 );
}
return sensitivity->value;
}
/* /*
=========== ===========
IN_ResetMouse IN_ResetMouse
@ -355,22 +385,33 @@ void IN_ResetMouse( void )
{ {
// no work to do in SDL // no work to do in SDL
#ifdef _WIN32 #ifdef _WIN32
if ( !m_bRawInput && mouseactive && gEngfuncs.GetWindowCenterX && gEngfuncs.GetWindowCenterY ) if ( !IN_UseRawInput() && mouseactive && gEngfuncs.GetWindowCenterX && gEngfuncs.GetWindowCenterY )
{ {
SetCursorPos ( gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY() ); SetCursorPos ( gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY() );
ThreadInterlockedExchange( &old_mouse_pos.x, gEngfuncs.GetWindowCenterX() ); ThreadInterlockedExchange( &old_mouse_pos.x, gEngfuncs.GetWindowCenterX() );
ThreadInterlockedExchange( &old_mouse_pos.y, gEngfuncs.GetWindowCenterY() ); ThreadInterlockedExchange( &old_mouse_pos.y, gEngfuncs.GetWindowCenterY() );
} }
if ( gpGlobals && gpGlobals->time - s_flRawInputUpdateTime > 1.0f )
{
s_flRawInputUpdateTime = gpGlobals->time;
m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) != 0;
}
#endif #endif
} }
/*
===========
IN_ResetRelativeMouseState
===========
*/
void IN_ResetRelativeMouseState(void)
{
if ( IN_UseRawInput() )
{
SDL_PumpEvents();
int deltaX, deltaY;
SDL_GetRelativeMouseState(&deltaX, &deltaY);
}
}
/* /*
=========== ===========
IN_MouseEvent IN_MouseEvent
@ -414,7 +455,7 @@ void IN_ScaleMouse( float *x, float *y )
float my = *y; float my = *y;
// This is the default sensitivity // This is the default sensitivity
float mouse_senstivity = ( gHUD.GetSensitivity() != 0 ) ? gHUD.GetSensitivity() : sensitivity->value; float mouse_senstivity = ( gHUD.GetSensitivity() != 0 ) ? gHUD.GetSensitivity() : IN_GetMouseSensitivity();
// Using special accleration values // Using special accleration values
if ( m_customaccel->value != 0 ) if ( m_customaccel->value != 0 )
@ -474,7 +515,7 @@ void IN_MouseMove ( float frametime, usercmd_t *cmd)
{ {
int deltaX, deltaY; int deltaX, deltaY;
#ifdef _WIN32 #ifdef _WIN32
if ( !m_bRawInput ) if ( !IN_UseRawInput() )
{ {
if ( m_bMouseThread ) if ( m_bMouseThread )
{ {
@ -497,7 +538,7 @@ void IN_MouseMove ( float frametime, usercmd_t *cmd)
} }
#ifdef _WIN32 #ifdef _WIN32
if ( !m_bRawInput ) if ( !IN_UseRawInput() )
{ {
if ( m_bMouseThread ) if ( m_bMouseThread )
{ {
@ -598,7 +639,7 @@ void CL_DLLEXPORT IN_Accumulate (void)
if (mouseactive) if (mouseactive)
{ {
#ifdef _WIN32 #ifdef _WIN32
if ( !m_bRawInput ) if ( !IN_UseRawInput() )
{ {
if ( !m_bMouseThread ) if ( !m_bMouseThread )
{ {
@ -650,40 +691,55 @@ void IN_StartupJoystick (void)
if ( gEngfuncs.CheckParm ("-nojoy", NULL ) ) if ( gEngfuncs.CheckParm ("-nojoy", NULL ) )
return; return;
// assume no joystick static float flLastCheck = 0.0f;
joy_avail = 0; if ( flLastCheck > 0.0f && (gEngfuncs.GetAbsoluteTime()-flLastCheck) < 1.0f )
return;
//gEngfuncs.Con_Printf("IN_StartupJoystick, %f\n", flLastCheck);
flLastCheck = gEngfuncs.GetAbsoluteTime();
int nJoysticks = SDL_NumJoysticks(); int nJoysticks = SDL_NumJoysticks();
if ( nJoysticks > 0 ) if ( nJoysticks > 0 )
{ {
for ( int i = 0; i < nJoysticks; i++ ) if ( s_pJoystick == NULL )
{ {
if ( SDL_IsGameController( i ) ) for ( int i = 0; i < nJoysticks; i++ )
{ {
s_pJoystick = SDL_GameControllerOpen( i ); if ( SDL_IsGameController( i ) )
if ( s_pJoystick )
{ {
//save the joystick's number of buttons and POV status s_pJoystick = SDL_GameControllerOpen( i );
joy_numbuttons = SDL_CONTROLLER_BUTTON_MAX; if ( s_pJoystick )
joy_haspov = 0; {
//save the joystick's number of buttons and POV status
joy_numbuttons = SDL_CONTROLLER_BUTTON_MAX;
joy_haspov = 0;
// old button and POV states default to no buttons pressed // old button and POV states default to no buttons pressed
joy_oldbuttonstate = joy_oldpovstate = 0; joy_oldbuttonstate = joy_oldpovstate = 0;
// mark the joystick as available and advanced initialization not completed
// this is needed as cvars are not available during initialization
gEngfuncs.Con_Printf ("joystick found %s\n\n", SDL_GameControllerName(s_pJoystick));
joy_avail = 1;
joy_advancedinit = 0;
break;
}
// mark the joystick as available and advanced initialization not completed
// this is needed as cvars are not available during initialization
gEngfuncs.Con_Printf ("joystick found\n\n", SDL_GameControllerName(s_pJoystick));
joy_avail = 1;
joy_advancedinit = 0;
break;
} }
} }
} }
} }
else else
{ {
gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n"); if ( s_pJoystick )
SDL_GameControllerClose( s_pJoystick );
s_pJoystick = NULL;
if ( joy_avail )
{
joy_avail = 0;
gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n");
}
} }
} }
@ -806,12 +862,14 @@ void IN_Commands (void)
{ {
key_index = (i < 4) ? K_JOY1 : K_AUX1; key_index = (i < 4) ? K_JOY1 : K_AUX1;
gEngfuncs.Key_Event (key_index + i, 1); gEngfuncs.Key_Event (key_index + i, 1);
//gEngfuncs.Con_Printf ("Button %d pressed\n", i);
} }
if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) ) if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
{ {
key_index = (i < 4) ? K_JOY1 : K_AUX1; key_index = (i < 4) ? K_JOY1 : K_AUX1;
gEngfuncs.Key_Event (key_index + i, 0); gEngfuncs.Key_Event (key_index + i, 0);
//gEngfuncs.Con_Printf ("Button %d released\n", i);
} }
} }
joy_oldbuttonstate = buttonstate; joy_oldbuttonstate = buttonstate;
@ -875,6 +933,9 @@ void IN_JoyMove ( float frametime, usercmd_t *cmd )
joy_advancedinit = 1; joy_advancedinit = 1;
} }
// re-scan for joystick presence
IN_StartupJoystick();
// verify joystick is available and that the user wants to use it // verify joystick is available and that the user wants to use it
if (!joy_avail || !in_joystick->value) if (!joy_avail || !in_joystick->value)
{ {
@ -1062,7 +1123,7 @@ IN_Init
void IN_Init (void) void IN_Init (void)
{ {
m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE ); m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE );
sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE ); // user mouse sensitivity setting. sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE | FCVAR_FILTERSTUFFTEXT ); // user mouse sensitivity setting.
in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE ); in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE );
joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 ); joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 );
@ -1073,6 +1134,7 @@ void IN_Init (void)
joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 ); joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 );
joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 ); joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 );
joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 ); joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 );
joy_supported = gEngfuncs.pfnRegisterVariable ( "joysupported", "1", 0 );
joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 ); joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 );
joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 ); joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 );
joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 ); joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 );
@ -1089,12 +1151,13 @@ void IN_Init (void)
m_customaccel_max = gEngfuncs.pfnRegisterVariable ( "m_customaccel_max", "0", FCVAR_ARCHIVE ); m_customaccel_max = gEngfuncs.pfnRegisterVariable ( "m_customaccel_max", "0", FCVAR_ARCHIVE );
m_customaccel_exponent = gEngfuncs.pfnRegisterVariable ( "m_customaccel_exponent", "1", FCVAR_ARCHIVE ); m_customaccel_exponent = gEngfuncs.pfnRegisterVariable ( "m_customaccel_exponent", "1", FCVAR_ARCHIVE );
m_rawinput = gEngfuncs.pfnGetCvarPointer("m_rawinput");
#ifdef _WIN32 #ifdef _WIN32
m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) > 0;
m_bMouseThread = gEngfuncs.CheckParm ("-mousethread", NULL ) != NULL; m_bMouseThread = gEngfuncs.CheckParm ("-mousethread", NULL ) != NULL;
m_mousethread_sleep = gEngfuncs.pfnRegisterVariable ( "m_mousethread_sleep", "10", FCVAR_ARCHIVE ); m_mousethread_sleep = gEngfuncs.pfnRegisterVariable ( "m_mousethread_sleep", "10", FCVAR_ARCHIVE );
if ( !m_bRawInput && m_bMouseThread && m_mousethread_sleep ) if ( !IN_UseRawInput() && m_bMouseThread && m_mousethread_sleep )
{ {
s_mouseDeltaX = s_mouseDeltaY = 0; s_mouseDeltaX = s_mouseDeltaY = 0;

View file

@ -143,6 +143,10 @@ int CHudMenu :: Draw( float flTime )
if ( gViewPort && gViewPort->IsScoreBoardVisible() ) if ( gViewPort && gViewPort->IsScoreBoardVisible() )
return 1; return 1;
SCREENINFO screenInfo;
screenInfo.iSize = sizeof( SCREENINFO );
gEngfuncs.pfnGetScreenInfo( &screenInfo );
// draw the menu, along the left-hand side of the screen // draw the menu, along the left-hand side of the screen
// count the number of newlines // count the number of newlines
@ -154,8 +158,10 @@ int CHudMenu :: Draw( float flTime )
nlc++; nlc++;
} }
int nFontHeight = max(12, screenInfo.iCharHeight);
// center it // center it
int y = (ScreenHeight/2) - ((nlc/2)*12) - 40; // make sure it is above the say text int y = (ScreenHeight/2) - ((nlc/2)* nFontHeight) - (3 * nFontHeight + nFontHeight / 3); // make sure it is above the say text
menu_r = 255; menu_r = 255;
menu_g = 255; menu_g = 255;
@ -175,7 +181,7 @@ int CHudMenu :: Draw( float flTime )
{ {
menu_ralign = FALSE; menu_ralign = FALSE;
menu_x = 20; menu_x = 20;
y += (12); y += nFontHeight;
sptr++; sptr++;
} }

View file

@ -20,6 +20,7 @@
#include "hud.h" #include "hud.h"
#include "cl_util.h" #include "cl_util.h"
#include "commonmacros.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "parsemsg.h" #include "parsemsg.h"
@ -58,6 +59,7 @@ void CHudMessage::Reset( void )
memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages ); memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages );
memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages ); memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages );
m_bEndAfterMessage = false;
m_gameTitleTime = 0; m_gameTitleTime = 0;
m_pGameTitle = NULL; m_pGameTitle = NULL;
} }
@ -147,13 +149,13 @@ void CHudMessage::MessageScanNextChar( void )
srcGreen = m_parms.pMessage->g1; srcGreen = m_parms.pMessage->g1;
srcBlue = m_parms.pMessage->b1; srcBlue = m_parms.pMessage->b1;
blend = 0; // Pure source blend = 0; // Pure source
destRed = destGreen = destBlue = 0;
switch( m_parms.pMessage->effect ) switch( m_parms.pMessage->effect )
{ {
// Fade-in / Fade-out // Fade-in / Fade-out
case 0: case 0:
case 1: case 1:
destRed = destGreen = destBlue = 0;
blend = m_parms.fadeBlend; blend = m_parms.fadeBlend;
break; break;
@ -168,6 +170,7 @@ void CHudMessage::MessageScanNextChar( void )
{ {
float deltaTime = m_parms.time - m_parms.charTime; float deltaTime = m_parms.time - m_parms.charTime;
destRed = destGreen = destBlue = 0;
if ( m_parms.time > m_parms.fadeTime ) if ( m_parms.time > m_parms.fadeTime )
{ {
blend = m_parms.fadeBlend; blend = m_parms.fadeBlend;
@ -285,7 +288,7 @@ void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time )
{ {
m_parms.lineLength = 0; m_parms.lineLength = 0;
m_parms.width = 0; m_parms.width = 0;
while ( *pText && *pText != '\n' ) while ( *pText && *pText != '\n' && m_parms.lineLength < ARRAYSIZE( line ) - 1 )
{ {
unsigned char c = *pText; unsigned char c = *pText;
line[m_parms.lineLength] = c; line[m_parms.lineLength] = c;
@ -402,6 +405,12 @@ int CHudMessage::Draw( float fTime )
{ {
// The message is over // The message is over
m_pMessages[i] = NULL; m_pMessages[i] = NULL;
if (m_bEndAfterMessage)
{
// leave game
gEngfuncs.pfnClientCmd("wait\nwait\nwait\nwait\nwait\nwait\nwait\ndisconnect\n");
}
} }
} }
} }
@ -487,6 +496,14 @@ int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf )
char *pString = READ_STRING(); char *pString = READ_STRING();
bool bIsEnding = false;
const char *HL1_ENDING_STR = "END3";
if (strlen(pString) == strlen(HL1_ENDING_STR) && strcmp(HL1_ENDING_STR, pString) == 0)
{
m_bEndAfterMessage = true;
}
MessageAdd( pString, gHUD.m_flTime ); MessageAdd( pString, gHUD.m_flTime );
// Remember the time -- to fix up level transitions // Remember the time -- to fix up level transitions
m_parms.time = gHUD.m_flTime; m_parms.time = gHUD.m_flTime;

View file

@ -46,6 +46,7 @@ int CHudTextMessage::Init(void)
// the new value is pushed into dst_buffer // the new value is pushed into dst_buffer
char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ) char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size )
{ {
int len = buffer_size;
char *dst = dst_buffer; char *dst = dst_buffer;
for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- ) for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- )
{ {
@ -85,7 +86,7 @@ char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, in
} }
} }
dst_buffer[buffer_size-1] = 0; // ensure null termination dst_buffer[len-1] = 0; // ensure null termination
return dst_buffer; return dst_buffer;
} }
@ -195,7 +196,7 @@ int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf
case HUD_PRINTNOTIFY: case HUD_PRINTNOTIFY:
psz[0] = 1; // mark this message to go into the notify buffer psz[0] = 1; // mark this message to go into the notify buffer
safe_sprintf( psz+1, MSG_BUF_SIZE, msg_text, sstr1, sstr2, sstr3, sstr4 ); safe_sprintf( psz+1, MSG_BUF_SIZE - 1, msg_text, sstr1, sstr2, sstr3, sstr4 );
ConsolePrint( ConvertCRtoNL( psz ) ); ConsolePrint( ConvertCRtoNL( psz ) );
break; break;

View file

@ -118,15 +118,19 @@ void VectorMA (const float *veca, float scale, const float *vecb, float *vecc)
HSPRITE LoadSprite(const char *pszName) HSPRITE LoadSprite(const char *pszName)
{ {
int i; int iRes;
char sz[256]; char sz[256];
if (ScreenWidth < 640) if (ScreenWidth > 2560 && ScreenHeight > 1600)
i = 320; iRes = 2560;
else if (ScreenWidth >= 1280 && ScreenHeight > 720)
iRes = 1280;
else if (ScreenWidth >= 640)
iRes = 640;
else else
i = 640; iRes = 320;
sprintf(sz, pszName, i); sprintf(sz, pszName, iRes);
return SPR_Load(sz); return SPR_Load(sz);
} }

View file

@ -78,6 +78,7 @@ int g_iUser3 = 0;
#define SBOARD_INDENT_Y_400 20 #define SBOARD_INDENT_Y_400 20
void IN_ResetMouse( void ); void IN_ResetMouse( void );
void IN_ResetRelativeMouseState( void );
extern CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ); extern CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall );
extern float * GetClientColor( int clientIndex ); extern float * GetClientColor( int clientIndex );
@ -817,8 +818,7 @@ try
// Get the button text // Get the button text
pfile = gEngfuncs.COM_ParseFile(pfile, token); pfile = gEngfuncs.COM_ParseFile(pfile, token);
strncpy( cText, token, 32 ); CHudTextMessage::LocaliseTextString( token, cText, sizeof( cText ) );
cText[31] = '\0';
// save off the last button text we've come across (for error reporting) // save off the last button text we've come across (for error reporting)
strcpy( szLastButtonText, cText ); strcpy( szLastButtonText, cText );
@ -2081,6 +2081,12 @@ void TeamFortressViewport::UpdateCursorState()
IN_ResetMouse(); IN_ResetMouse();
} }
if ( g_iVisibleMouse )
{
//Clear any residual input so our camera doesn't jerk when dismissing the UI
IN_ResetRelativeMouseState();
}
g_iVisibleMouse = false; g_iVisibleMouse = false;
App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_none) ); App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_none) );
} }

View file

@ -199,8 +199,8 @@ float V_CalcBob ( struct ref_params_s *pparams )
bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value; bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value;
bob = bob * 0.3 + bob * 0.7 * sin(cycle); bob = bob * 0.3 + bob * 0.7 * sin(cycle);
bob = min( bob, 4 ); bob = min( bob, 4.0f );
bob = max( bob, -7 ); bob = max( bob, -7.0f );
return bob; return bob;
} }
@ -374,9 +374,6 @@ void V_CalcGunAngle ( struct ref_params_s *pparams )
// don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view. // don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view.
viewent->angles[PITCH] -= v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * (v_ipitch_level.value * 0.5); viewent->angles[PITCH] -= v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * (v_ipitch_level.value * 0.5);
viewent->angles[YAW] -= v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; viewent->angles[YAW] -= v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value;
VectorCopy( viewent->angles, viewent->curstate.angles );
VectorCopy( viewent->angles, viewent->latched.prevangles );
} }
/* /*
@ -827,6 +824,15 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams )
} }
} }
// Update the latched view origin/angles here, this was
// previously done in V_CalcGunAngle but that happens
// before a bunch of other stuff happens, which nukes
// a bunch of the viewbob fx.
VectorCopy( view->origin, view->curstate.origin );
VectorCopy( view->origin, view->latched.prevorigin );
VectorCopy( view->angles, view->curstate.angles );
VectorCopy( view->angles, view->latched.prevangles );
lasttime = pparams->time; lasttime = pparams->time;
v_origin = pparams->vieworg; v_origin = pparams->vieworg;
@ -1679,7 +1685,7 @@ void V_DropPunchAngle ( float frametime, float *ev_punchangle )
len = VectorNormalize ( ev_punchangle ); len = VectorNormalize ( ev_punchangle );
len -= (10.0 + len * 0.5) * frametime; len -= (10.0 + len * 0.5) * frametime;
len = max( len, 0.0 ); len = max( len, 0.0f );
VectorScale ( ev_punchangle, len, ev_punchangle ); VectorScale ( ev_punchangle, len, ev_punchangle );
} }
@ -1712,7 +1718,7 @@ void V_Init (void)
v_centerspeed = gEngfuncs.pfnRegisterVariable( "v_centerspeed","500", 0 ); v_centerspeed = gEngfuncs.pfnRegisterVariable( "v_centerspeed","500", 0 );
cl_bobcycle = gEngfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0 );// best default for my experimental gun wag (sjb) cl_bobcycle = gEngfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0 );// best default for my experimental gun wag (sjb)
cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", 0 );// best default for my experimental gun wag (sjb) cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", FCVAR_ARCHIVE );// best default for my experimental gun wag (sjb)
cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 ); cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 );
cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 ); cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 );
cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 ); cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 );

View file

@ -116,6 +116,7 @@
// entity flags // entity flags
#define EFLAG_SLERP 1 // do studio interpolation of this entity #define EFLAG_SLERP 1 // do studio interpolation of this entity
#define EFLAG_FLESH_SOUND 2 // JoshA: Whether this entity should sound like flesh. (ie. pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
// //
// temp entity events // temp entity events

View file

@ -25,6 +25,10 @@
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). #define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log #define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar #define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar
#define FCVAR_PRIVILEGED (1<<10) // Not queryable/settable by unprivileged sources
#define FCVAR_FILTERSTUFFTEXT (1<<11) // Not queryable/settable if unprivileged and filterstufftext is enabled
#define FCVAR_FILTERCHARS (1<<12) // This cvar's string will be filtered for 'bad' characters (e.g. ';', '\n')
#define FCVAR_NOBADPATHS (1<<13) // This cvar's string cannot contain file paths that are above the current directory
typedef struct cvar_s typedef struct cvar_s
{ {

View file

@ -108,8 +108,8 @@ void __inline restore_fpu_cw(void)
_asm fldcw old_cw _asm fldcw old_cw
} }
#else #else
#define quick_ftol(f) ((int)(f))
#define set_fpu_cw() /* */ #define set_fpu_cw() /* */
#define quick_ftol(f) ftol(f)
#define restore_fpu_cw() /* */ #define restore_fpu_cw() /* */
#endif #endif

View file

@ -19,21 +19,26 @@
#pragma once #pragma once
#endif #endif
// JoshA: Unfortunately netadr_s is passed to clients for connectionless packets.
// No Valve mod uses them, but custom mods *might*, so not changing the start of this struct layout.
// It's very unlikely they touch this, but I'd like to play as safe as possible with all ABI etc for mod compat.
// If we want to add IPv6 someday, bung it at the end of netadr_s and leave ip + ipx alone.
typedef enum typedef enum
{ {
NA_UNUSED, NA_UNUSED,
NA_LOOPBACK, NA_LOOPBACK,
NA_BROADCAST, NA_BROADCAST,
NA_IP, NA_IP,
NA_IPX, NA_IPX, // deprecated
NA_BROADCAST_IPX, NA_BROADCAST_IPX, // deprecated
} netadrtype_t; } netadrtype_t;
typedef struct netadr_s typedef struct netadr_s
{ {
netadrtype_t type; netadrtype_t type;
unsigned char ip[4]; unsigned char ip[4];
unsigned char ipx[10]; unsigned char ipx[10]; // deprecated
unsigned short port; unsigned short port;
} netadr_t; } netadr_t;

View file

@ -21,7 +21,7 @@
// Font stuff // Font stuff
#define NUM_GLYPHS 256 #define NUM_GLYPHS 256
// does not exist: // #include "basetypes.h" #include "basetypes.h"
typedef struct typedef struct
{ {
@ -35,7 +35,7 @@ typedef struct qfont_s
int rowcount; int rowcount;
int rowheight; int rowheight;
charinfo fontinfo[ NUM_GLYPHS ]; charinfo fontinfo[ NUM_GLYPHS ];
unsigned char data[4]; byte data[4];
} qfont_t; } qfont_t;
#endif // qfont.h #endif // qfont.h

View file

@ -0,0 +1,86 @@
from PIL import Image
import sys
import os
def convert_to_tiles(input_file, output_folder, tile_size=(256, 256)):
# Open the image
img = Image.open(input_file)
width, height = img.size
# Create the output folder if it doesn't exist
if not os.path.exists(output_folder):
os.makedirs(output_folder)
output_img_folder = os.path.join(output_folder, "background")
if not os.path.exists(output_img_folder):
os.makedirs(output_img_folder)
row = 0
col = 0
prefix = "21_9"
# background txt file should look like:
#
# resolution 800 600
#
# resource/background/800_1_a_loading.tga fit 0 0
# resource/background/800_1_b_loading.tga fit 256 0
# etc
layout_file = f"resolution\t{width}\t{height}\n\n"
# Loop through the image and extract tiles
for j in range(0, height, tile_size[1]):
row = row + 1
col = 0
for i in range(0, width, tile_size[0]):
# Calculate the boundaries for the tile, making sure it doesn't exceed the image dimensions
right_bound = min(i + tile_size[0], width)
bottom_bound = min(j + tile_size[1], height)
box = (i, j, right_bound, bottom_bound)
tile = img.crop(box)
tile_char = chr(ord('a')+col)
target_file = f"{prefix}_{row}_{tile_char}_loading.tga"
tile_filename = os.path.join(output_img_folder, target_file)
tile.save(tile_filename)
print(f"Saved {tile_filename}")
line = f"resource/background/{target_file}\tfit\t{i}\t{j}\n"
layout_file += line
col = col + 1
print("------------------------------------------")
print(layout_file)
print("------------------------------------------")
out_txt = os.path.join(output_folder, "BackgroundLayout.txt")
with open(out_txt, 'w') as f:
f.write(layout_file)
out_txt = os.path.join(output_folder, "BackgroundLoadingLayout.txt")
with open(out_txt, 'w') as f:
f.write(layout_file)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python image_to_background.py path_to_image (psd/png/tga)")
sys.exit(1)
img_path = sys.argv[1]
img_dir = os.path.dirname(img_path)
img_dir = os.path.join(img_dir, "Background")
print(f"out dir: {img_dir}")
convert_to_tiles(img_path, img_dir)
#width, height, palette, data = read_spr(spr_path)
#save_as_png(spr_path + "__.png", width, height, palette, data)
print(f"Converted {img_path}")

238
devtools/image_to_spr.py Normal file
View file

@ -0,0 +1,238 @@
import os
import sys
import struct
from PIL import Image
import math
# Sprite type:
# 0 = VP_PARALLEL_UPRIGHT,
# 1 = FACING_UPRIGHT,
# 2 = VP_PARALLEL,
# 3 = ORIENTED,
# 4 = VP_PARALLEL_ORIENTED
# Texture format:
# 0 = SPR_NORMAL
# 1 = SPR_ADDITIVE
# 2 = SPR_INDEXALPHA
# 3 = SPR_ALPHTEST
#TODO: original width / height preservation throughout, use that for offsets and bounding radii
def write_spr_header(spr_file, width, height, numframes, sprite_type=2, texture_format=1, synctype=0):
bounding_radius = 32
if width > 0 and height > 0:
bounding_radius = math.sqrt( ( (width / 2) ** 2 ) + ( ( height / 2) ** 2 ) )
spr_file.write(b'IDSP') # Identifier
spr_file.write(struct.pack('<i', 2)) # Version (2 for Half-Life)
spr_file.write(struct.pack('<i', sprite_type)) # Sprite type
spr_file.write(struct.pack('<i', texture_format)) #Texture Format (0 = SPR_NORMAL)
spr_file.write(struct.pack('<f', bounding_radius))
spr_file.write(struct.pack('<i', width)) # Width
spr_file.write(struct.pack('<i', height)) # Height
spr_file.write(struct.pack('<i', numframes)) # Number of frames
spr_file.write(struct.pack('<f', 0.0)) # Beamlength (not used)
spr_file.write(struct.pack('<i', synctype)) # Synctype (0 for synchronized)
def write_palette_data(spr_file, image, palette):
spr_file.write(struct.pack('<h', 256))
#palette = image.getpalette()#[:768] # 256 colors * 3 (R, G, B)
spr_file.write(bytearray(palette))
def closest_color_index(rgb, color_list):
"""Find the index of the closest color in the list."""
distances = [euclidean_distance(rgb, color) for color in color_list]
return distances.index(min(distances))
def euclidean_distance(c1, c2):
"""Calculate the Euclidean distance between two colors."""
return sum((a - b) ** 2 for a, b in zip(c1, c2)) ** 0.5
def write_indexed_data(spr_file, image, palette):
img_data = list( image.getdata() )
indexed_data = []
palette_colors = []
for i in range(0, len(palette)-4, 3):
palette_colors.append( palette[i:i+3] )
img_colors = []
for i in range(0, len(img_data), 1):
col = img_data[i]
img_colors.append( list(col) )
#print(f"palette_colors: {palette_colors}\n\n")
num_prints = 0
for p in img_colors:
idx = 0
if p in palette_colors:
#print(f"found {p} in palette_colors")
idx = palette_colors.index(p)
else:
num_prints = num_prints + 1
if num_prints < 30:
print(f"couldn't find {p}")
indexed_data.append(idx)
spr_file.write(bytearray(indexed_data))
# for index in indexed_data:
# spr_file.write(struct.pack('<B', index))
def next_power_of_two(n):
"""Return the next power of two for given n."""
return 2 ** (n - 1).bit_length()
def pad_image_to_power_of_two(image):
"""Pad image dimensions to the next power of two."""
width, height = image.size
new_width = next_power_of_two(width)
new_height = next_power_of_two(height)
# Create a new blank image with the padded size
padded_image = Image.new("RGB", (new_width, new_height), 0)
padded_image.paste(image, (0, 0))
return padded_image
def create_palette(img):
"""Extract unique colors from the image and create a palette."""
# Get the list of all colors in the image
colors = list(img.getdata())
# Deduplicate the colors
unique_colors = sorted(list(set(colors)))
#print( f"unique_colors: {unique_colors}" )
# Create a palette
palette = []
for color in unique_colors:
palette.extend(color[:3]) # We only want RGB, not RGBA
# Fill the rest of the 256-color palette with black
while len(palette) < 256 * 3:
palette.extend((0, 0, 0))
#print( f"palette: {palette}" )
return unique_colors, palette
def palettize_image(img, unique_colors, palette):
# Create a palette image whose size does not matter
arbitrary_size = 16, 16
palimage = Image.new('P', arbitrary_size)
palimage.putpalette(palette)
img_p = img.convert("P", 0, palimage.im)
img_p.putpalette(palette)
return img_p
def img_to_spr(img_path, spr_path):
# 1. Read the image file and convert to indexed color
image = Image.open(img_path).convert("RGBA")
# 1.1. Pad image to power of two dimensions
image = pad_image_to_power_of_two(image)
width, height = image.size
# Extract unique colors and create a palette
unique_colors, palette = create_palette(image)
# Palettize the image
# image.save(spr_path + "_PALETTETIME.png")
#print("\n\n\n")
with open(spr_path, 'wb') as spr_file:
# 2. Write SPR header
write_spr_header(spr_file, width, height, 1)
# 3. Write the palette data
write_palette_data(spr_file, image, palette)
# 4. Write the frame header
spr_file.write(struct.pack('<i', 0)) # frame group
spr_file.write(struct.pack('<i', int(-width/2)) ) # frame_origin_x
spr_file.write(struct.pack('<i', int(-height/2)) ) # frame_origin_y
spr_file.write(struct.pack('<i', width)) # frame_width
spr_file.write(struct.pack('<i', height)) # frame_height
# 4.1 Write the indexed data
write_indexed_data(spr_file, image, palette)
def read_spr(filename):
with open(filename, 'rb') as f:
# Read the SPR header
id = f.read(4).decode()
if id != 'IDSP':
raise ValueError("Not a valid SPR file")
version, = struct.unpack('<i', f.read(4))
type, = struct.unpack('<i', f.read(4))
if type != 2: # 2 = VP_PARALLEL
raise ValueError(f"Only VP_PARALLEL type supported, got {type}")
# other header info...
format, = struct.unpack('<i', f.read(4))
bounding_radius, = struct.unpack('<f', f.read(4))
width, = struct.unpack('<i', f.read(4))
height, = struct.unpack('<i', f.read(4))
num_frames, = struct.unpack('<i', f.read(4))
beam_len, = struct.unpack('<f', f.read(4))
sync_type, = struct.unpack('<i', f.read(4))
#print(f"format: {format}\nbounding_radius: {bounding_radius}\nwidth: {width}\nheight: {height}\nnum_frames: {num_frames}\nbeam_len: {beam_len}\nsync_type: {sync_type}\n")
# For simplicity, assume a single frame
if num_frames != 1:
raise ValueError(f"Only single frame SPRs supported, got {num_frames}")
palette_len, = struct.unpack('<h', f.read(2))
# Read the palette (256 RGB entries)
palette = [(ord(f.read(1)), ord(f.read(1)), ord(f.read(1))) for _ in range(256)]
#print( f"palette: {palette}" )
# Read the frame
frame_group, = struct.unpack('<i', f.read(4))
frame_origin_x, = struct.unpack('<i', f.read(4))
frame_origin_y, = struct.unpack('<i', f.read(4))
frame_width, = struct.unpack('<i', f.read(4))
frame_height, = struct.unpack('<i', f.read(4))
#print(f"frame_group: {frame_group} frame_origin_x: {frame_origin_x} frame_origin_y: {frame_origin_y} frame_width: {frame_width} frame_height: {frame_height}")
data = f.read(width * height)
return width, height, palette, data
def save_as_png(filename, width, height, palette, data):
img_data = [palette[byte] for byte in data]
img = Image.new('RGB', (width, height))
img.putdata(img_data)
img.save(filename)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python image_to_spr.py path_to_image (psd/png)")
sys.exit(1)
img_path = sys.argv[1]
spr_path = img_path.rsplit('.', 1)[0] + ".spr" # Replace .png with .spr for output
print(f"{img_path} -> {spr_path}")
img_to_spr(img_path, spr_path)
width, height, palette, data = read_spr(spr_path)
save_as_png(spr_path + "__.png", width, height, palette, data)
print(f"Converted {img_path} to {spr_path}")
#spr_path = 'content/materialsrc/Sprites/1280/test.spr'
#width, height, palette, data = read_spr(spr_path)
#save_as_png(spr_path + "__.png", width, height, palette, data)

View file

@ -111,6 +111,7 @@ public:
LINK_ENTITY_TO_CLASS( monster_flyer, CFlockingFlyer ); LINK_ENTITY_TO_CLASS( monster_flyer, CFlockingFlyer );
LINK_ENTITY_TO_CLASS( monster_flyer_flock, CFlockingFlyerFlock ); LINK_ENTITY_TO_CLASS( monster_flyer_flock, CFlockingFlyerFlock );
TYPEDESCRIPTION CFlockingFlyer::m_SaveData[] = TYPEDESCRIPTION CFlockingFlyer::m_SaveData[] =
{ {
DEFINE_FIELD( CFlockingFlyer, m_pSquadLeader, FIELD_CLASSPTR ), DEFINE_FIELD( CFlockingFlyer, m_pSquadLeader, FIELD_CLASSPTR ),

View file

@ -108,6 +108,8 @@ public:
SCRIPTSTATE m_scriptState; // internal cinematic state SCRIPTSTATE m_scriptState; // internal cinematic state
CCineMonster *m_pCine; CCineMonster *m_pCine;
float m_flLastYawTime; // Last time yaw change was computed
virtual int Save( CSave &save ); virtual int Save( CSave &save );
virtual int Restore( CRestore &restore ); virtual int Restore( CRestore &restore );
@ -190,11 +192,8 @@ public:
virtual void ScheduleChange( void ) {} virtual void ScheduleChange( void ) {}
// virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); } // virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); }
virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel ); virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel );
virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); } virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAllowedToSpeak(); }
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); virtual BOOL IsAllowedToSpeak() { return IsAlive(); }
virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
virtual void SentenceStop( void );
Task_t *GetTask ( void ); Task_t *GetTask ( void );
virtual MONSTERSTATE GetIdealState ( void ); virtual MONSTERSTATE GetIdealState ( void );

View file

@ -60,6 +60,10 @@ CBaseEntity
#endif #endif
#endif #endif
#if defined EXPORT
#undef EXPORT
#endif
#define EXPORT CBASE_DLLEXPORT #define EXPORT CBASE_DLLEXPORT
extern "C" CBASE_DLLEXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); extern "C" CBASE_DLLEXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
@ -105,7 +109,10 @@ typedef void (CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCall
#define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace #define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace
#define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures. #define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
#define CLASS_VEHICLE 14
class CBaseEntity; class CBaseEntity;
class CBaseToggle;
class CBaseMonster; class CBaseMonster;
class CBasePlayerItem; class CBasePlayerItem;
class CSquadMonster; class CSquadMonster;
@ -175,6 +182,7 @@ public:
virtual int BloodColor( void ) { return DONT_BLEED; } virtual int BloodColor( void ) { return DONT_BLEED; }
virtual void TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ); virtual void TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
virtual BOOL IsTriggered( CBaseEntity *pActivator ) {return TRUE;} virtual BOOL IsTriggered( CBaseEntity *pActivator ) {return TRUE;}
virtual CBaseToggle* MyTogglePointer(void) { return NULL; }
virtual CBaseMonster *MyMonsterPointer( void ) { return NULL;} virtual CBaseMonster *MyMonsterPointer( void ) { return NULL;}
virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL;} virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL;}
virtual int GetToggleState( void ) { return TS_AT_TOP; } virtual int GetToggleState( void ) { return TS_AT_TOP; }
@ -546,6 +554,14 @@ public:
void EXPORT AngularMoveDone( void ); void EXPORT AngularMoveDone( void );
BOOL IsLockedByMaster( void ); BOOL IsLockedByMaster( void );
virtual CBaseToggle* MyTogglePointer(void) { return this; }
// monsters use this, but so could buttons for instance
virtual void PlaySentence(const char* pszSentence, float duration, float volume, float attenuation);
virtual void PlayScriptedSentence(const char* pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity* pListener);
virtual void SentenceStop(void);
virtual BOOL IsAllowedToSpeak() { return FALSE; }
static float AxisValue( int flags, const Vector &angles ); static float AxisValue( int flags, const Vector &angles );
static void AxisDir( entvars_t *pev ); static void AxisDir( entvars_t *pev );
static float AxisDelta( int flags, const Vector &angle1, const Vector &angle2 ); static float AxisDelta( int flags, const Vector &angle1, const Vector &angle2 );
@ -705,6 +721,7 @@ public:
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
// Buttons that don't take damage can be IMPULSE used // Buttons that don't take damage can be IMPULSE used
virtual int ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); } virtual int ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); }
virtual BOOL IsAllowedToSpeak() { return TRUE; }
BOOL m_fStayPushed; // button stays pushed in until touched again? BOOL m_fStayPushed; // button stays pushed in until touched again?
BOOL m_fRotating; // a rotating button? default is a sliding button. BOOL m_fRotating; // a rotating button? default is a sliding button.

View file

@ -495,8 +495,6 @@ ClientCommand
called each time a player uses a "cmd" command called each time a player uses a "cmd" command
============ ============
*/ */
extern float g_flWeaponCheat;
// Use CMD_ARGV, CMD_ARGV, and CMD_ARGC to get pointers the character string command. // Use CMD_ARGV, CMD_ARGV, and CMD_ARGC to get pointers the character string command.
void ClientCommand( edict_t *pEntity ) void ClientCommand( edict_t *pEntity )
{ {
@ -523,7 +521,7 @@ void ClientCommand( edict_t *pEntity )
} }
else if ( FStrEq(pcmd, "give" ) ) else if ( FStrEq(pcmd, "give" ) )
{ {
if ( g_flWeaponCheat != 0.0) if ( CVAR_GET_FLOAT( "sv_cheats" ) != 0.0)
{ {
int iszItem = ALLOC_STRING( CMD_ARGV(1) ); // Make a copy of the classname int iszItem = ALLOC_STRING( CMD_ARGV(1) ); // Make a copy of the classname
GetClassPtr((CBasePlayer *)pev)->GiveNamedItem( STRING(iszItem) ); GetClassPtr((CBasePlayer *)pev)->GiveNamedItem( STRING(iszItem) );
@ -537,7 +535,7 @@ void ClientCommand( edict_t *pEntity )
} }
else if ( FStrEq(pcmd, "fov" ) ) else if ( FStrEq(pcmd, "fov" ) )
{ {
if ( g_flWeaponCheat && CMD_ARGC() > 1) if ( CVAR_GET_FLOAT( "sv_cheats" ) && CMD_ARGC() > 1)
{ {
GetClassPtr((CBasePlayer *)pev)->m_iFOV = atoi( CMD_ARGV(1) ); GetClassPtr((CBasePlayer *)pev)->m_iFOV = atoi( CMD_ARGV(1) );
} }
@ -607,6 +605,13 @@ void ClientCommand( edict_t *pEntity )
// max total length is 192 ...and we're adding a string below ("Unknown command: %s\n") // max total length is 192 ...and we're adding a string below ("Unknown command: %s\n")
strncpy( command, pcmd, 127 ); strncpy( command, pcmd, 127 );
command[127] = '\0'; command[127] = '\0';
// First parse the name and remove any %'s
for ( char *pApersand = command; pApersand != NULL && *pApersand != 0; pApersand++ )
{
// Replace it with a space
if ( *pApersand == '%' )
*pApersand = ' ';
}
// tell the user they entered an unknown command // tell the user they entered an unknown command
ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", command ) ); ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", command ) );
@ -870,6 +875,7 @@ void ClientPrecache( void )
PRECACHE_SOUND("debris/wood3.wav"); PRECACHE_SOUND("debris/wood3.wav");
PRECACHE_SOUND("plats/train_use1.wav"); // use a train PRECACHE_SOUND("plats/train_use1.wav"); // use a train
PRECACHE_SOUND("plats/vehicle_ignition.wav");
PRECACHE_SOUND("buttons/spark5.wav"); // hit computer texture PRECACHE_SOUND("buttons/spark5.wav"); // hit computer texture
PRECACHE_SOUND("buttons/spark6.wav"); PRECACHE_SOUND("buttons/spark6.wav");
@ -1268,6 +1274,12 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
state->health = ent->v.health; state->health = ent->v.health;
} }
CBaseEntity *pEntity = static_cast<CBaseEntity*>( GET_PRIVATE( ent ) );
if ( pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE )
state->eflags |= EFLAG_FLESH_SOUND;
else
state->eflags &= ~EFLAG_FLESH_SOUND;
return 1; return 1;
} }
@ -1622,12 +1634,12 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
item->m_iId = II.iId; item->m_iId = II.iId;
item->m_iClip = gun->m_iClip; item->m_iClip = gun->m_iClip;
item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001 ); item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001f );
item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001 ); item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001f );
item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001 ); item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001f );
item->m_fInReload = gun->m_fInReload; item->m_fInReload = gun->m_fInReload;
item->m_fInSpecialReload = gun->m_fInSpecialReload; item->m_fInSpecialReload = gun->m_fInSpecialReload;
item->fuser1 = max( gun->pev->fuser1, -0.001 ); item->fuser1 = max( gun->pev->fuser1, -0.001f );
item->fuser2 = gun->m_flStartThrow; item->fuser2 = gun->m_flStartThrow;
item->fuser3 = gun->m_flReleaseThrow; item->fuser3 = gun->m_flReleaseThrow;
item->iuser1 = gun->m_chargeReady; item->iuser1 = gun->m_chargeReady;
@ -1635,7 +1647,7 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
item->iuser3 = gun->m_fireState; item->iuser3 = gun->m_fireState;
// item->m_flPumpTime = max( gun->m_flPumpTime, -0.001 ); // item->m_flPumpTime = max( gun->m_flPumpTime, -0.001f );
} }
} }
pPlayerItem = pPlayerItem->m_pNext; pPlayerItem = pPlayerItem->m_pNext;

View file

@ -193,9 +193,12 @@ int CCrowbar::Swing( int fFirst )
} }
#endif #endif
PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar, if ( fFirst )
0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, {
0.0, 0, 0.0 ); PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar,
0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0,
0.0, 0, 0.0 );
}
if ( tr.flFraction >= 1.0 ) if ( tr.flFraction >= 1.0 )
@ -232,7 +235,9 @@ int CCrowbar::Swing( int fFirst )
ClearMultiDamage( ); ClearMultiDamage( );
if ( (m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() ) // JoshA: Changed from < -> <= to fix the full swing logic since client weapon prediction.
// -1.0f + 1.0f = 0.0f. UTIL_WeaponTimeBase is always 0 with client weapon prediction (0 time base vs curtime base)
if ( ( m_flNextPrimaryAttack + 1.0f <= UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() )
{ {
// first swing does full damage // first swing does full damage
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB ); pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB );
@ -307,7 +312,7 @@ int CCrowbar::Swing( int fFirst )
m_flNextPrimaryAttack = GetNextAttackDelay(0.25); m_flNextPrimaryAttack = GetNextAttackDelay(0.25);
SetThink( &CCrowbar::Smack ); SetThink( &CCrowbar::Smack );
pev->nextthink = UTIL_WeaponTimeBase() + 0.2; pev->nextthink = gpGlobals->time + 0.2;
} }

View file

@ -427,7 +427,7 @@ LINK_ENTITY_TO_CLASS( trip_beam, CTripBeam );
void CTripBeam::Spawn( void ) void CTripBeam::Spawn( void )
{ {
CLightning::Spawn(); CLightning::Spawn();
SetTouch( &CTripBeam::TriggerTouch ); SetTouch( &CBeam::TriggerTouch );
pev->solid = SOLID_TRIGGER; pev->solid = SOLID_TRIGGER;
RelinkBeam(); RelinkBeam();
} }

View file

@ -35,6 +35,10 @@
#define EGON_SWITCH_NARROW_TIME 0.75 // Time it takes to switch fire modes #define EGON_SWITCH_NARROW_TIME 0.75 // Time it takes to switch fire modes
#define EGON_SWITCH_WIDE_TIME 1.5 #define EGON_SWITCH_WIDE_TIME 1.5
#ifndef CLIENT_DLL
extern bool IsBustingGame();
#endif
enum egon_e { enum egon_e {
EGON_IDLE1 = 0, EGON_IDLE1 = 0,
EGON_FIDGET1, EGON_FIDGET1,
@ -51,11 +55,11 @@ enum egon_e {
LINK_ENTITY_TO_CLASS( weapon_egon, CEgon ); LINK_ENTITY_TO_CLASS( weapon_egon, CEgon );
void CEgon::Spawn( ) void CEgon::Spawn()
{ {
Precache( ); Precache();
m_iId = WEAPON_EGON; m_iId = WEAPON_EGON;
SET_MODEL(ENT(pev), "models/w_egon.mdl"); SET_MODEL( ENT( pev ), "models/w_egon.mdl" );
m_iDefaultAmmo = EGON_DEFAULT_GIVE; m_iDefaultAmmo = EGON_DEFAULT_GIVE;
@ -102,6 +106,7 @@ int CEgon::AddToPlayer( CBasePlayer *pPlayer )
MESSAGE_END(); MESSAGE_END();
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
@ -155,6 +160,12 @@ BOOL CEgon::HasAmmo( void )
void CEgon::UseAmmo( int count ) void CEgon::UseAmmo( int count )
{ {
#ifndef CLIENT_DLL
if ( IsBustingGame() )
return;
#endif
if ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= count ) if ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= count )
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= count; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= count;
else else
@ -440,7 +451,9 @@ void CEgon::CreateEffect( void )
m_pSprite->pev->scale = 1.0; m_pSprite->pev->scale = 1.0;
m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation ); m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY; m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY;
m_pSprite->pev->flags |= FL_SKIPLOCALHOST; // Josh: This sprite is not predicted o the client, so was missing
// for many years after it got broken in an update.
//m_pSprite->pev->flags |= FL_SKIPLOCALHOST;
m_pSprite->pev->owner = m_pPlayer->edict(); m_pSprite->pev->owner = m_pPlayer->edict();
if ( m_fireMode == FIRE_WIDE ) if ( m_fireMode == FIRE_WIDE )
@ -519,7 +532,17 @@ void CEgon::WeaponIdle( void )
m_deployed = TRUE; m_deployed = TRUE;
} }
BOOL CEgon::CanHolster( void )
{
#ifndef CLIENT_DLL
if ( IsBustingGame() )
{
return FALSE;
}
#endif
return TRUE;
}
void CEgon::EndAttack( void ) void CEgon::EndAttack( void )
{ {

View file

@ -54,9 +54,6 @@ typedef int BOOL;
#include <limits.h> #include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> // memset #include <string.h> // memset
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max #ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b))
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) #define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
@ -66,6 +63,10 @@ typedef int BOOL;
// Misc C-runtime library headers // Misc C-runtime library headers
#include "stdio.h" #include "stdio.h"
#include "stdlib.h" #include "stdlib.h"
#include "minmax.h"
#ifndef _WIN32
# define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
#endif
#include "math.h" #include "math.h"
// Header file containing definition of globalvars_t and entvars_t // Header file containing definition of globalvars_t and entvars_t

View file

@ -87,13 +87,18 @@ void CFlyingMonster :: Stop( void )
} }
float CFlyingMonster :: ChangeYaw( int speed ) float CFlyingMonster :: ChangeYaw( int yawSpeed )
{ {
if ( pev->movetype == MOVETYPE_FLY ) if ( pev->movetype == MOVETYPE_FLY )
{ {
float diff = FlYawDiff(); float diff = FlYawDiff();
float target = 0; float target = 0;
if ( m_flLastZYawTime == 0.f )
{
m_flLastZYawTime = gpGlobals->time - gpGlobals->frametime;
}
if ( m_IdealActivity != GetStoppedActivity() ) if ( m_IdealActivity != GetStoppedActivity() )
{ {
if ( diff < -20 ) if ( diff < -20 )
@ -101,9 +106,18 @@ float CFlyingMonster :: ChangeYaw( int speed )
else if ( diff > 20 ) else if ( diff > 20 )
target = -90; target = -90;
} }
pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * gpGlobals->frametime );
float delta = gpGlobals->time - m_flLastZYawTime;
m_flLastZYawTime = gpGlobals->time;
// Clamp delta like the engine does with frametime
if ( delta > 0.25f )
delta = 0.25f;
float speed = 220.f * delta;
pev->angles.z = UTIL_Approach( target, pev->angles.z, speed );
} }
return CBaseMonster::ChangeYaw( speed ); return CBaseMonster::ChangeYaw( yawSpeed );
} }

View file

@ -25,7 +25,7 @@ public:
Activity GetStoppedActivity( void ); Activity GetStoppedActivity( void );
void Killed( entvars_t *pevAttacker, int iGib ); void Killed( entvars_t *pevAttacker, int iGib );
void Stop( void ); void Stop( void );
float ChangeYaw( int speed ); float ChangeYaw( int yawSpeed );
void HandleAnimEvent( MonsterEvent_t *pEvent ); void HandleAnimEvent( MonsterEvent_t *pEvent );
void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval ); void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval );
void Move( float flInterval = 0.1 ); void Move( float flInterval = 0.1 );
@ -46,6 +46,7 @@ protected:
float m_stopTime; // Last time we stopped (to avoid switching states too soon) float m_stopTime; // Last time we stopped (to avoid switching states too soon)
float m_momentum; // Weight for desired vs. momentum velocity float m_momentum; // Weight for desired vs. momentum velocity
const char *m_pFlapSound; const char *m_pFlapSound;
float m_flLastZYawTime; // Last frame time Z was changed when yaw was changed
}; };

View file

@ -934,7 +934,11 @@ void CPushable :: Move( CBaseEntity *pOther, int push )
if ( pOther->IsPlayer() ) if ( pOther->IsPlayer() )
{ {
if ( push && !(pevToucher->button & (IN_FORWARD|IN_USE)) ) // Don't push unless the player is pushing forward and NOT use (pull) // JoshA: Used to check for FORWARD too and logic was inverted
// from comment which seems wrong.
// Fixed to just check for USE being not set for PUSH.
// Should have the right effect.
if ( push && !!(pevToucher->button & IN_USE) ) // Don't push unless the player is not useing (pull)
return; return;
playerTouch = 1; playerTouch = 1;
} }
@ -956,19 +960,39 @@ void CPushable :: Move( CBaseEntity *pOther, int push )
else else
factor = 0.25; factor = 0.25;
pev->velocity.x += pevToucher->velocity.x * factor; // This used to be added every 'frame', but to be consistent at high fps,
pev->velocity.y += pevToucher->velocity.y * factor; // now act as if it's added at a constant rate with a fudge factor.
extern cvar_t sv_pushable_fixed_tick_fudge;
if ( !push && sv_pushable_fixed_tick_fudge.value >= 0.0f )
{
factor *= gpGlobals->frametime * sv_pushable_fixed_tick_fudge.value;
}
// JoshA: Always apply this if pushing, or if under the player's velocity.
if ( push || ( abs(pev->velocity.x) < abs(pevToucher->velocity.x - pevToucher->velocity.x * factor) ) )
pev->velocity.x += pevToucher->velocity.x * factor;
if ( push || ( abs(pev->velocity.y) < abs(pevToucher->velocity.y - pevToucher->velocity.y * factor) ) )
pev->velocity.y += pevToucher->velocity.y * factor;
float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y ); float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y );
if ( push && (length > MaxSpeed()) ) if ( length > MaxSpeed() )
{ {
pev->velocity.x = (pev->velocity.x * MaxSpeed() / length ); pev->velocity.x = (pev->velocity.x * MaxSpeed() / length );
pev->velocity.y = (pev->velocity.y * MaxSpeed() / length ); pev->velocity.y = (pev->velocity.y * MaxSpeed() / length );
} }
if ( playerTouch ) if ( playerTouch )
{ {
pevToucher->velocity.x = pev->velocity.x; // JoshA: Match the player to our pushable's velocity.
pevToucher->velocity.y = pev->velocity.y; // Previously this always happened, but it should only
// happen if the player is pushing (or rather, being pushed.)
// This either stops the player in their tracks or nudges them along.
if ( push )
{
pevToucher->velocity.x = pev->velocity.x;
pevToucher->velocity.y = pev->velocity.y;
}
if ( (gpGlobals->time - m_soundTime) > 0.7 ) if ( (gpGlobals->time - m_soundTime) > 0.7 )
{ {
m_soundTime = gpGlobals->time; m_soundTime = gpGlobals->time;

View file

@ -46,6 +46,7 @@ cvar_t mp_chattime = {"mp_chattime","10", FCVAR_SERVER };
// Engine Cvars // Engine Cvars
cvar_t *g_psv_gravity = NULL; cvar_t *g_psv_gravity = NULL;
cvar_t *g_psv_aim = NULL; cvar_t *g_psv_aim = NULL;
cvar_t *g_psv_allow_autoaim = NULL;
cvar_t *g_footsteps = NULL; cvar_t *g_footsteps = NULL;
//CVARS FOR SKILL LEVEL SETTINGS //CVARS FOR SKILL LEVEL SETTINGS
@ -450,6 +451,10 @@ cvar_t sk_player_leg3 = { "sk_player_leg3","1" };
// END Cvars for Skill Level settings // END Cvars for Skill Level settings
cvar_t sv_pushable_fixed_tick_fudge = { "sv_pushable_fixed_tick_fudge", "15" };
cvar_t sv_busters = { "sv_busters", "0" };
// Register your console variables here // Register your console variables here
// This gets called one time when the game is initialied // This gets called one time when the game is initialied
void GameDLLInit( void ) void GameDLLInit( void )
@ -458,6 +463,7 @@ void GameDLLInit( void )
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" ); g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
g_psv_aim = CVAR_GET_POINTER( "sv_aim" ); g_psv_aim = CVAR_GET_POINTER( "sv_aim" );
g_psv_allow_autoaim = CVAR_GET_POINTER( "sv_allow_autoaim" );
g_footsteps = CVAR_GET_POINTER( "mp_footsteps" ); g_footsteps = CVAR_GET_POINTER( "mp_footsteps" );
CVAR_REGISTER (&displaysoundlist); CVAR_REGISTER (&displaysoundlist);
@ -484,6 +490,8 @@ void GameDLLInit( void )
CVAR_REGISTER (&mp_chattime); CVAR_REGISTER (&mp_chattime);
CVAR_REGISTER( &sv_busters );
// REGISTER CVARS FOR SKILL LEVEL STUFF // REGISTER CVARS FOR SKILL LEVEL STUFF
// Agrunt // Agrunt
CVAR_REGISTER ( &sk_agrunt_health1 );// {"sk_agrunt_health1","0"}; CVAR_REGISTER ( &sk_agrunt_health1 );// {"sk_agrunt_health1","0"};
@ -885,6 +893,8 @@ void GameDLLInit( void )
CVAR_REGISTER ( &sk_player_leg3 ); CVAR_REGISTER ( &sk_player_leg3 );
// END REGISTER CVARS FOR SKILL LEVEL STUFF // END REGISTER CVARS FOR SKILL LEVEL STUFF
CVAR_REGISTER ( &sv_pushable_fixed_tick_fudge );
SERVER_COMMAND( "exec skill.cfg\n" ); SERVER_COMMAND( "exec skill.cfg\n" );
} }

View file

@ -40,6 +40,7 @@ extern cvar_t allowmonsters;
// Engine Cvars // Engine Cvars
extern cvar_t *g_psv_gravity; extern cvar_t *g_psv_gravity;
extern cvar_t *g_psv_aim; extern cvar_t *g_psv_aim;
extern cvar_t *g_psv_allow_autoaim;
extern cvar_t *g_footsteps; extern cvar_t *g_footsteps;
#endif // GAME_H #endif // GAME_H

View file

@ -34,6 +34,7 @@ extern int gmsgDeathMsg; // client dll messages
extern int gmsgMOTD; extern int gmsgMOTD;
int g_teamplay = 0; int g_teamplay = 0;
extern cvar_t sv_busters;
//========================================================= //=========================================================
//========================================================= //=========================================================
@ -328,7 +329,13 @@ CGameRules *InstallGameRules( void )
g_teamplay = 1; g_teamplay = 1;
return new CHalfLifeTeamplay; return new CHalfLifeTeamplay;
} }
if ((int)gpGlobals->deathmatch == 1)
if ( sv_busters.value == 1 )
{
g_teamplay = 0;
return new CMultiplayBusters;
}
else if ((int)gpGlobals->deathmatch == 1)
{ {
// vanilla deathmatch // vanilla deathmatch
g_teamplay = 0; g_teamplay = 0;

View file

@ -293,6 +293,7 @@ public:
virtual BOOL AllowAutoTargetCrosshair( void ); virtual BOOL AllowAutoTargetCrosshair( void );
virtual BOOL ClientCommand( CBasePlayer *pPlayer, const char *pcmd ); virtual BOOL ClientCommand( CBasePlayer *pPlayer, const char *pcmd );
virtual void ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer );
// Client kills/scoring // Client kills/scoring
virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ); virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled );
@ -357,4 +358,32 @@ protected:
void SendMOTDToClient( edict_t *client ); void SendMOTDToClient( edict_t *client );
}; };
//=========================================================
// CMultiplayBusters
// Rules for a multiplayer mode that makes you feel good
//=========================================================
class CMultiplayBusters : public CHalfLifeMultiplay
{
public:
CMultiplayBusters();
virtual void Think( void );
virtual int IPointsForKill( CBasePlayer* pAttacker, CBasePlayer* pKilled );
virtual void PlayerKilled( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor );
virtual void DeathNotice( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor );
virtual int WeaponShouldRespawn( CBasePlayerItem* pWeapon );
virtual BOOL CanHavePlayerItem( CBasePlayer* pPlayer, CBasePlayerItem* pWeapon );
virtual BOOL CanHaveItem( CBasePlayer* pPlayer, CItem* pItem );
virtual void PlayerGotWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pWeapon );
virtual void ClientUserInfoChanged( CBasePlayer* pPlayer, char* infobuffer );
virtual void PlayerSpawn( CBasePlayer* pPlayer );
void SetPlayerModel( CBasePlayer* pPlayer );
protected:
float m_flEgonBustingCheckTime = -1.0f;
void CheckForEgons( void );
};
extern DLL_GLOBAL CGameRules* g_pGameRules; extern DLL_GLOBAL CGameRules* g_pGameRules;

View file

@ -171,6 +171,10 @@ void CGauss::PrimaryAttack()
void CGauss::SecondaryAttack() void CGauss::SecondaryAttack()
{ {
// JoshA: Sanitize this so it's not total garbage on level transition
// and we end up ear blasting the player!
m_pPlayer->m_flStartCharge = min( m_pPlayer->m_flStartCharge, gpGlobals->time );
// don't fire underwater // don't fire underwater
if ( m_pPlayer->pev->waterlevel == 3 ) if ( m_pPlayer->pev->waterlevel == 3 )
{ {
@ -309,6 +313,10 @@ void CGauss::StartFire( void )
{ {
float flDamage; float flDamage;
// JoshA: Sanitize this so it's not total garbage on level transition
// and we end up ear blasting the player!
m_pPlayer->m_flStartCharge = min( m_pPlayer->m_flStartCharge, gpGlobals->time );
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
Vector vecAiming = gpGlobals->v_forward; Vector vecAiming = gpGlobals->v_forward;
Vector vecSrc = m_pPlayer->GetGunPosition( ); // + gpGlobals->v_up * -8 + gpGlobals->v_right * 8; Vector vecSrc = m_pPlayer->GetGunPosition( ); // + gpGlobals->v_up * -8 + gpGlobals->v_right * 8;
@ -375,7 +383,7 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
int fFirstBeam = 1; int fFirstBeam = 1;
int nMaxHits = 10; int nMaxHits = 10;
pentIgnore = ENT( m_pPlayer->pev ); pentIgnore = m_pPlayer->edict();
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
if ( m_fPrimaryFire == false ) if ( m_fPrimaryFire == false )
@ -426,6 +434,13 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
if (pEntity->pev->takedamage) if (pEntity->pev->takedamage)
{ {
ClearMultiDamage(); ClearMultiDamage();
// if you hurt yourself clear the headshot bit
if (m_pPlayer->pev == pEntity->pev)
{
tr.iHitgroup = 0;
}
pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET ); pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET );
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
} }

View file

@ -228,13 +228,7 @@ void CGlock::GlockFire( float flSpread , float flCycleTime, BOOL fUseAutoAim )
void CGlock::Reload( void ) void CGlock::Reload( void )
{ {
int iResult; int iResult = DefaultReload( GLOCK_MAX_CLIP, m_iClip > 0 ? GLOCK_RELOAD_NOT_EMPTY : GLOCK_RELOAD, 1.5 );
if (m_iClip == 0)
iResult = DefaultReload( 17, GLOCK_RELOAD, 1.5 );
else
iResult = DefaultReload( 18, GLOCK_RELOAD_NOT_EMPTY, 1.5 );
if (iResult) if (iResult)
{ {
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );

View file

@ -45,6 +45,7 @@ public:
// Don't treat as a live target // Don't treat as a live target
virtual BOOL IsAlive( void ) { return FALSE; } virtual BOOL IsAlive( void ) { return FALSE; }
virtual BOOL IsAllowedToSpeak() { return TRUE; }
virtual int Save( CSave &save ); virtual int Save( CSave &save );
virtual int Restore( CRestore &restore ); virtual int Restore( CRestore &restore );

View file

@ -140,9 +140,10 @@ void CHandGrenade::WeaponIdle( void )
else else
angThrow.x = -10 + angThrow.x * ( ( 90 + 10 ) / 90.0 ); angThrow.x = -10 + angThrow.x * ( ( 90 + 10 ) / 90.0 );
float flVel = ( 90 - angThrow.x ) * 4; static float flMultiplier = 6.5f;
if ( flVel > 500 ) float flVel = ( 90 - angThrow.x ) * flMultiplier;
flVel = 500; if ( flVel > 1000 )
flVel = 1000;
UTIL_MakeVectors( angThrow ); UTIL_MakeVectors( angThrow );

View file

@ -728,12 +728,12 @@ void CHAssassin :: RunAI( void )
EMIT_SOUND (ENT(pev), CHAN_BODY, "debris/beamstart1.wav", 0.2, ATTN_NORM ); EMIT_SOUND (ENT(pev), CHAN_BODY, "debris/beamstart1.wav", 0.2, ATTN_NORM );
} }
pev->renderamt = max( pev->renderamt - 50, m_iTargetRanderamt ); pev->renderamt = max<float>( pev->renderamt - 50, m_iTargetRanderamt );
pev->rendermode = kRenderTransTexture; pev->rendermode = kRenderTransTexture;
} }
else if (pev->renderamt < m_iTargetRanderamt) else if (pev->renderamt < m_iTargetRanderamt)
{ {
pev->renderamt = min( pev->renderamt + 50, m_iTargetRanderamt ); pev->renderamt = min<float>( pev->renderamt + 50, m_iTargetRanderamt );
if (pev->renderamt == 255) if (pev->renderamt == 255)
pev->rendermode = kRenderNormal; pev->rendermode = kRenderNormal;
} }

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,14 @@
#include "hornet.h" #include "hornet.h"
#include "gamerules.h" #include "gamerules.h"
static float GetRechargeTime()
{
if (gpGlobals->maxClients > 1)
{
return 0.3f;
}
return 0.5f;
}
enum hgun_e { enum hgun_e {
HGUN_IDLE1 = 0, HGUN_IDLE1 = 0,
@ -144,7 +152,7 @@ void CHgun::PrimaryAttack()
CBaseEntity *pHornet = CBaseEntity::Create( "hornet", m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12, m_pPlayer->pev->v_angle, m_pPlayer->edict() ); CBaseEntity *pHornet = CBaseEntity::Create( "hornet", m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pHornet->pev->velocity = gpGlobals->v_forward * 300; pHornet->pev->velocity = gpGlobals->v_forward * 300;
m_flRechargeTime = gpGlobals->time + 0.5; m_flRechargeTime = gpGlobals->time + GetRechargeTime();
#endif #endif
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
@ -173,6 +181,10 @@ void CHgun::PrimaryAttack()
{ {
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25; m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
} }
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0)
{
m_flNextPrimaryAttack += GetRechargeTime();
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
} }
@ -237,7 +249,7 @@ void CHgun::SecondaryAttack( void )
pHornet->SetThink( &CHornet::StartDart ); pHornet->SetThink( &CHornet::StartDart );
m_flRechargeTime = gpGlobals->time + 0.5; m_flRechargeTime = gpGlobals->time + GetRechargeTime();
#endif #endif
int flags; int flags;
@ -257,7 +269,14 @@ void CHgun::SecondaryAttack( void )
// player "shoot" animation // player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1; m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1;
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0)
{
m_flRechargeTime = gpGlobals->time + 0.5;
m_flNextSecondaryAttack += 0.5;
m_flNextPrimaryAttack += 0.5;
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
} }
@ -270,7 +289,7 @@ void CHgun::Reload( void )
while (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < HORNET_MAX_CARRY && m_flRechargeTime < gpGlobals->time) while (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < HORNET_MAX_CARRY && m_flRechargeTime < gpGlobals->time)
{ {
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++;
m_flRechargeTime += 0.5; m_flRechargeTime += GetRechargeTime();
} }
} }

View file

@ -78,7 +78,7 @@ public:
BOOL CheckMeleeAttack1 ( float flDot, float flDist ); BOOL CheckMeleeAttack1 ( float flDot, float flDist );
BOOL CheckRangeAttack1 ( float flDot, float flDist ); BOOL CheckRangeAttack1 ( float flDot, float flDist );
float ChangeYaw( int speed ); float ChangeYaw( int yawSpeed );
Activity GetStoppedActivity( void ); Activity GetStoppedActivity( void );
void Move( float flInterval ); void Move( float flInterval );
@ -90,7 +90,7 @@ public:
float VectorToPitch( const Vector &vec); float VectorToPitch( const Vector &vec);
float FlPitchDiff( void ); float FlPitchDiff( void );
float ChangePitch( int speed ); float ChangePitch( int pitchSpeed );
Vector m_SaveVelocity; Vector m_SaveVelocity;
float m_idealDist; float m_idealDist;
@ -108,6 +108,9 @@ public:
float m_flNextAlert; float m_flNextAlert;
float m_flLastPitchTime; // Last frame time pitch was changed
float m_flLastZYawTime; // Last frame time Z was changed when yaw was changed
static const char *pIdleSounds[]; static const char *pIdleSounds[];
static const char *pAlertSounds[]; static const char *pAlertSounds[];
static const char *pAttackSounds[]; static const char *pAttackSounds[];
@ -795,12 +798,18 @@ float CIchthyosaur::FlPitchDiff( void )
return flPitchDiff; return flPitchDiff;
} }
float CIchthyosaur :: ChangePitch( int speed ) float CIchthyosaur :: ChangePitch( int pitchSpeed )
{ {
if ( pev->movetype == MOVETYPE_FLY ) if ( pev->movetype == MOVETYPE_FLY )
{ {
float diff = FlPitchDiff(); float diff = FlPitchDiff();
float target = 0; float target = 0;
if ( m_flLastPitchTime == 0.f )
{
m_flLastPitchTime = gpGlobals->time - gpGlobals->frametime;
}
if ( m_IdealActivity != GetStoppedActivity() ) if ( m_IdealActivity != GetStoppedActivity() )
{ {
if (diff < -20) if (diff < -20)
@ -808,18 +817,32 @@ float CIchthyosaur :: ChangePitch( int speed )
else if (diff > 20) else if (diff > 20)
target = -45; target = -45;
} }
pev->angles.x = UTIL_Approach(target, pev->angles.x, 220.0 * 0.1 );
float delta = gpGlobals->time - m_flLastPitchTime;
m_flLastPitchTime = gpGlobals->time;
// Clamp delta like the engine does with frametime
if ( delta > 0.25f )
delta = 0.25f;
float speed = 220.f * delta;
pev->angles.x = UTIL_Approach(target, pev->angles.x, speed );
} }
return 0; return 0;
} }
float CIchthyosaur::ChangeYaw( int speed ) float CIchthyosaur::ChangeYaw( int yawSpeed )
{ {
if ( pev->movetype == MOVETYPE_FLY ) if ( pev->movetype == MOVETYPE_FLY )
{ {
float diff = FlYawDiff(); float diff = FlYawDiff();
float target = 0; float target = 0;
if ( m_flLastZYawTime == 0.f )
{
m_flLastZYawTime = gpGlobals->time - gpGlobals->frametime;
}
if ( m_IdealActivity != GetStoppedActivity() ) if ( m_IdealActivity != GetStoppedActivity() )
{ {
if ( diff < -20 ) if ( diff < -20 )
@ -827,9 +850,18 @@ float CIchthyosaur::ChangeYaw( int speed )
else if ( diff > 20 ) else if ( diff > 20 )
target = -20; target = -20;
} }
pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * 0.1 );
float delta = gpGlobals->time - m_flLastZYawTime;
m_flLastZYawTime = gpGlobals->time;
// Clamp delta like the engine does with frametime
if ( delta > 0.25f )
delta = 0.25f;
float speed = 220.f * delta;
pev->angles.z = UTIL_Approach( target, pev->angles.z, speed );
} }
return CFlyingMonster::ChangeYaw( speed ); return CFlyingMonster::ChangeYaw( yawSpeed );
} }

View file

@ -229,7 +229,7 @@ class CItemBattery : public CItem
char szcharge[64]; char szcharge[64];
pPlayer->pev->armorvalue += gSkillData.batteryCapacity; pPlayer->pev->armorvalue += gSkillData.batteryCapacity;
pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY); pPlayer->pev->armorvalue = min<float>(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY);
EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM );

View file

@ -799,7 +799,7 @@ void CGamePlayerEquip::KeyValue( KeyValueData *pkvd )
{ {
char tmp[128]; char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp ); UTIL_StripToken( pkvd->szKeyName, tmp, sizeof( tmp ) );
m_weaponNames[i] = ALLOC_STRING(tmp); m_weaponNames[i] = ALLOC_STRING(tmp);
m_weaponCount[i] = atoi(pkvd->szValue); m_weaponCount[i] = atoi(pkvd->szValue);

View file

@ -1989,7 +1989,7 @@ void CBaseMonster::MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, f
while (flTotal > 0.001) while (flTotal > 0.001)
{ {
// don't walk more than 16 units or stairs stop working // don't walk more than 16 units or stairs stop working
flStep = min( 16.0, flTotal ); flStep = min( 16.0f, flTotal );
UTIL_MoveToOrigin ( ENT(pev), m_Route[ m_iRouteIndex ].vecLocation, flStep, MOVE_NORMAL ); UTIL_MoveToOrigin ( ENT(pev), m_Route[ m_iRouteIndex ].vecLocation, flStep, MOVE_NORMAL );
flTotal -= flStep; flTotal -= flStep;
} }
@ -2537,7 +2537,19 @@ float CBaseMonster::ChangeYaw ( int yawSpeed )
ideal = pev->ideal_yaw; ideal = pev->ideal_yaw;
if (current != ideal) if (current != ideal)
{ {
speed = (float)yawSpeed * gpGlobals->frametime * 10; if ( m_flLastYawTime == 0.f )
{
m_flLastYawTime = gpGlobals->time - gpGlobals->frametime;
}
float delta = gpGlobals->time - m_flLastYawTime;
m_flLastYawTime = gpGlobals->time;
// Clamp delta like the engine does with frametime
if ( delta > 0.25f )
delta = 0.25f;
speed = (float)yawSpeed * delta * 2;
move = ideal - current; move = ideal - current;
if (ideal > current) if (ideal > current)
@ -3231,30 +3243,6 @@ BOOL CBaseMonster :: FCanActiveIdle ( void )
} }
void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation )
{
if ( pszSentence && IsAlive() )
{
if ( pszSentence[0] == '!' )
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, PITCH_NORM );
else
SENTENCEG_PlayRndSz( edict(), pszSentence, volume, attenuation, 0, PITCH_NORM );
}
}
void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener )
{
PlaySentence( pszSentence, duration, volume, attenuation );
}
void CBaseMonster::SentenceStop( void )
{
EMIT_SOUND( edict(), CHAN_VOICE, "common/null.wav", 1.0, ATTN_IDLE );
}
void CBaseMonster::CorpseFallThink( void ) void CBaseMonster::CorpseFallThink( void )
{ {
if ( pev->flags & FL_ONGROUND ) if ( pev->flags & FL_ONGROUND )

View file

@ -55,7 +55,7 @@ void CMP5::Spawn( )
SET_MODEL(ENT(pev), "models/w_9mmAR.mdl"); SET_MODEL(ENT(pev), "models/w_9mmAR.mdl");
m_iId = WEAPON_MP5; m_iId = WEAPON_MP5;
m_iDefaultAmmo = MP5_DEFAULT_GIVE; m_iDefaultAmmo = gpGlobals->maxClients > 1 ? MP5_MAX_CLIP : MP5_DEFAULT_GIVE;
FallInit();// get ready to fall down. FallInit();// get ready to fall down.
} }
@ -158,9 +158,9 @@ void CMP5::PrimaryAttack()
Vector vecDir; Vector vecDir;
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
if ( !bIsMultiplayer() ) if ( bIsMultiplayer() )
#else #else
if ( !g_pGameRules->IsMultiplayer() ) if ( g_pGameRules->IsMultiplayer() )
#endif #endif
{ {
// optimized multiplayer. Widened to make it easier to hit a moving player // optimized multiplayer. Widened to make it easier to hit a moving player

View file

@ -27,6 +27,7 @@
#include "items.h" #include "items.h"
#include "voice_gamemgr.h" #include "voice_gamemgr.h"
#include "hltv.h" #include "hltv.h"
#include "trains.h"
#if !defined ( _WIN32 ) #if !defined ( _WIN32 )
#include <ctype.h> #include <ctype.h>
@ -47,6 +48,15 @@ extern int g_teamplay;
float g_flIntermissionStartTime = 0; float g_flIntermissionStartTime = 0;
// longest the intermission can last, in seconds
#define MAX_INTERMISSION_TIME 120
extern cvar_t timeleft, fragsleft, sv_busters;
extern cvar_t mp_chattime;
CVoiceGameMgr g_VoiceGameMgr; CVoiceGameMgr g_VoiceGameMgr;
class CMultiplayGameMgrHelper : public IVoiceGameMgrHelper class CMultiplayGameMgrHelper : public IVoiceGameMgrHelper
@ -135,7 +145,7 @@ void CHalfLifeMultiplay::RefreshSkillData( void )
gSkillData.plrDmg9MM = 12; gSkillData.plrDmg9MM = 12;
// 357 Round // 357 Round
gSkillData.plrDmg357 = 40; gSkillData.plrDmg357 = 50;
// MP5 Round // MP5 Round
gSkillData.plrDmgMP5 = 12; gSkillData.plrDmgMP5 = 12;
@ -169,13 +179,6 @@ void CHalfLifeMultiplay::RefreshSkillData( void )
gSkillData.plrDmgHornet = 10; gSkillData.plrDmgHornet = 10;
} }
// longest the intermission can last, in seconds
#define MAX_INTERMISSION_TIME 120
extern cvar_t timeleft, fragsleft;
extern cvar_t mp_chattime;
//========================================================= //=========================================================
//========================================================= //=========================================================
void CHalfLifeMultiplay :: Think ( void ) void CHalfLifeMultiplay :: Think ( void )
@ -306,6 +309,18 @@ BOOL CHalfLifeMultiplay::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerI
return TRUE; return TRUE;
} }
if ( pPlayer->m_iAutoWepSwitch == 0 )
{
return FALSE;
}
else if ( pPlayer->m_iAutoWepSwitch == 2 )
{
if ( pPlayer->m_afButtonLast & ( IN_ATTACK | IN_ATTACK2 ) )
{
return FALSE;
}
}
if ( !pPlayer->m_pActiveItem->CanHolster() ) if ( !pPlayer->m_pActiveItem->CanHolster() )
{ {
// can't put away the active item. // can't put away the active item.
@ -320,71 +335,11 @@ BOOL CHalfLifeMultiplay::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerI
return FALSE; return FALSE;
} }
extern BOOL HLGetNextBestWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pCurrentWeapon );
BOOL CHalfLifeMultiplay :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) BOOL CHalfLifeMultiplay :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon )
{ {
return HLGetNextBestWeapon( pPlayer, pCurrentWeapon );
CBasePlayerItem *pCheck;
CBasePlayerItem *pBest;// this will be used in the event that we don't find a weapon in the same category.
int iBestWeight;
int i;
iBestWeight = -1;// no weapon lower than -1 can be autoswitched to
pBest = NULL;
if ( !pCurrentWeapon->CanHolster() )
{
// can't put this gun away right now, so can't switch.
return FALSE;
}
for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ )
{
pCheck = pPlayer->m_rgpPlayerItems[ i ];
while ( pCheck )
{
if ( pCheck->iWeight() > -1 && pCheck->iWeight() == pCurrentWeapon->iWeight() && pCheck != pCurrentWeapon )
{
// this weapon is from the same category.
if ( pCheck->CanDeploy() )
{
if ( pPlayer->SwitchWeapon( pCheck ) )
{
return TRUE;
}
}
}
else if ( pCheck->iWeight() > iBestWeight && pCheck != pCurrentWeapon )// don't reselect the weapon we're trying to get rid of
{
//ALERT ( at_console, "Considering %s\n", STRING( pCheck->pev->classname ) );
// we keep updating the 'best' weapon just in case we can't find a weapon of the same weight
// that the player was using. This will end up leaving the player with his heaviest-weighted
// weapon.
if ( pCheck->CanDeploy() )
{
// if this weapon is useable, flag it as the best
iBestWeight = pCheck->iWeight();
pBest = pCheck;
}
}
pCheck = pCheck->m_pNext;
}
}
// if we make it here, we've checked all the weapons and found no useable
// weapon in the same catagory as the current weapon.
// if pBest is null, we didn't find ANYTHING. Shouldn't be possible- should always
// at least get the crowbar, but ya never know.
if ( !pBest )
{
return FALSE;
}
pPlayer->SwitchWeapon( pBest );
return TRUE;
} }
//========================================================= //=========================================================
@ -553,6 +508,9 @@ void CHalfLifeMultiplay :: PlayerSpawn( CBasePlayer *pPlayer )
BOOL addDefault; BOOL addDefault;
CBaseEntity *pWeaponEntity = NULL; CBaseEntity *pWeaponEntity = NULL;
int iAutoWepSwitch = pPlayer->m_iAutoWepSwitch;
pPlayer->m_iAutoWepSwitch = 1;
pPlayer->pev->weapons |= (1<<WEAPON_SUIT); pPlayer->pev->weapons |= (1<<WEAPON_SUIT);
addDefault = TRUE; addDefault = TRUE;
@ -569,6 +527,8 @@ void CHalfLifeMultiplay :: PlayerSpawn( CBasePlayer *pPlayer )
pPlayer->GiveNamedItem( "weapon_9mmhandgun" ); pPlayer->GiveNamedItem( "weapon_9mmhandgun" );
pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads
} }
pPlayer->m_iAutoWepSwitch = iAutoWepSwitch;
} }
//========================================================= //=========================================================
@ -605,16 +565,27 @@ int CHalfLifeMultiplay :: IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *p
//========================================================= //=========================================================
void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{ {
CBasePlayer* peKiller = NULL;
CBaseEntity* ktmp = CBaseEntity::Instance( pKiller );
if ( ktmp && ( ktmp->Classify() == CLASS_PLAYER ) )
peKiller = (CBasePlayer*)ktmp;
else if ( ktmp && ( ktmp->Classify() == CLASS_VEHICLE ) )
{
CBasePlayer* pDriver = ( (CFuncVehicle*)ktmp )->m_pDriver;
if ( pDriver != NULL )
{
peKiller = pDriver;
ktmp = pDriver;
pKiller = pDriver->pev;
}
}
DeathNotice( pVictim, pKiller, pInflictor ); DeathNotice( pVictim, pKiller, pInflictor );
pVictim->m_iDeaths += 1; pVictim->m_iDeaths += 1;
FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 ); FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 );
CBasePlayer *peKiller = NULL;
CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) )
peKiller = (CBasePlayer*)ktmp;
if ( pVictim->pev == pKiller ) if ( pVictim->pev == pKiller )
{ // killed self { // killed self
@ -819,6 +790,7 @@ void CHalfLifeMultiplay::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller,
WRITE_LONG( 7 | DRC_FLAG_DRAMATIC); // eventflags (priority and flags) WRITE_LONG( 7 | DRC_FLAG_DRAMATIC); // eventflags (priority and flags)
MESSAGE_END(); MESSAGE_END();
// Print a standard message // Print a standard message
// TODO: make this go direct to console // TODO: make this go direct to console
return; // just remove for now return; // just remove for now
@ -1332,7 +1304,8 @@ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle )
if ( strlen( com_token ) <= 0 ) if ( strlen( com_token ) <= 0 )
break; break;
strcpy( szMap, com_token ); strncpy( szMap, com_token, sizeof( szMap ) );
szMap[ sizeof( szMap ) - 1 ] = '\0';
// Any more tokens on this line? // Any more tokens on this line?
if ( COM_TokenWaiting( pFileList ) ) if ( COM_TokenWaiting( pFileList ) )
@ -1341,7 +1314,8 @@ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle )
if ( strlen( com_token ) > 0 ) if ( strlen( com_token ) > 0 )
{ {
hasbuffer = 1; hasbuffer = 1;
strcpy( szBuffer, com_token ); strncpy( szBuffer, com_token, sizeof( szBuffer ) );
szBuffer[ sizeof( szBuffer ) - 1 ] = '\0';
} }
} }
@ -1689,4 +1663,291 @@ void CHalfLifeMultiplay :: SendMOTDToClient( edict_t *client )
FREE_FILE( aFileList ); FREE_FILE( aFileList );
} }
void CHalfLifeMultiplay :: ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer )
{
// Set preferences
pPlayer->SetPrefsFromUserinfo( infobuffer );
}
//=========================================================
//=========================================================
// Busters Gamerules
//=========================================================
//=========================================================
#define EGON_BUSTING_TIME 10
bool IsBustingGame()
{
return sv_busters.value == 1;
}
bool IsPlayerBusting( CBaseEntity* pPlayer )
{
if ( !pPlayer || !pPlayer->IsPlayer() || !IsBustingGame() )
return FALSE;
return ( (CBasePlayer*)pPlayer )->HasPlayerItemFromID( WEAPON_EGON );
}
BOOL BustingCanHaveItem( CBasePlayer* pPlayer, CBaseEntity* pItem )
{
BOOL bIsWeaponOrAmmo = FALSE;
if ( strstr( STRING( pItem->pev->classname ), "weapon_" ) || strstr( STRING( pItem->pev->classname ), "ammo_" ) )
{
bIsWeaponOrAmmo = TRUE;
}
//Busting players can't have ammo nor weapons
if ( IsPlayerBusting( pPlayer ) && bIsWeaponOrAmmo )
return FALSE;
return TRUE;
}
//=========================================================
CMultiplayBusters::CMultiplayBusters()
{
m_flEgonBustingCheckTime = -1;
}
//=========================================================
void CMultiplayBusters::Think()
{
CheckForEgons();
CHalfLifeMultiplay::Think();
}
//=========================================================
int CMultiplayBusters::IPointsForKill( CBasePlayer* pAttacker, CBasePlayer* pKilled )
{
//If the attacker is busting, they get a point per kill
if ( IsPlayerBusting( pAttacker ) )
return 1;
//If the victim is busting, then the attacker gets a point
if ( IsPlayerBusting( pKilled ) )
return 2;
return 0;
}
//=========================================================
void CMultiplayBusters::PlayerKilled( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor )
{
if ( IsPlayerBusting( pVictim ) )
{
UTIL_ClientPrintAll( HUD_PRINTCENTER, "The Buster is dead!!" );
//Reset egon check time
m_flEgonBustingCheckTime = -1;
CBasePlayer *peKiller = NULL;
CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
if ( ktmp && ( ktmp->Classify() == CLASS_PLAYER ) )
{
peKiller = (CBasePlayer*)ktmp;
}
else if ( ktmp && ( ktmp->Classify() == CLASS_VEHICLE ) )
{
CBasePlayer *pDriver = ( (CFuncVehicle*)ktmp )->m_pDriver;
if ( pDriver != NULL )
{
peKiller = pDriver;
ktmp = pDriver;
pKiller = pDriver->pev;
}
}
if ( peKiller )
{
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s has has killed the Buster!\n", STRING( (CBasePlayer*)peKiller->pev->netname ) ) );
}
pVictim->pev->renderfx = kRenderFxNone;
pVictim->pev->rendercolor = g_vecZero;
//pVictim->pev->effects &= ~EF_BRIGHTFIELD;
}
CHalfLifeMultiplay::PlayerKilled( pVictim, pKiller, pInflictor );
}
//=========================================================
void CMultiplayBusters::DeathNotice( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pevInflictor )
{
//Only death notices that the Buster was involved in in Busting game mode
if ( !IsPlayerBusting( pVictim ) && !IsPlayerBusting( CBaseEntity::Instance( pKiller ) ) )
return;
CHalfLifeMultiplay::DeathNotice( pVictim, pKiller, pevInflictor );
}
//=========================================================
int CMultiplayBusters::WeaponShouldRespawn( CBasePlayerItem* pWeapon )
{
if ( pWeapon->m_iId == WEAPON_EGON )
return GR_WEAPON_RESPAWN_NO;
return CHalfLifeMultiplay::WeaponShouldRespawn( pWeapon );
}
//=========================================================
// CheckForEgons:
//Check to see if any player has an egon
//If they don't then get the lowest player on the scoreboard and give them one
//Then check to see if any weapon boxes out there has an egon, and delete it
//=========================================================
void CMultiplayBusters::CheckForEgons()
{
if ( m_flEgonBustingCheckTime <= 0.0f )
{
m_flEgonBustingCheckTime = gpGlobals->time + EGON_BUSTING_TIME;
return;
}
if ( m_flEgonBustingCheckTime <= gpGlobals->time )
{
m_flEgonBustingCheckTime = -1.0f;
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer* pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i );
//Someone is busting, no need to continue
if ( IsPlayerBusting( pPlayer ) )
return;
}
int bBestFrags = 9999;
CBasePlayer* pBestPlayer = NULL;
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer* pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i );
if ( pPlayer && pPlayer->pev->frags <= bBestFrags )
{
bBestFrags = pPlayer->pev->frags;
pBestPlayer = pPlayer;
}
}
if ( pBestPlayer )
{
pBestPlayer->GiveNamedItem( "weapon_egon" );
CBaseEntity* pEntity = NULL;
//Find a weaponbox that includes an Egon, then destroy it
while ( ( pEntity = UTIL_FindEntityByClassname( pEntity, "weaponbox" ) ) != NULL )
{
CWeaponBox* pWeaponBox = (CWeaponBox*)pEntity;
if ( pWeaponBox )
{
CBasePlayerItem* pWeapon;
for ( int i = 0; i < MAX_ITEM_TYPES; i++ )
{
pWeapon = pWeaponBox->m_rgpPlayerItems[i];
while ( pWeapon )
{
//There you are, bye box
if ( pWeapon->m_iId == WEAPON_EGON )
{
pWeaponBox->Kill();
break;
}
pWeapon = pWeapon->m_pNext;
}
}
}
}
}
}
}
//=========================================================
BOOL CMultiplayBusters::CanHavePlayerItem( CBasePlayer* pPlayer, CBasePlayerItem* pItem )
{
//Buster cannot have more weapons nor ammo
if ( BustingCanHaveItem( pPlayer, pItem ) == FALSE )
{
return FALSE;
}
return CHalfLifeMultiplay::CanHavePlayerItem( pPlayer, pItem );
}
//=========================================================
BOOL CMultiplayBusters::CanHaveItem( CBasePlayer* pPlayer, CItem* pItem )
{
//Buster cannot have more weapons nor ammo
if (BustingCanHaveItem( pPlayer, pItem ) == FALSE )
{
return FALSE;
}
return CHalfLifeMultiplay::CanHaveItem( pPlayer, pItem );
}
//=========================================================
void CMultiplayBusters::PlayerGotWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pWeapon )
{
if ( pWeapon->m_iId == WEAPON_EGON )
{
pPlayer->RemoveAllItems( false );
UTIL_ClientPrintAll( HUD_PRINTCENTER, "Long live the new Buster!" );
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s is busting!\n", STRING( (CBasePlayer*)pPlayer->pev->netname ) ) );
SetPlayerModel( pPlayer );
pPlayer->pev->health = pPlayer->pev->max_health;
pPlayer->pev->armorvalue = 100;
pPlayer->pev->renderfx = kRenderFxGlowShell;
pPlayer->pev->renderamt = 25;
pPlayer->pev->rendercolor = Vector( 0, 75, 250 );
CBasePlayerWeapon *pEgon = (CBasePlayerWeapon*)pWeapon;
pEgon->m_iDefaultAmmo = 100;
pPlayer->m_rgAmmo[pEgon->m_iPrimaryAmmoType] = pEgon->m_iDefaultAmmo;
g_engfuncs.pfnSetClientKeyValue( pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", "ivan" );
}
}
void CMultiplayBusters::ClientUserInfoChanged( CBasePlayer* pPlayer, char* infobuffer )
{
SetPlayerModel( pPlayer );
// Set preferences
pPlayer->SetPrefsFromUserinfo( infobuffer );
}
void CMultiplayBusters::PlayerSpawn( CBasePlayer* pPlayer )
{
CHalfLifeMultiplay::PlayerSpawn( pPlayer );
SetPlayerModel( pPlayer );
}
void CMultiplayBusters::SetPlayerModel( CBasePlayer* pPlayer )
{
if ( IsPlayerBusting( pPlayer ) )
{
g_engfuncs.pfnSetClientKeyValue( pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", "ivan" );
}
else
{
g_engfuncs.pfnSetClientKeyValue( pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", "skeleton" );
}
}

View file

@ -462,7 +462,7 @@ void CNihilanth :: DyingThink( void )
{ {
if (m_pBall->pev->renderamt > 0) if (m_pBall->pev->renderamt > 0)
{ {
m_pBall->pev->renderamt = max( 0, m_pBall->pev->renderamt - 2); m_pBall->pev->renderamt = max<float>( 0, m_pBall->pev->renderamt - 2);
} }
else else
{ {
@ -884,7 +884,7 @@ void CNihilanth :: HuntThink( void )
} }
else else
{ {
m_flAdj = min( m_flAdj + 10, 1000 ); m_flAdj = min( m_flAdj + 10.0f, 1000.0f );
} }
} }

View file

@ -53,6 +53,8 @@ extern void respawn(entvars_t *pev, BOOL fCopyCorpse);
extern Vector VecBModelOrigin(entvars_t *pevBModel ); extern Vector VecBModelOrigin(entvars_t *pevBModel );
extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer ); extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer );
extern bool IsBustingGame();
// the world node graph // the world node graph
extern CGraph WorldGraph; extern CGraph WorldGraph;
@ -718,8 +720,20 @@ void CBasePlayer::PackDeadPlayerItems( void )
case GR_PLR_DROP_GUN_ACTIVE: case GR_PLR_DROP_GUN_ACTIVE:
if ( m_pActiveItem && pPlayerItem == m_pActiveItem ) if ( m_pActiveItem && pPlayerItem == m_pActiveItem )
{ {
CBasePlayerWeapon *pWeapon = (CBasePlayerWeapon*)pPlayerItem;
int nIndex = iPW++;
// this is the active item. Pack it. // this is the active item. Pack it.
rgpPackWeapons[ iPW++ ] = (CBasePlayerWeapon *)pPlayerItem; rgpPackWeapons[nIndex] = pWeapon;
//Reload the weapon before dropping it if we have ammo
int j = min( pWeapon->iMaxClip() - pWeapon->m_iClip, m_rgAmmo[pWeapon->m_iPrimaryAmmoType] );
// Add them to the clip
pWeapon->m_iClip += j;
m_rgAmmo[pWeapon->m_iPrimaryAmmoType] -= j;
TabulateAmmo();
} }
break; break;
@ -783,24 +797,69 @@ void CBasePlayer::PackDeadPlayerItems( void )
iPA = 0; iPA = 0;
iPW = 0; iPW = 0;
// pack the ammo if ( IsBustingGame() )
while ( iPackAmmo[ iPA ] != -1 )
{ {
pWeaponBox->PackAmmo( MAKE_STRING( CBasePlayerItem::AmmoInfoArray[ iPackAmmo[ iPA ] ].pszName ), m_rgAmmo[ iPackAmmo[ iPA ] ] ); if ( HasNamedPlayerItem( "weapon_egon" ) )
iPA++; {
} for ( i = 0; i < MAX_ITEM_TYPES; i++ )
{
CBasePlayerItem *pItem = m_rgpPlayerItems[i];
// now pack all of the items in the lists if ( pItem )
while ( rgpPackWeapons[ iPW ] ) {
if ( !strcmp( "weapon_egon", STRING( pItem->pev->classname ) ) )
{
pWeaponBox->PackWeapon( pItem );
SET_MODEL( ENT( pWeaponBox->pev ), "models/w_egon.mdl" );
pWeaponBox->pev->velocity = vec3_t( 0, 0, 0 );
pWeaponBox->pev->renderfx = kRenderFxGlowShell;
pWeaponBox->pev->renderamt = 25;
pWeaponBox->pev->rendercolor = Vector( 0, 75, 250 );
break;
}
}
}
}
}
else
{ {
// weapon unhooked from the player. Pack it into der box. bool bPackItems = TRUE;
pWeaponBox->PackWeapon( rgpPackWeapons[ iPW ] );
iPW++; if ( iAmmoRules == GR_PLR_DROP_AMMO_ACTIVE && iWeaponRules == GR_PLR_DROP_GUN_ACTIVE )
{
if ( FClassnameIs( rgpPackWeapons[0]->pev, "weapon_satchel" ) && ( iPackAmmo[0] == -1 || ( m_rgAmmo[iPackAmmo[0]] == 0 ) ) )
{
bPackItems = FALSE;
}
}
if ( bPackItems )
{
// pack the ammo
while ( iPackAmmo[iPA] != -1 )
{
pWeaponBox->PackAmmo( MAKE_STRING( CBasePlayerItem::AmmoInfoArray[iPackAmmo[iPA]].pszName ), m_rgAmmo[iPackAmmo[iPA]] );
iPA++;
}
// now pack all of the items in the lists
while ( rgpPackWeapons[iPW] )
{
// weapon unhooked from the player. Pack it into der box.
pWeaponBox->PackWeapon( rgpPackWeapons[iPW] );
iPW++;
}
}
pWeaponBox->pev->velocity = pev->velocity * 1.2;// weaponbox has player's velocity, then some.
} }
pWeaponBox->pev->velocity = pev->velocity * 1.2;// weaponbox has player's velocity, then some.
RemoveAllItems( TRUE );// now strip off everything that wasn't handled by the code above. RemoveAllItems( TRUE );// now strip off everything that wasn't handled by the code above.
} }
@ -891,7 +950,7 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
SetAnimation( PLAYER_DIE ); SetAnimation( PLAYER_DIE );
m_iRespawnFrames = 0; m_flRespawnTimer = 0.0f;
pev->modelindex = g_ulModelIndexPlayer; // don't use eyes pev->modelindex = g_ulModelIndexPlayer; // don't use eyes
@ -924,13 +983,19 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
WRITE_BYTE(0); WRITE_BYTE(0);
MESSAGE_END(); MESSAGE_END();
//Adrian: always make the players non-solid in multiplayer when they die
if ( g_pGameRules->IsMultiplayer() )
{
pev->solid = SOLID_NOT;
}
// UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12 // UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12
// UTIL_ScreenFade( edict(), Vector(128,0,0), 6, 15, 255, FFADE_OUT | FFADE_MODULATE ); // UTIL_ScreenFade( edict(), Vector(128,0,0), 6, 15, 255, FFADE_OUT | FFADE_MODULATE );
if ( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS ) if ( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS )
{ {
pev->solid = SOLID_NOT; pev->solid = SOLID_NOT;
GibMonster(); // This clears pev->model GibMonster(); // This clears pev->model
pev->effects |= EF_NODRAW; pev->effects |= EF_NODRAW;
return; return;
@ -1028,6 +1093,9 @@ void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim )
if (pev->sequence == animDesired) if (pev->sequence == animDesired)
return; return;
//ALERT(at_console, "Set die animation to %d\n", animDesired);
pev->gaitsequence = 0; pev->gaitsequence = 0;
pev->sequence = animDesired; pev->sequence = animDesired;
pev->frame = 0; pev->frame = 0;
@ -1111,6 +1179,7 @@ void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim )
return; return;
//ALERT( at_console, "Set animation to %d\n", animDesired ); //ALERT( at_console, "Set animation to %d\n", animDesired );
// Reset to first frame of desired animation // Reset to first frame of desired animation
pev->sequence = animDesired; pev->sequence = animDesired;
pev->frame = 0; pev->frame = 0;
@ -1292,18 +1361,29 @@ void CBasePlayer::PlayerDeathThink(void)
{ {
StudioFrameAdvance( ); StudioFrameAdvance( );
m_iRespawnFrames++; // Note, these aren't necessarily real "frames", so behavior is dependent on # of client movement commands m_flRespawnTimer += gpGlobals->frametime;
if ( m_iRespawnFrames < 120 ) // Animations should be no longer than this if ( m_flRespawnTimer < 4.0f ) // 120 frames at 30fps -- animations should be no longer than this
return; return;
} }
if ( pev->deadflag == DEAD_DYING )
{
//Once we finish animating, if we're in multiplayer just make a copy of our body right away.
if ( m_fSequenceFinished && g_pGameRules->IsMultiplayer() && pev->movetype == MOVETYPE_NONE )
{
CopyToBodyQue( pev );
pev->modelindex = 0;
}
pev->deadflag = DEAD_DEAD;
}
// once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore // once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore
// this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn // this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn
if ( pev->movetype != MOVETYPE_NONE && FBitSet(pev->flags, FL_ONGROUND) ) if ( pev->movetype != MOVETYPE_NONE && FBitSet(pev->flags, FL_ONGROUND) )
pev->movetype = MOVETYPE_NONE; pev->movetype = MOVETYPE_NONE;
if (pev->deadflag == DEAD_DYING)
pev->deadflag = DEAD_DEAD;
StopAnimation(); StopAnimation();
@ -1330,7 +1410,7 @@ void CBasePlayer::PlayerDeathThink(void)
// if the player has been dead for one second longer than allowed by forcerespawn, // if the player has been dead for one second longer than allowed by forcerespawn,
// forcerespawn isn't on. Send the player off to an intermission camera until they // forcerespawn isn't on. Send the player off to an intermission camera until they
// choose to respawn. // choose to respawn.
if ( g_pGameRules->IsMultiplayer() && ( gpGlobals->time > (m_fDeadTime + 6) ) && !(m_afPhysicsFlags & PFLAG_OBSERVER) ) if ( g_pGameRules->IsMultiplayer() && ( gpGlobals->time > (m_fDeadTime + 6) ) && !(m_afPhysicsFlags & PFLAG_OBSERVER) )
{ {
// go to dead camera. // go to dead camera.
StartDeathCam(); StartDeathCam();
@ -1345,7 +1425,7 @@ void CBasePlayer::PlayerDeathThink(void)
return; return;
pev->button = 0; pev->button = 0;
m_iRespawnFrames = 0; m_flRespawnTimer = 0.0f;
//ALERT(at_console, "Respawn\n"); //ALERT(at_console, "Respawn\n");
@ -1515,6 +1595,9 @@ void CBasePlayer::PlayerUse ( void )
{ {
m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = TRAIN_NEW|TRAIN_OFF; m_iTrain = TRAIN_NEW|TRAIN_OFF;
CBaseEntity *pTrain = CBaseEntity::Instance( pev->groundentity );
if (pTrain && (pTrain->Classify() == CLASS_VEHICLE))
((CFuncVehicle*)pTrain)->m_pDriver = NULL;
return; return;
} }
else else
@ -1526,7 +1609,13 @@ void CBasePlayer::PlayerUse ( void )
m_afPhysicsFlags |= PFLAG_ONTRAIN; m_afPhysicsFlags |= PFLAG_ONTRAIN;
m_iTrain = TrainSpeed(pTrain->pev->speed, pTrain->pev->impulse); m_iTrain = TrainSpeed(pTrain->pev->speed, pTrain->pev->impulse);
m_iTrain |= TRAIN_NEW; m_iTrain |= TRAIN_NEW;
EMIT_SOUND( ENT(pev), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM); if (pTrain->Classify() == CLASS_VEHICLE)
{
EMIT_SOUND( ENT(pev), CHAN_ITEM, "plats/vehicle_ignition.wav", 0.8, ATTN_NORM);
((CFuncVehicle*)pTrain)->m_pDriver = this;
}
else
EMIT_SOUND( ENT(pev), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM);
return; return;
} }
} }
@ -1646,6 +1735,16 @@ void CBasePlayer::Jump()
{ {
pev->velocity = pev->velocity + pev->basevelocity; pev->velocity = pev->velocity + pev->basevelocity;
} }
// JoshA: CS behaviour does this for tracktrain + train as well,
// but let's just do this for func_vehicle to avoid breaking existing content.
//
// If you're standing on a moving train... then add the velocity of the train to yours.
if ( pevGround && ( /*(!strcmp( "func_tracktrain", STRING(pevGround->classname))) ||
(!strcmp( "func_train", STRING(pevGround->classname))) ) ||*/
(!strcmp( "func_vehicle", STRING(pevGround->classname)))) )
pev->velocity = pev->velocity + pevGround->velocity;
} }
@ -1923,28 +2022,59 @@ void CBasePlayer::PreThink(void)
//ALERT( at_error, "In train mode with no train!\n" ); //ALERT( at_error, "In train mode with no train!\n" );
m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = TRAIN_NEW|TRAIN_OFF; m_iTrain = TRAIN_NEW|TRAIN_OFF;
if (pTrain->Classify() == CLASS_VEHICLE)
((CFuncVehicle*)pTrain)->m_pDriver = NULL;
return; return;
} }
} }
else if ( !FBitSet( pev->flags, FL_ONGROUND ) || FBitSet( pTrain->pev->spawnflags, SF_TRACKTRAIN_NOCONTROL ) || (pev->button & (IN_MOVELEFT|IN_MOVERIGHT) ) ) else if ( !FBitSet( pev->flags, FL_ONGROUND ) || FBitSet( pTrain->pev->spawnflags, SF_TRACKTRAIN_NOCONTROL ) || ((pev->button & (IN_MOVELEFT|IN_MOVERIGHT) ) && pTrain->Classify() != CLASS_VEHICLE) )
{ {
// Turn off the train if you jump, strafe, or the train controls go dead // Turn off the train if you jump, strafe, or the train controls go dead
// and it isn't a func_vehicle.
m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = TRAIN_NEW|TRAIN_OFF; m_iTrain = TRAIN_NEW|TRAIN_OFF;
if (pTrain->Classify() == CLASS_VEHICLE)
((CFuncVehicle*)pTrain)->m_pDriver = NULL;
return; return;
} }
pev->velocity = g_vecZero; pev->velocity = g_vecZero;
vel = 0; vel = 0;
if ( m_afButtonPressed & IN_FORWARD ) if (pTrain->Classify() == CLASS_VEHICLE)
{ {
vel = 1; if ( pev->button & IN_FORWARD )
pTrain->Use( this, this, USE_SET, (float)vel ); {
vel = 1;
pTrain->Use( this, this, USE_SET, (float)vel );
}
if ( pev->button & IN_BACK )
{
vel = -1;
pTrain->Use( this, this, USE_SET, (float)vel );
}
if ( pev->button & IN_MOVELEFT)
{
vel = 20;
pTrain->Use( this, this, USE_SET, (float)vel );
}
if ( pev->button & IN_MOVERIGHT)
{
vel = 30;
pTrain->Use( this, this, USE_SET, (float)vel );
}
} }
else if ( m_afButtonPressed & IN_BACK ) else
{ {
vel = -1; if ( m_afButtonPressed & IN_FORWARD )
pTrain->Use( this, this, USE_SET, (float)vel ); {
vel = 1;
pTrain->Use( this, this, USE_SET, (float)vel );
}
else if ( m_afButtonPressed & IN_BACK )
{
vel = -1;
pTrain->Use( this, this, USE_SET, (float)vel );
}
} }
if (vel) if (vel)
@ -2674,23 +2804,23 @@ pt_end:
if ( gun && gun->UseDecrement() ) if ( gun && gun->UseDecrement() )
{ {
gun->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0 ); gun->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0f );
gun->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001 ); gun->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001f );
if ( gun->m_flTimeWeaponIdle != 1000 ) if ( gun->m_flTimeWeaponIdle != 1000 )
{ {
gun->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001 ); gun->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001f );
} }
if ( gun->pev->fuser1 != 1000 ) if ( gun->pev->fuser1 != 1000 )
{ {
gun->pev->fuser1 = max( gun->pev->fuser1 - gpGlobals->frametime, -0.001 ); gun->pev->fuser1 = max( gun->pev->fuser1 - gpGlobals->frametime, -0.001f );
} }
// Only decrement if not flagged as NO_DECREMENT // Only decrement if not flagged as NO_DECREMENT
// if ( gun->m_flPumpTime != 1000 ) // if ( gun->m_flPumpTime != 1000 )
// { // {
// gun->m_flPumpTime = max( gun->m_flPumpTime - gpGlobals->frametime, -0.001 ); // gun->m_flPumpTime = max( gun->m_flPumpTime - gpGlobals->frametime, -0.001f );
// } // }
} }
@ -2764,6 +2894,8 @@ edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer )
CBaseEntity *pSpot; CBaseEntity *pSpot;
edict_t *player; edict_t *player;
int nNumRandomSpawnsToTry = 10;
player = pPlayer->edict(); player = pPlayer->edict();
// choose a info_player_deathmatch point // choose a info_player_deathmatch point
@ -2778,9 +2910,21 @@ edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer )
} }
else if ( g_pGameRules->IsDeathmatch() ) else if ( g_pGameRules->IsDeathmatch() )
{ {
if (NULL == g_pLastSpawn)
{
int nNumSpawnPoints = 0;
CBaseEntity* pEnt = UTIL_FindEntityByClassname(NULL, "info_player_deathmatch");
while (NULL != pEnt)
{
nNumSpawnPoints++;
pEnt = UTIL_FindEntityByClassname(pEnt, "info_player_deathmatch");
}
nNumRandomSpawnsToTry = nNumSpawnPoints;
}
pSpot = g_pLastSpawn; pSpot = g_pLastSpawn;
// Randomize the start spot // Randomize the start spot
for ( int i = RANDOM_LONG(1,5); i > 0; i-- ) for ( int i = RANDOM_LONG(1, nNumRandomSpawnsToTry - 1); i > 0; i-- )
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" ); pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
if ( FNullEnt( pSpot ) ) // skip over the null point if ( FNullEnt( pSpot ) ) // skip over the null point
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" ); pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
@ -2849,6 +2993,8 @@ ReturnSpot:
void CBasePlayer::Spawn( void ) void CBasePlayer::Spawn( void )
{ {
m_flStartCharge = gpGlobals->time;
pev->classname = MAKE_STRING("player"); pev->classname = MAKE_STRING("player");
pev->health = 100; pev->health = 100;
pev->armorvalue = 0; pev->armorvalue = 0;
@ -3056,6 +3202,9 @@ int CBasePlayer::Restore( CRestore &restore )
RenewItems(); RenewItems();
//Resync ammo data so you can reload - Solokiller
TabulateAmmo();
#if defined( CLIENT_WEAPONS ) #if defined( CLIENT_WEAPONS )
// HACK: This variable is saved/restored in CBaseMonster as a time variable, but we're using it // HACK: This variable is saved/restored in CBaseMonster as a time variable, but we're using it
// as just a counter. Ideally, this needs its own variable that's saved as a plain float. // as just a counter. Ideally, this needs its own variable that's saved as a plain float.
@ -3063,6 +3212,12 @@ int CBasePlayer::Restore( CRestore &restore )
m_flNextAttack = UTIL_WeaponTimeBase(); m_flNextAttack = UTIL_WeaponTimeBase();
#endif #endif
// Force a flashlight update for the HUD
if ( m_flFlashLightTime == 0 )
{
m_flFlashLightTime = 1;
}
return status; return status;
} }
@ -3424,8 +3579,6 @@ void CBasePlayer :: ForceClientDllUpdate( void )
ImpulseCommands ImpulseCommands
============ ============
*/ */
extern float g_flWeaponCheat;
void CBasePlayer::ImpulseCommands( ) void CBasePlayer::ImpulseCommands( )
{ {
TraceResult tr;// UNDONE: kill me! This is temporary for PreAlpha CDs TraceResult tr;// UNDONE: kill me! This is temporary for PreAlpha CDs
@ -3507,7 +3660,7 @@ void CBasePlayer::ImpulseCommands( )
void CBasePlayer::CheatImpulseCommands( int iImpulse ) void CBasePlayer::CheatImpulseCommands( int iImpulse )
{ {
#if !defined( HLDEMO_BUILD ) #if !defined( HLDEMO_BUILD )
if ( g_flWeaponCheat == 0.0 ) if ( CVAR_GET_FLOAT( "sv_cheats" ) == 0.0 )
{ {
return; return;
} }
@ -3755,7 +3908,7 @@ int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem )
pev->viewmodel = 0; pev->viewmodel = 0;
pev->weaponmodel = 0; pev->weaponmodel = 0;
} }
else if ( m_pLastItem == pItem ) if ( m_pLastItem == pItem )
m_pLastItem = NULL; m_pLastItem = NULL;
CBasePlayerItem *pPrev = m_rgpPlayerItems[pItem->iItemSlot()]; CBasePlayerItem *pPrev = m_rgpPlayerItems[pItem->iItemSlot()];
@ -4180,6 +4333,22 @@ void CBasePlayer :: UpdateClientData( void )
} }
} }
void CBasePlayer :: SetPrefsFromUserinfo( char * infobuffer )
{
const char * pszKeyVal;
// Set autoswitch preference
pszKeyVal = g_engfuncs.pfnInfoKeyValue( infobuffer, "cl_autowepswitch" );
if ( FStrEq( pszKeyVal, "" ) )
{
m_iAutoWepSwitch = 1;
}
else
{
m_iAutoWepSwitch = atoi( pszKeyVal );
}
}
//========================================================= //=========================================================
// FBecomeProne - Overridden for the player to set the proper // FBecomeProne - Overridden for the player to set the proper
@ -4317,7 +4486,7 @@ Vector CBasePlayer :: GetAutoaimVector( float flDelta )
// m_vecAutoAim = m_vecAutoAim * 0.99; // m_vecAutoAim = m_vecAutoAim * 0.99;
// Don't send across network if sv_aim is 0 // Don't send across network if sv_aim is 0
if ( g_psv_aim->value != 0 ) if ( g_psv_aim->value != 0 && g_psv_allow_autoaim->value != 0 )
{ {
if ( m_vecAutoAim.x != m_lastx || if ( m_vecAutoAim.x != m_lastx ||
m_vecAutoAim.y != m_lasty ) m_vecAutoAim.y != m_lasty )
@ -4345,7 +4514,7 @@ Vector CBasePlayer :: AutoaimDeflection( Vector &vecSrc, float flDist, float flD
edict_t *bestent; edict_t *bestent;
TraceResult tr; TraceResult tr;
if ( g_psv_aim->value == 0 ) if ( g_psv_aim->value == 0 || g_psv_allow_autoaim->value == 0 )
{ {
m_fOnTarget = FALSE; m_fOnTarget = FALSE;
return g_vecZero; return g_vecZero;
@ -4642,6 +4811,33 @@ BOOL CBasePlayer::HasNamedPlayerItem( const char *pszItemName )
return FALSE; return FALSE;
} }
//=========================================================
// HasPlayerItemFromID
// Just compare IDs, rather than classnames
//=========================================================
BOOL CBasePlayer::HasPlayerItemFromID( int nID )
{
CBasePlayerItem* pItem;
int i;
for ( i = 0; i < MAX_ITEM_TYPES; i++ )
{
pItem = m_rgpPlayerItems[i];
while ( pItem )
{
if ( pItem->m_iId == nID )
{
return TRUE;
}
pItem = pItem->m_pNext;
}
}
return FALSE;
}
//========================================================= //=========================================================
// //
//========================================================= //=========================================================

View file

@ -189,7 +189,7 @@ public:
Vector m_vecAutoAim; Vector m_vecAutoAim;
BOOL m_fOnTarget; BOOL m_fOnTarget;
int m_iDeaths; int m_iDeaths;
float m_iRespawnFrames; // used in PlayerDeathThink() to make sure players can always respawn float m_flRespawnTimer; // used in PlayerDeathThink() to make sure players can always respawn
int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE
@ -233,6 +233,8 @@ public:
// JOHN: sends custom messages if player HUD data has changed (eg health, ammo) // JOHN: sends custom messages if player HUD data has changed (eg health, ammo)
virtual void UpdateClientData( void ); virtual void UpdateClientData( void );
void SetPrefsFromUserinfo( char * infobuffer );
static TYPEDESCRIPTION m_playerSaveData[]; static TYPEDESCRIPTION m_playerSaveData[];
// Player is moved across the transition by other means // Player is moved across the transition by other means
@ -265,6 +267,7 @@ public:
void DropPlayerItem ( char *pszItemName ); void DropPlayerItem ( char *pszItemName );
BOOL HasPlayerItem( CBasePlayerItem *pCheckItem ); BOOL HasPlayerItem( CBasePlayerItem *pCheckItem );
BOOL HasNamedPlayerItem( const char *pszItemName ); BOOL HasNamedPlayerItem( const char *pszItemName );
BOOL HasPlayerItemFromID( int nID );
BOOL HasWeapons( void );// do I have ANY weapons? BOOL HasWeapons( void );// do I have ANY weapons?
void SelectPrevItem( int iItem ); void SelectPrevItem( int iItem );
void SelectNextItem( int iItem ); void SelectNextItem( int iItem );
@ -323,6 +326,7 @@ public:
float m_flNextChatTime; float m_flNextChatTime;
int m_iAutoWepSwitch;
}; };
#define AUTOAIM_2DEGREES 0.0348994967025 #define AUTOAIM_2DEGREES 0.0348994967025

View file

@ -171,7 +171,7 @@ void CPython::PrimaryAttack()
Reload( ); Reload( );
else else
{ {
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM); PlayEmptySound();
m_flNextPrimaryAttack = 0.15; m_flNextPrimaryAttack = 0.15;
} }

View file

@ -111,8 +111,9 @@ CRpgRocket *CRpgRocket::CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBa
pRocket->pev->angles = vecAngles; pRocket->pev->angles = vecAngles;
pRocket->Spawn(); pRocket->Spawn();
pRocket->SetTouch( &CRpgRocket::RocketTouch ); pRocket->SetTouch( &CRpgRocket::RocketTouch );
pRocket->m_pLauncher = pLauncher;// remember what RPG fired me.
pRocket->m_pLauncher->m_cActiveRockets++;// register this missile as active for the launcher pLauncher->m_cActiveRockets++;
pRocket->m_hLauncher = pLauncher;// remember what RPG fired me.
pRocket->pev->owner = pOwner->edict(); pRocket->pev->owner = pOwner->edict();
return pRocket; return pRocket;
@ -152,16 +153,36 @@ void CRpgRocket :: Spawn( void )
//========================================================= //=========================================================
void CRpgRocket :: RocketTouch ( CBaseEntity *pOther ) void CRpgRocket :: RocketTouch ( CBaseEntity *pOther )
{ {
if ( m_pLauncher ) //ALERT( at_console, "RpgRocket RocketTouch, m_pLauncher: %u\n", GetLauncher() );
if ( GetLauncher() )
{ {
// my launcher is still around, tell it I'm dead. // my launcher is still around, tell it I'm dead.
m_pLauncher->m_cActiveRockets--; GetLauncher()->m_cActiveRockets--;
m_hLauncher = NULL;
} }
STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" ); STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" );
ExplodeTouch( pOther ); ExplodeTouch( pOther );
} }
//=========================================================
void CRpgRocket::Explode( TraceResult *pTrace, int bitsDamageType )
{
//ALERT( at_console, "RpgRocket Explode, m_pLauncher: %u\n", GetLauncher() );
STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav");
if ( GetLauncher() )
{
// my launcher is still around, tell it I'm dead.
GetLauncher()->m_cActiveRockets--;
m_hLauncher = NULL;
}
CGrenade::Explode( pTrace, bitsDamageType );
}
//========================================================= //=========================================================
//========================================================= //=========================================================
void CRpgRocket :: Precache( void ) void CRpgRocket :: Precache( void )
@ -205,6 +226,14 @@ void CRpgRocket :: IgniteThink( void )
} }
CRpg* CRpgRocket::GetLauncher()
{
if ( !m_hLauncher )
return NULL;
return (CRpg*)( (CBaseEntity*)m_hLauncher );
}
void CRpgRocket :: FollowThink( void ) void CRpgRocket :: FollowThink( void )
{ {
CBaseEntity *pOther = NULL; CBaseEntity *pOther = NULL;
@ -221,8 +250,17 @@ void CRpgRocket :: FollowThink( void )
// Examine all entities within a reasonable radius // Examine all entities within a reasonable radius
while ((pOther = UTIL_FindEntityByClassname( pOther, "laser_spot" )) != NULL) while ((pOther = UTIL_FindEntityByClassname( pOther, "laser_spot" )) != NULL)
{ {
UTIL_TraceLine ( pev->origin, pOther->pev->origin, dont_ignore_monsters, ENT(pev), &tr ); Vector vSpotLocation = pOther->pev->origin;
// ALERT( at_console, "%f\n", tr.flFraction );
if( UTIL_PointContents( vSpotLocation ) == CONTENTS_SKY )
{
//ALERT( at_console, "laser spot is in the sky...\n");
}
UTIL_TraceLine ( pev->origin, vSpotLocation, dont_ignore_monsters, ENT(pev), &tr );
//ALERT( at_console, "fraction: %f\n", tr.flFraction );
if (tr.flFraction >= 0.90) if (tr.flFraction >= 0.90)
{ {
vecDir = pOther->pev->origin - pev->origin; vecDir = pOther->pev->origin - pev->origin;
@ -274,7 +312,27 @@ void CRpgRocket :: FollowThink( void )
Detonate( ); Detonate( );
} }
} }
// ALERT( at_console, "%.0f\n", flSpeed );
if( GetLauncher() )
{
float flDistance = ( pev->origin - GetLauncher()->pev->origin ).Length();
// if we've travelled more than max distance the player can send a spot, stop tracking the original launcher (allow it to reload)
if( flDistance > 8192.0f || gpGlobals->time - m_flIgniteTime > 6.0f )
{
//ALERT( at_console, "RPG too far (%f)!\n", flDistance );
GetLauncher()->m_cActiveRockets--;
m_hLauncher = NULL;
}
//ALERT( at_console, "%.0f, m_pLauncher: %u, flDistance: %f\n", flSpeed, GetLauncher(), flDistance );
}
if( (UTIL_PointContents(pev->origin) == CONTENTS_SKY ) )
{
//ALERT( at_console, "Rocket is in the sky, detonating...\n");
Detonate();
}
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
} }
@ -284,6 +342,8 @@ void CRpgRocket :: FollowThink( void )
void CRpg::Reload( void ) void CRpg::Reload( void )
{ {
//ALERT( at_console, "RPG Reload, m_cActiveRockets: %d, m_fSpotActive: %d\n", m_cActiveRockets, m_fSpotActive );
int iResult; int iResult;
if ( m_iClip == 1 ) if ( m_iClip == 1 )
@ -309,6 +369,8 @@ void CRpg::Reload( void )
if ( m_cActiveRockets && m_fSpotActive ) if ( m_cActiveRockets && m_fSpotActive )
{ {
//ALERT( at_console, "RPG reload failed, m_cActiveRockets: %d, m_fSpotActive: %d\n", m_cActiveRockets, m_fSpotActive );
// no reloading when there are active missiles tracking the designator. // no reloading when there are active missiles tracking the designator.
// ward off future autoreload attempts by setting next attack time into the future for a bit. // ward off future autoreload attempts by setting next attack time into the future for a bit.
return; return;
@ -385,7 +447,7 @@ int CRpg::GetItemInfo(ItemInfo *p)
p->iSlot = 3; p->iSlot = 3;
p->iPosition = 0; p->iPosition = 0;
p->iId = m_iId = WEAPON_RPG; p->iId = m_iId = WEAPON_RPG;
p->iFlags = 0; p->iFlags = ITEM_FLAG_NOAUTOSWITCHTO;
p->iWeight = RPG_WEIGHT; p->iWeight = RPG_WEIGHT;
return 1; return 1;
@ -481,6 +543,8 @@ void CRpg::PrimaryAttack()
m_flNextPrimaryAttack = GetNextAttackDelay(1.5); m_flNextPrimaryAttack = GetNextAttackDelay(1.5);
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5;
ResetEmptySound();
} }
else else
{ {
@ -510,8 +574,6 @@ void CRpg::WeaponIdle( void )
{ {
UpdateSpot( ); UpdateSpot( );
ResetEmptySound( );
if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() ) if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return; return;
@ -538,6 +600,7 @@ void CRpg::WeaponIdle( void )
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0;
} }
ResetEmptySound( );
SendWeaponAnim( iAnim ); SendWeaponAnim( iAnim );
} }
else else

View file

@ -176,7 +176,7 @@ LINK_ENTITY_TO_CLASS( weapon_satchel, CSatchel );
//========================================================= //=========================================================
int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal ) int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal )
{ {
CSatchel *pSatchel; CSatchel* pSatchel = NULL;
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
if ( bIsMultiplayer() ) if ( bIsMultiplayer() )
@ -186,7 +186,26 @@ int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal )
{ {
pSatchel = (CSatchel *)pOriginal; pSatchel = (CSatchel *)pOriginal;
if ( pSatchel->m_chargeReady != 0 ) if ( pOriginal->m_pPlayer == NULL )
return TRUE;
int nSatchelsInPocket = pSatchel->m_pPlayer->m_rgAmmo[ pSatchel->PrimaryAmmoIndex() ];
int nNumSatchels = 0;
CBaseEntity* pLiveSatchel = NULL;
while ( ( pLiveSatchel = UTIL_FindEntityInSphere( pLiveSatchel, pOriginal->m_pPlayer->pev->origin, 4096 ) ) != NULL )
{
if ( FClassnameIs( pLiveSatchel->pev, "monster_satchel" ) )
{
if ( pLiveSatchel->pev->owner == pOriginal->m_pPlayer->edict() )
{
nNumSatchels++;
}
}
}
if ( pSatchel->m_chargeReady != 0 && ( nSatchelsInPocket + nNumSatchels ) >= SATCHEL_MAX_CARRY )
{ {
// player has some satchels deployed. Refuse to add more. // player has some satchels deployed. Refuse to add more.
return FALSE; return FALSE;
@ -331,15 +350,18 @@ void CSatchel::Holster( int skiplocal /* = 0 */ )
void CSatchel::PrimaryAttack() void CSatchel::PrimaryAttack()
{ {
switch (m_chargeReady) // we're reloading, don't allow fire
if( m_chargeReady != 2 )
{
Throw();
}
}
void CSatchel::SecondaryAttack( void )
{
if ( m_chargeReady == 1 )
{ {
case 0:
{
Throw( );
}
break;
case 1:
{
SendWeaponAnim( SATCHEL_RADIO_FIRE ); SendWeaponAnim( SATCHEL_RADIO_FIRE );
edict_t *pPlayer = m_pPlayer->edict( ); edict_t *pPlayer = m_pPlayer->edict( );
@ -362,23 +384,6 @@ void CSatchel::PrimaryAttack()
m_flNextPrimaryAttack = GetNextAttackDelay(0.5); m_flNextPrimaryAttack = GetNextAttackDelay(0.5);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
break;
}
case 2:
// we're reloading, don't allow fire
{
}
break;
}
}
void CSatchel::SecondaryAttack( void )
{
if ( m_chargeReady != 2 )
{
Throw( );
} }
} }

View file

@ -99,6 +99,8 @@ public:
void TalkInit( void ); void TalkInit( void );
char* GetScientistModel() const;
void Killed( entvars_t *pevAttacker, int iGib ); void Killed( entvars_t *pevAttacker, int iGib );
virtual int Save( CSave &save ); virtual int Save( CSave &save );
@ -424,6 +426,17 @@ DEFINE_CUSTOM_SCHEDULES( CScientist )
IMPLEMENT_CUSTOM_SCHEDULES( CScientist, CTalkMonster ); IMPLEMENT_CUSTOM_SCHEDULES( CScientist, CTalkMonster );
char* CScientist::GetScientistModel() const
{
char* pszOverride = (char*)CVAR_GET_STRING("_sv_override_scientist_mdl");
if (pszOverride && strlen(pszOverride) > 5) // at least requires ".mdl"
{
return pszOverride;
}
return "models/scientist.mdl";
}
void CScientist::DeclineFollowing( void ) void CScientist::DeclineFollowing( void )
{ {
Talk( 10 ); Talk( 10 );
@ -658,7 +671,7 @@ void CScientist :: Spawn( void )
{ {
Precache( ); Precache( );
SET_MODEL(ENT(pev), "models/scientist.mdl"); SET_MODEL(ENT(pev), GetScientistModel());
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX; pev->solid = SOLID_SLIDEBOX;
@ -694,7 +707,7 @@ void CScientist :: Spawn( void )
//========================================================= //=========================================================
void CScientist :: Precache( void ) void CScientist :: Precache( void )
{ {
PRECACHE_MODEL("models/scientist.mdl"); PRECACHE_MODEL(GetScientistModel());
PRECACHE_SOUND("scientist/sci_pain1.wav"); PRECACHE_SOUND("scientist/sci_pain1.wav");
PRECACHE_SOUND("scientist/sci_pain2.wav"); PRECACHE_SOUND("scientist/sci_pain2.wav");
PRECACHE_SOUND("scientist/sci_pain3.wav"); PRECACHE_SOUND("scientist/sci_pain3.wav");
@ -1104,12 +1117,26 @@ public:
void Spawn( void ); void Spawn( void );
int Classify ( void ) { return CLASS_HUMAN_PASSIVE; } int Classify ( void ) { return CLASS_HUMAN_PASSIVE; }
// passed into Precache which is non-const
char* GetScientistModel() const;
void KeyValue( KeyValueData *pkvd ); void KeyValue( KeyValueData *pkvd );
int m_iPose;// which sequence to display int m_iPose;// which sequence to display
static char *m_szPoses[7]; static char *m_szPoses[7];
}; };
char *CDeadScientist::m_szPoses[] = { "lying_on_back", "lying_on_stomach", "dead_sitting", "dead_hang", "dead_table1", "dead_table2", "dead_table3" }; char *CDeadScientist::m_szPoses[] = { "lying_on_back", "lying_on_stomach", "dead_sitting", "dead_hang", "dead_table1", "dead_table2", "dead_table3" };
char* CDeadScientist::GetScientistModel() const
{
char* pszOverride = (char*)CVAR_GET_STRING("_sv_override_scientist_mdl");
if (pszOverride && strlen(pszOverride) > 5) // at least requires ".mdl"
{
return pszOverride;
}
return "models/scientist.mdl";
}
void CDeadScientist::KeyValue( KeyValueData *pkvd ) void CDeadScientist::KeyValue( KeyValueData *pkvd )
{ {
if (FStrEq(pkvd->szKeyName, "pose")) if (FStrEq(pkvd->szKeyName, "pose"))
@ -1127,8 +1154,8 @@ LINK_ENTITY_TO_CLASS( monster_scientist_dead, CDeadScientist );
// //
void CDeadScientist :: Spawn( ) void CDeadScientist :: Spawn( )
{ {
PRECACHE_MODEL("models/scientist.mdl"); PRECACHE_MODEL(GetScientistModel());
SET_MODEL(ENT(pev), "models/scientist.mdl"); SET_MODEL(ENT(pev), GetScientistModel());
pev->effects = 0; pev->effects = 0;
pev->sequence = 0; pev->sequence = 0;
@ -1209,8 +1236,8 @@ SITTING_ANIM_sitting3
// //
void CSittingScientist :: Spawn( ) void CSittingScientist :: Spawn( )
{ {
PRECACHE_MODEL("models/scientist.mdl"); PRECACHE_MODEL(GetScientistModel());
SET_MODEL(ENT(pev), "models/scientist.mdl"); SET_MODEL(ENT(pev), GetScientistModel());
Precache(); Precache();
InitBoneControllers(); InitBoneControllers();

View file

@ -934,9 +934,9 @@ public:
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
CBaseMonster *FindEntity( void ); CBaseToggle *FindEntity( void );
BOOL AcceptableSpeaker( CBaseMonster *pMonster ); BOOL AcceptableSpeaker( CBaseToggle *pTarget );
BOOL StartSentence( CBaseMonster *pTarget ); BOOL StartSentence( CBaseToggle *pTarget );
private: private:
@ -1072,10 +1072,10 @@ void CScriptedSentence :: Spawn( void )
void CScriptedSentence :: FindThink( void ) void CScriptedSentence :: FindThink( void )
{ {
CBaseMonster *pMonster = FindEntity(); CBaseToggle *pEnt = FindEntity();
if ( pMonster ) if (pEnt)
{ {
StartSentence( pMonster ); StartSentence(pEnt);
if ( pev->spawnflags & SF_SENTENCE_ONCE ) if ( pev->spawnflags & SF_SENTENCE_ONCE )
UTIL_Remove( this ); UTIL_Remove( this );
SetThink( &CScriptedSentence::DelayThink ); SetThink( &CScriptedSentence::DelayThink );
@ -1100,8 +1100,16 @@ void CScriptedSentence :: DelayThink( void )
} }
BOOL CScriptedSentence :: AcceptableSpeaker( CBaseMonster *pMonster ) BOOL CScriptedSentence :: AcceptableSpeaker( CBaseToggle *pTarget )
{ {
CBaseMonster *pMonster;
pMonster = NULL;
if (pTarget)
{
pMonster = pTarget->MyMonsterPointer();
}
if ( pMonster ) if ( pMonster )
{ {
if ( pev->spawnflags & SF_SENTENCE_FOLLOWERS ) if ( pev->spawnflags & SF_SENTENCE_FOLLOWERS )
@ -1117,27 +1125,40 @@ BOOL CScriptedSentence :: AcceptableSpeaker( CBaseMonster *pMonster )
if ( pMonster->CanPlaySentence( override ) ) if ( pMonster->CanPlaySentence( override ) )
return TRUE; return TRUE;
} }
else
{
// targeting something other than a monster, sure it can speak
if( pTarget && pTarget->IsAllowedToSpeak() )
return TRUE;
}
return FALSE; return FALSE;
} }
CBaseMonster *CScriptedSentence :: FindEntity( void ) CBaseToggle *CScriptedSentence :: FindEntity( void )
{ {
edict_t *pentTarget; edict_t *pentTarget;
CBaseMonster *pMonster; CBaseToggle *pSpeakingEnt;
pentTarget = FIND_ENTITY_BY_TARGETNAME(NULL, STRING(m_iszEntity)); pentTarget = FIND_ENTITY_BY_TARGETNAME(NULL, STRING(m_iszEntity));
pMonster = NULL; pSpeakingEnt = NULL;
while (!FNullEnt(pentTarget)) while (!FNullEnt(pentTarget))
{ {
pMonster = GetMonsterPointer( pentTarget ); CBaseEntity *pEnt = Instance(pentTarget);
if ( pMonster != NULL ) pSpeakingEnt = pEnt ? pEnt->MyTogglePointer() : NULL;
if (pSpeakingEnt != NULL )
{ {
if ( AcceptableSpeaker( pMonster ) ) if (AcceptableSpeaker(pSpeakingEnt))
return pMonster; {
// ALERT( at_console, "%s (%s), not acceptable\n", STRING(pMonster->pev->classname), STRING(pMonster->pev->targetname) ); //ALERT(at_console, "acceptable speaker\n");
return pSpeakingEnt;
}
//ALERT(at_console, "found unacceptable speaker\n");
} }
pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, STRING(m_iszEntity)); pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, STRING(m_iszEntity));
} }
@ -1149,9 +1170,9 @@ CBaseMonster *CScriptedSentence :: FindEntity( void )
{ {
if ( FBitSet( pEntity->pev->flags, FL_MONSTER )) if ( FBitSet( pEntity->pev->flags, FL_MONSTER ))
{ {
pMonster = pEntity->MyMonsterPointer( ); pSpeakingEnt = pEntity->MyTogglePointer( );
if ( AcceptableSpeaker( pMonster ) ) if ( AcceptableSpeaker( pSpeakingEnt ) )
return pMonster; return pSpeakingEnt;
} }
} }
} }
@ -1160,7 +1181,7 @@ CBaseMonster *CScriptedSentence :: FindEntity( void )
} }
BOOL CScriptedSentence :: StartSentence( CBaseMonster *pTarget ) BOOL CScriptedSentence :: StartSentence( CBaseToggle *pTarget )
{ {
if ( !pTarget ) if ( !pTarget )
{ {

View file

@ -175,8 +175,7 @@ void CShotgun::PrimaryAttack()
// HEV suit - indicate out of ammo condition // HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
if (m_iClip != 0) m_flPumpTime = gpGlobals->time + 0.5;
m_flPumpTime = gpGlobals->time + 0.5;
m_flNextPrimaryAttack = GetNextAttackDelay(0.75); m_flNextPrimaryAttack = GetNextAttackDelay(0.75);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
@ -249,8 +248,7 @@ void CShotgun::SecondaryAttack( void )
// HEV suit - indicate out of ammo condition // HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
if (m_iClip != 0) m_flPumpTime = gpGlobals->time + 0.95;
m_flPumpTime = gpGlobals->time + 0.95;
m_flNextPrimaryAttack = GetNextAttackDelay(1.5); m_flNextPrimaryAttack = GetNextAttackDelay(1.5);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.5; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.5;
@ -317,13 +315,6 @@ void CShotgun::WeaponIdle( void )
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
if ( m_flPumpTime && m_flPumpTime < gpGlobals->time )
{
// play pumping sound
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f));
m_flPumpTime = 0;
}
if (m_flTimeWeaponIdle < UTIL_WeaponTimeBase() ) if (m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
{ {
if (m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) if (m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
@ -371,6 +362,18 @@ void CShotgun::WeaponIdle( void )
} }
} }
void CShotgun::ItemPostFrame( void )
{
if ( m_flPumpTime && m_flPumpTime < gpGlobals->time )
{
// play pumping sound
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f));
m_flPumpTime = 0;
}
CBasePlayerWeapon::ItemPostFrame();
}
class CShotgunAmmo : public CBasePlayerAmmo class CShotgunAmmo : public CBasePlayerAmmo

View file

@ -34,6 +34,8 @@ extern int gmsgMOTD;
//========================================================= //=========================================================
CHalfLifeRules::CHalfLifeRules( void ) CHalfLifeRules::CHalfLifeRules( void )
{ {
SERVER_COMMAND( "exec spserver.cfg\n" );
RefreshSkillData(); RefreshSkillData();
} }
@ -83,10 +85,88 @@ BOOL CHalfLifeRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem
return TRUE; return TRUE;
} }
BOOL HLGetNextBestWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pCurrentWeapon )
{
CBasePlayerItem* pCheck;
CBasePlayerItem* pBest;// this will be used in the event that we don't find a weapon in the same category.
int iBestWeight;
int i;
iBestWeight = -1;// no weapon lower than -1 can be autoswitched to
pBest = NULL;
if ( !pCurrentWeapon->CanHolster() )
{
// can't put this gun away right now, so can't switch.
return FALSE;
}
for ( i = 0; i < MAX_ITEM_TYPES; i++ )
{
pCheck = pPlayer->m_rgpPlayerItems[i];
while ( pCheck )
{
if ( (pCheck->iFlags() & ITEM_FLAG_NOAUTOSWITCHTO ) != 0 )
{
pCheck = pCheck->m_pNext;
continue;
}
if ( pCheck->iWeight() > -1 && pCheck->iWeight() == pCurrentWeapon->iWeight() && pCheck != pCurrentWeapon )
{
// this weapon is from the same category.
if ( pCheck->CanDeploy() )
{
if ( pPlayer->SwitchWeapon( pCheck ) )
{
return TRUE;
}
}
}
else if ( pCheck->iWeight() > iBestWeight && pCheck != pCurrentWeapon )// don't reselect the weapon we're trying to get rid of
{
//ALERT ( at_console, "Considering %s\n", STRING( pCheck->pev->classname ) );
// we keep updating the 'best' weapon just in case we can't find a weapon of the same weight
// that the player was using. This will end up leaving the player with his heaviest-weighted
// weapon.
if ( pCheck->CanDeploy() )
{
// if this weapon is useable, flag it as the best
iBestWeight = pCheck->iWeight();
pBest = pCheck;
}
}
pCheck = pCheck->m_pNext;
}
}
// if we make it here, we've checked all the weapons and found no useable
// weapon in the same catagory as the current weapon.
// if pBest is null, we didn't find ANYTHING. Shouldn't be possible- should always
// at least get the crowbar, but ya never know.
if ( !pBest )
{
return FALSE;
}
pPlayer->SwitchWeapon( pBest );
return TRUE;
}
//========================================================= //=========================================================
//========================================================= //=========================================================
BOOL CHalfLifeRules :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) BOOL CHalfLifeRules :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon )
{ {
if ( pCurrentWeapon && pCurrentWeapon->iFlags() & ITEM_FLAG_EXHAUSTIBLE )
{
return HLGetNextBestWeapon( pPlayer, pCurrentWeapon );
}
return FALSE; return FALSE;
} }

View file

@ -340,7 +340,7 @@ void CSqueakGrenade::SuperBounceTouch( CBaseEntity *pOther )
// higher pitch as squeeker gets closer to detonation time // higher pitch as squeeker gets closer to detonation time
flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY); flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY);
if ( pOther->pev->takedamage && m_flNextAttack < gpGlobals->time ) if ( pOther->pev->takedamage && m_flNextAttack < gpGlobals->time && ( pOther->pev->flags & FL_WORLDBRUSH ) == 0)
{ {
// attack! // attack!
@ -492,25 +492,66 @@ void CSqueak::Holster( int skiplocal /* = 0 */ )
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM);
} }
// up / down
#define PITCH 0
// left / right
#define YAW 1
// fall over
#define ROLL 2
void AngleVectors(const vec3_t angles, vec3_t& forward, vec3_t& right, vec3_t& up)
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI * 2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI * 2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI * 2 / 360);
sr = sin(angle);
cr = cos(angle);
forward[0] = cp * cy;
forward[1] = cp * sy;
forward[2] = -sp;
right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
right[2] = -1 * sr * cp;
up[0] = (cr * sp * cy + -sr * -sy);
up[1] = (cr * sp * sy + -sr * cy);
up[2] = cr * cp;
}
void CSqueak::PrimaryAttack() void CSqueak::PrimaryAttack()
{ {
if ( m_pPlayer->m_rgAmmo[ m_iPrimaryAmmoType ] ) if ( m_pPlayer->m_rgAmmo[ m_iPrimaryAmmoType ] )
{ {
UTIL_MakeVectors( m_pPlayer->pev->v_angle ); vec3_t forward, right, up;
vec3_t vEntityForward = m_pPlayer->pev->v_angle;
vEntityForward[0] = 0;
AngleVectors(vEntityForward, forward, right, up);
vEntityForward = forward;
AngleVectors(m_pPlayer->pev->v_angle, forward, right, up);
TraceResult tr; TraceResult tr;
Vector trace_origin; Vector trace_origin;
// HACK HACK: Ugly hacks to handle change in origin based on new physics code for players // HACK HACK: Ugly hacks to handle change in origin based on new physics code for players
// Move origin up if crouched and start trace a bit outside of body ( 20 units instead of 16 ) // Move origin up if crouched and start trace a bit outside of body ( 20 units instead of 16 )
float flAimDownFraction = m_pPlayer->pev->v_angle[0] > 0 ? m_pPlayer->pev->v_angle[0] / 90.f : 0;
trace_origin = m_pPlayer->pev->origin; trace_origin = m_pPlayer->pev->origin;
if ( m_pPlayer->pev->flags & FL_DUCKING ) if ( m_pPlayer->pev->flags & FL_DUCKING )
{ {
trace_origin = trace_origin - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN ); trace_origin = trace_origin - (flAimDownFraction + 1) * ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
} }
Vector vTraceForward = (flAimDownFraction * vEntityForward) + (1 - flAimDownFraction) * forward;
// find place to toss monster // find place to toss monster
UTIL_TraceLine( trace_origin + gpGlobals->v_forward * 20, trace_origin + gpGlobals->v_forward * 64, dont_ignore_monsters, NULL, &tr ); UTIL_TraceLine(trace_origin + vTraceForward * 24, trace_origin + forward * 60, dont_ignore_monsters, NULL, &tr);
int flags; int flags;
#ifdef CLIENT_WEAPONS #ifdef CLIENT_WEAPONS
@ -521,14 +562,14 @@ void CSqueak::PrimaryAttack()
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 ); PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
if ( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25 ) if (tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0 )
{ {
// player "shoot" animation // player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict() ); CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pSqueak->pev->velocity = gpGlobals->v_forward * 200 + m_pPlayer->pev->velocity; pSqueak->pev->velocity = vTraceForward * 200 + m_pPlayer->pev->velocity;
#endif #endif
// play hunt sound // play hunt sound

View file

@ -450,6 +450,31 @@ BOOL CBaseToggle :: IsLockedByMaster( void )
return FALSE; return FALSE;
} }
void CBaseToggle::PlaySentence(const char* pszSentence, float duration, float volume, float attenuation)
{
if ( pszSentence && IsAllowedToSpeak() )
{
if (pszSentence[0] == '!')
EMIT_SOUND_DYN(edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, PITCH_NORM);
else
SENTENCEG_PlayRndSz(edict(), pszSentence, volume, attenuation, 0, PITCH_NORM);
}
}
void CBaseToggle::PlayScriptedSentence(const char* pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity* pListener)
{
PlaySentence(pszSentence, duration, volume, attenuation);
}
void CBaseToggle::SentenceStop(void)
{
EMIT_SOUND(edict(), CHAN_VOICE, "common/null.wav", 1.0, ATTN_IDLE);
}
/* /*
============= =============
AngularMove AngularMove

View file

@ -423,11 +423,11 @@ void CTalkMonster :: StartTask( Task_t *pTask )
if (yaw < 0) if (yaw < 0)
{ {
pev->ideal_yaw = min( yaw + 45, 0 ) + pev->angles.y; pev->ideal_yaw = min( yaw + 45.0f, 0.0f ) + pev->angles.y;
} }
else else
{ {
pev->ideal_yaw = max( yaw - 45, 0 ) + pev->angles.y; pev->ideal_yaw = max( yaw - 45.0f, 0.0f ) + pev->angles.y;
} }
} }
TaskComplete(); TaskComplete();
@ -1402,7 +1402,7 @@ BOOL CTalkMonster::CanFollow( void )
{ {
if ( m_MonsterState == MONSTERSTATE_SCRIPT ) if ( m_MonsterState == MONSTERSTATE_SCRIPT )
{ {
if ( !m_pCine->CanInterrupt() ) if ( !m_pCine || !m_pCine->CanInterrupt() )
return FALSE; return FALSE;
} }

View file

@ -111,7 +111,7 @@ public:
int IRelationship ( CBaseEntity *pTarget ); int IRelationship ( CBaseEntity *pTarget );
virtual int CanPlaySentence( BOOL fDisregardState ); virtual int CanPlaySentence( BOOL fDisregardState );
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ); virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
void KeyValue( KeyValueData *pkvd ); void KeyValue( KeyValueData *pkvd );
// AI functions // AI functions

View file

@ -124,4 +124,82 @@ private:
unsigned short m_usAdjustPitch; unsigned short m_usAdjustPitch;
}; };
class CFuncVehicle : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
void Blocked( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData* pkvd );
void EXPORT Next( void );
void EXPORT Find( void );
void EXPORT NearestPath( void );
void EXPORT DeadEnd( void );
void NextThink( float thinkTime, BOOL alwaysThink );
int Classify (void);
void CollisionDetection(void);
void TerrainFollowing(void);
void CheckTurning(void);
void SetTrack( CPathTrack *track ) { m_ppath = track->Nearest(pev->origin); }
void SetControls( entvars_t *pevControls );
BOOL OnControls( entvars_t *pev );
void StopSound ( void );
void UpdateSound ( void );
static CFuncVehicle *Instance( edict_t *pent );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DIRECTIONAL_USE; }
virtual void OverrideReset( void );
CPathTrack *m_ppath;
float m_length;
float m_width;
float m_height;
float m_speed;
float m_dir;
float m_startSpeed;
Vector m_controlMins;
Vector m_controlMaxs;
int m_soundPlaying;
int m_sounds;
int m_acceleration;
float m_flVolume;
float m_flBank;
float m_oldSpeed;
int m_iTurnAngle;
float m_flSteeringWheelDecay;
float m_flAcceleratorDecay;
float m_flTurnStartTime;
float m_flLaunchTime; //Time at which the vehicle has become airborne
float m_flLastNormalZ;
float m_flCanTurnNow;
float m_flUpdateSound;
Vector m_vFrontLeft;
Vector m_vFront;
Vector m_vFrontRight;
Vector m_vBackLeft;
Vector m_vBack;
Vector m_vBackRight;
Vector m_vSurfaceNormal;
Vector m_vVehicleDirection;
CBasePlayer *m_pDriver;
// GOOSEMAN
void Restart();
private:
unsigned short m_usAdjustPitch;
};
#endif #endif

View file

@ -331,7 +331,7 @@ void CMultiManager :: KeyValue( KeyValueData *pkvd )
{ {
char tmp[128]; char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp ); UTIL_StripToken( pkvd->szKeyName, tmp, sizeof( tmp ) );
m_iTargetName [ m_cTargets ] = ALLOC_STRING( tmp ); m_iTargetName [ m_cTargets ] = ALLOC_STRING( tmp );
m_flTargetDelay [ m_cTargets ] = atof (pkvd->szValue); m_flTargetDelay [ m_cTargets ] = atof (pkvd->szValue);
m_cTargets++; m_cTargets++;
@ -1002,7 +1002,19 @@ void CBaseTrigger :: HurtTouch ( CBaseEntity *pOther )
#endif #endif
if ( fldmg < 0 ) if ( fldmg < 0 )
pOther->TakeHealth( -fldmg, m_bitsDamageInflict ); {
BOOL bApplyHeal = TRUE;
if ( g_pGameRules->IsMultiplayer() && pOther->IsPlayer() )
{
bApplyHeal = pOther->pev->deadflag == DEAD_NO;
}
if ( bApplyHeal )
{
pOther->TakeHealth( -fldmg, m_bitsDamageInflict );
}
}
else else
pOther->TakeDamage( pev, pev, fldmg, m_bitsDamageInflict ); pOther->TakeDamage( pev, pev, fldmg, m_bitsDamageInflict );

View file

@ -407,7 +407,7 @@ int CTripmine::GetItemInfo(ItemInfo *p)
BOOL CTripmine::Deploy( ) BOOL CTripmine::Deploy( )
{ {
//pev->body = 0; pev->body = 0;
return DefaultDeploy( "models/v_tripmine.mdl", "models/p_tripmine.mdl", TRIPMINE_DRAW, "trip" ); return DefaultDeploy( "models/v_tripmine.mdl", "models/p_tripmine.mdl", TRIPMINE_DRAW, "trip" );
} }

View file

@ -1384,7 +1384,8 @@ void UTIL_StringToVector( float *pVector, const char *pString )
char *pstr, *pfront, tempString[128]; char *pstr, *pfront, tempString[128];
int j; int j;
strcpy( tempString, pString ); strncpy( tempString, pString, sizeof( tempString ) );
tempString[ sizeof( tempString ) - 1 ] = '\0';
pstr = pfront = tempString; pstr = pfront = tempString;
for ( j = 0; j < 3; j++ ) // lifted from pr_edict.c for ( j = 0; j < 3; j++ ) // lifted from pr_edict.c
@ -1415,7 +1416,8 @@ void UTIL_StringToIntArray( int *pVector, int count, const char *pString )
char *pstr, *pfront, tempString[128]; char *pstr, *pfront, tempString[128];
int j; int j;
strcpy( tempString, pString ); strncpy( tempString, pString, sizeof( tempString ) );
tempString[ sizeof( tempString ) - 1 ] = '\0';
pstr = pfront = tempString; pstr = pfront = tempString;
for ( j = 0; j < count; j++ ) // lifted from pr_edict.c for ( j = 0; j < count; j++ ) // lifted from pr_edict.c
@ -1626,11 +1628,11 @@ float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vecto
//========================================================= //=========================================================
// UTIL_StripToken - for redundant keynames // UTIL_StripToken - for redundant keynames
//========================================================= //=========================================================
void UTIL_StripToken( const char *pKey, char *pDest ) void UTIL_StripToken( const char *pKey, char *pDest, int nLen )
{ {
int i = 0; int i = 0;
while ( pKey[i] && pKey[i] != '#' ) while ( i < nLen - 1 && pKey[i] && pKey[i] != '#' )
{ {
pDest[i] = pKey[i]; pDest[i] = pKey[i];
i++; i++;
@ -2235,7 +2237,7 @@ int CRestore::ReadField( void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCou
{ {
fieldNumber = (i+startField)%fieldCount; fieldNumber = (i+startField)%fieldCount;
pTest = &pFields[ fieldNumber ]; pTest = &pFields[ fieldNumber ];
if ( !stricmp( pTest->fieldName, pName ) ) if ( pTest->fieldName && !stricmp( pTest->fieldName, pName ) )
{ {
if ( !m_global || !(pTest->flags & FTYPEDESC_GLOBAL) ) if ( !m_global || !(pTest->flags & FTYPEDESC_GLOBAL) )
{ {

View file

@ -341,7 +341,7 @@ extern void UTIL_LogPrintf( char *fmt, ... );
// Sorta like FInViewCone, but for nonmonsters. // Sorta like FInViewCone, but for nonmonsters.
extern float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir ); extern float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir );
extern void UTIL_StripToken( const char *pKey, char *pDest );// for redundant keynames extern void UTIL_StripToken( const char *pKey, char *pDest, int nLen );// for redundant keynames
// Misc functions // Misc functions
extern void SetMovedir(entvars_t* pev); extern void SetMovedir(entvars_t* pev);
@ -464,7 +464,7 @@ extern DLL_GLOBAL int g_Language;
// sentence groups // sentence groups
#define CBSENTENCENAME_MAX 16 #define CBSENTENCENAME_MAX 16
#define CVOXFILESENTENCEMAX 1536 // max number of sentences in game. NOTE: this must match #define CVOXFILESENTENCEMAX 2048 // max number of sentences in game. NOTE: this must match
// CVOXFILESENTENCEMAX in engine\sound.h!!! // CVOXFILESENTENCEMAX in engine\sound.h!!!
extern char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX]; extern char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX];

View file

@ -106,7 +106,23 @@ public:
inline Vector operator*(float fl, const Vector& v) { return v * fl; } inline Vector operator*(float fl, const Vector& v) { return v * fl; }
inline float DotProduct(const Vector& a, const Vector& b) { return(a.x*b.x+a.y*b.y+a.z*b.z); } inline float DotProduct(const Vector& a, const Vector& b) { return(a.x*b.x+a.y*b.y+a.z*b.z); }
inline Vector CrossProduct(const Vector& a, const Vector& b) { return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); } inline Vector CrossProduct(const Vector& a, const Vector& b) { return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); }
inline Vector RotateVectorZ(const Vector& a, int angle)
{
float x_old, y_old, R_angle;
Vector new_vector;
x_old = a.x;
y_old = a.y;
R_angle = (float)(angle * (3.141517 / 180));
new_vector.x = (float)(x_old * cos(R_angle) - y_old * sin(R_angle));
new_vector.y = (float)(y_old * cos(R_angle) + x_old * sin(R_angle));
new_vector.z = 0;
return new_vector;
}
#define vec3_t Vector
#endif #endif

1100
dlls/vehicle.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -56,6 +56,8 @@ MULTIDAMAGE gMultiDamage;
#define TRACER_FREQ 4 // Tracers fire every fourth bullet #define TRACER_FREQ 4 // Tracers fire every fourth bullet
extern bool IsBustingGame();
extern bool IsPlayerBusting( CBaseEntity *pPlayer );
//========================================================= //=========================================================
// MaxAmmoCarry - pass in a name and this function will tell // MaxAmmoCarry - pass in a name and this function will tell
@ -510,6 +512,19 @@ void CBasePlayerItem::FallThink ( void )
Materialize(); Materialize();
} }
else if ( m_pPlayer != NULL )
{
SetThink( NULL );
}
//This weapon is an egon, it has no owner and we're in busting mode, so just remove it when it hits the ground
if ( IsBustingGame() && FNullEnt( pev->owner ) )
{
if ( !strcmp( "weapon_egon", STRING( pev->classname ) ) )
{
UTIL_Remove( this );
}
}
} }
//========================================================= //=========================================================
@ -950,7 +965,7 @@ BOOL CBasePlayerWeapon :: IsUseable( void )
if ( m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] <= 0 && iMaxAmmo1() != -1 ) if ( m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] <= 0 && iMaxAmmo1() != -1 )
{ {
// clip is empty (or nonexistant) and the player has no more ammo of this type. // clip is empty (or nonexistant) and the player has no more ammo of this type.
return FALSE; return CanDeploy();
} }
} }
@ -1107,6 +1122,9 @@ void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther )
return; return;
} }
if ( IsPlayerBusting( pOther ) )
return;
if (AddAmmo( pOther )) if (AddAmmo( pOther ))
{ {
if ( g_pGameRules->AmmoShouldRespawn( this ) == GR_AMMO_RESPAWN_YES ) if ( g_pGameRules->AmmoShouldRespawn( this ) == GR_AMMO_RESPAWN_YES )
@ -1572,8 +1590,10 @@ IMPLEMENT_SAVERESTORE( CRpg, CBasePlayerWeapon );
TYPEDESCRIPTION CRpgRocket::m_SaveData[] = TYPEDESCRIPTION CRpgRocket::m_SaveData[] =
{ {
DEFINE_FIELD( CRpgRocket, m_flIgniteTime, FIELD_TIME ), DEFINE_FIELD( CRpgRocket, m_flIgniteTime, FIELD_TIME ),
DEFINE_FIELD( CRpgRocket, m_pLauncher, FIELD_CLASSPTR ), DEFINE_FIELD( CRpgRocket, m_hLauncher, FIELD_EHANDLE ),
}; };
IMPLEMENT_SAVERESTORE( CRpgRocket, CGrenade ); IMPLEMENT_SAVERESTORE( CRpgRocket, CGrenade );
TYPEDESCRIPTION CShotgun::m_SaveData[] = TYPEDESCRIPTION CShotgun::m_SaveData[] =

View file

@ -36,7 +36,7 @@ public:
static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code ); static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code );
void Explode( Vector vecSrc, Vector vecAim ); void Explode( Vector vecSrc, Vector vecAim );
void Explode( TraceResult *pTrace, int bitsDamageType ); virtual void Explode( TraceResult *pTrace, int bitsDamageType );
void EXPORT Smoke( void ); void EXPORT Smoke( void );
void EXPORT BounceTouch( CBaseEntity *pOther ); void EXPORT BounceTouch( CBaseEntity *pOther );
@ -99,7 +99,7 @@ public:
#define RPG_WEIGHT 20 #define RPG_WEIGHT 20
#define GAUSS_WEIGHT 20 #define GAUSS_WEIGHT 20
#define EGON_WEIGHT 20 #define EGON_WEIGHT 20
#define HORNETGUN_WEIGHT 10 #define HORNETGUN_WEIGHT 15
#define HANDGRENADE_WEIGHT 5 #define HANDGRENADE_WEIGHT 5
#define SNARK_WEIGHT 5 #define SNARK_WEIGHT 5
#define SATCHEL_WEIGHT -10 #define SATCHEL_WEIGHT -10
@ -191,6 +191,7 @@ typedef enum
#define ITEM_FLAG_NOAUTOSWITCHEMPTY 4 #define ITEM_FLAG_NOAUTOSWITCHEMPTY 4
#define ITEM_FLAG_LIMITINWORLD 8 #define ITEM_FLAG_LIMITINWORLD 8
#define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon #define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon
#define ITEM_FLAG_NOAUTOSWITCHTO 32
#define WEAPON_IS_ONTARGET 0x40 #define WEAPON_IS_ONTARGET 0x40
@ -647,6 +648,7 @@ public:
BOOL Deploy( ); BOOL Deploy( );
void Reload( void ); void Reload( void );
void WeaponIdle( void ); void WeaponIdle( void );
void ItemPostFrame( void );
int m_fInReload; int m_fInReload;
float m_flNextReload; float m_flNextReload;
int m_iShell; int m_iShell;
@ -736,11 +738,17 @@ public:
void EXPORT FollowThink( void ); void EXPORT FollowThink( void );
void EXPORT IgniteThink( void ); void EXPORT IgniteThink( void );
void EXPORT RocketTouch( CBaseEntity *pOther ); void EXPORT RocketTouch( CBaseEntity *pOther );
virtual void Explode( TraceResult *pTrace, int bitsDamageType );
static CRpgRocket *CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher ); static CRpgRocket *CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher );
CRpg* GetLauncher();
int m_iTrail; int m_iTrail;
float m_flIgniteTime; float m_flIgniteTime;
CRpg *m_pLauncher;// pointer back to the launcher that fired me.
EHANDLE m_hLauncher; // pointer back to the launcher that fired me.
}; };
class CGauss : public CBasePlayerWeapon class CGauss : public CBasePlayerWeapon
@ -828,6 +836,7 @@ public:
void Fire( const Vector &vecOrigSrc, const Vector &vecDir ); void Fire( const Vector &vecOrigSrc, const Vector &vecDir );
BOOL HasAmmo( void ); BOOL HasAmmo( void );
BOOL CanHolster();
void UseAmmo( int count ); void UseAmmo( int count );

View file

@ -230,7 +230,7 @@ static void InitBodyQue(void)
// //
void CopyToBodyQue(entvars_t *pev) void CopyToBodyQue(entvars_t *pev)
{ {
if (pev->effects & EF_NODRAW) if (pev->effects & EF_NODRAW || pev->modelindex == 0 )
return; return;
entvars_t *pevHead = VARS(g_pBodyQueueHead); entvars_t *pevHead = VARS(g_pBodyQueueHead);
@ -467,13 +467,11 @@ LINK_ENTITY_TO_CLASS( worldspawn, CWorld );
#define SF_WORLD_FORCETEAM 0x0004 // Force teams #define SF_WORLD_FORCETEAM 0x0004 // Force teams
extern DLL_GLOBAL BOOL g_fGameOver; extern DLL_GLOBAL BOOL g_fGameOver;
float g_flWeaponCheat;
void CWorld :: Spawn( void ) void CWorld :: Spawn( void )
{ {
g_fGameOver = FALSE; g_fGameOver = FALSE;
Precache( ); Precache( );
g_flWeaponCheat = CVAR_GET_FLOAT( "sv_cheats" ); // Is the impulse 101 command allowed?
} }
void CWorld :: Precache( void ) void CWorld :: Precache( void )

View file

@ -176,13 +176,7 @@ void CGlock::Reload( void )
if ( m_pPlayer->ammo_9mm <= 0 ) if ( m_pPlayer->ammo_9mm <= 0 )
return; return;
int iResult; int iResult = DefaultReload( GLOCK_MAX_CLIP, m_iClip > 0 ? GLOCK_RELOAD_NOT_EMPTY : GLOCK_RELOAD, 1.5 );
if (m_iClip == 0)
iResult = DefaultReload( 17, GLOCK_RELOAD, 1.5 );
else
iResult = DefaultReload( 17, GLOCK_RELOAD_NOT_EMPTY, 1.5 );
if (iResult) if (iResult)
{ {
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );

View file

@ -169,18 +169,16 @@ void CZombie :: AlertSound( void )
void CZombie :: IdleSound( void ) void CZombie :: IdleSound( void )
{ {
int pitch = 100 + RANDOM_LONG(-5,5); int pitch = 95 + RANDOM_LONG(0,9);
// Play a random idle sound // Play a random idle sound
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pIdleSounds[ RANDOM_LONG(0,ARRAYSIZE(pIdleSounds)-1) ], 1.0, ATTN_NORM, 0, pitch ); EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pIdleSounds[ RANDOM_LONG(0,ARRAYSIZE(pIdleSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
} }
void CZombie :: AttackSound( void ) void CZombie :: AttackSound( void )
{ {
int pitch = 100 + RANDOM_LONG(-5,5);
// Play a random attack sound // Play a random attack sound
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAttackSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, pitch ); EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAttackSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
} }

View file

@ -611,14 +611,16 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
WEAPON Weapon; WEAPON Weapon;
strcpy( Weapon.szName, READ_STRING() ); strncpy( Weapon.szName, READ_STRING(), sizeof(Weapon.szName) );
Weapon.szName[ sizeof(Weapon.szName) - 1 ] = '\0';
Weapon.iAmmoType = (int)READ_CHAR(); Weapon.iAmmoType = (int)READ_CHAR();
Weapon.iMax1 = READ_BYTE(); Weapon.iMax1 = READ_BYTE();
if (Weapon.iMax1 == 255) if (Weapon.iMax1 == 255)
Weapon.iMax1 = -1; Weapon.iMax1 = -1;
Weapon.iAmmo2Type = READ_BYTE(); Weapon.iAmmo2Type = READ_CHAR();
Weapon.iMax2 = READ_BYTE(); Weapon.iMax2 = READ_BYTE();
if (Weapon.iMax2 == 255) if (Weapon.iMax2 == 255)
Weapon.iMax2 = -1; Weapon.iMax2 = -1;
@ -631,6 +633,27 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
Weapon.iClip = 0; Weapon.iClip = 0;
if (Weapon.iId < 0 || Weapon.iId >= MAX_WEAPONS)
return 0;
if (Weapon.iSlot < 0 || Weapon.iSlot >= MAX_WEAPON_SLOTS+1)
return 0;
if (Weapon.iSlotPos < 0 || Weapon.iSlotPos >= MAX_WEAPON_POSITIONS+1)
return 0;
if (Weapon.iAmmoType < -1 || Weapon.iAmmoType >= MAX_AMMO_TYPES)
return 0;
if (Weapon.iAmmo2Type < -1 || Weapon.iAmmo2Type >= MAX_AMMO_TYPES)
return 0;
if (Weapon.iAmmoType >= 0 && Weapon.iMax1 == 0)
return 0;
if (Weapon.iAmmo2Type >= 0 && Weapon.iMax2 == 0)
return 0;
gWR.AddWeapon( &Weapon ); gWR.AddWeapon( &Weapon );
return 1; return 1;
@ -831,7 +854,7 @@ int CHudAmmo::Draw(float flTime)
AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
a = (int) max( MIN_ALPHA, m_fFade ); a = max<int>( MIN_ALPHA, m_fFade );
if (m_fFade > 0) if (m_fFade > 0)
m_fFade -= (gHUD.m_flTimeDelta * 20); m_fFade -= (gHUD.m_flTimeDelta * 20);

View file

@ -61,7 +61,7 @@ int CHudAmmoSecondary :: Draw(float flTime)
// draw secondary ammo icons above normal ammo readout // draw secondary ammo icons above normal ammo readout
int a, x, y, r, g, b, AmmoWidth; int a, x, y, r, g, b, AmmoWidth;
UnpackRGB( r, g, b, RGB_YELLOWISH ); UnpackRGB( r, g, b, RGB_YELLOWISH );
a = (int) max( MIN_ALPHA, m_fFade ); a = max<int>( MIN_ALPHA, m_fFade );
if (m_fFade > 0) if (m_fFade > 0)
m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons
ScaleColors( r, g, b, a ); ScaleColors( r, g, b, a );

View file

@ -126,7 +126,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime )
int r, g, b; int r, g, b;
UnpackRGB(r,g,b, RGB_YELLOWISH); UnpackRGB(r,g,b, RGB_YELLOWISH);
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
ScaleColors(r, g, b, min(scale, 255) ); ScaleColors(r, g, b, min<int>(scale, 255) );
// Draw the pic // Draw the pic
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
@ -154,7 +154,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime )
UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
ScaleColors(r, g, b, min(scale, 255) ); ScaleColors(r, g, b, min<int>(scale, 255) );
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left);
@ -172,7 +172,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime )
UnpackRGB(r,g,b, RGB_YELLOWISH); UnpackRGB(r,g,b, RGB_YELLOWISH);
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
ScaleColors(r, g, b, min(scale, 255) ); ScaleColors(r, g, b, min<int>(scale, 255) );
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
int xpos = ScreenWidth - (rect.right - rect.left) - 10; int xpos = ScreenWidth - (rect.right - rect.left) - 10;

View file

@ -1,598 +0,0 @@
# Microsoft Developer Studio Project File - Name="cl_dll" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=cl_dll - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "cl_dll.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "cl_dll.mak" CFG="cl_dll - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "cl_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "cl_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/GoldSrc/dmc/cl_dlls", STQCAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "cl_dll - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Release"
# PROP Intermediate_Dir ".\Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\utils\common" /I "..\..\public" /I "..\engine" /I "..\common" /I "..\utils\vgui\include" /I "..\dlls" /I "..\..\engine" /I "..\..\common" /I "..\pm_shared" /I "..\..\utils\vgui\include" /I "." /I "..\..\game_shared" /I "..\..\external" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /D "DMC_BUILD" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ..\..\utils\vgui\lib\win32_vc6\vgui.lib wsock32.lib ..\..\lib\public\sdl2.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /out:".\Release\client.dll"
# Begin Custom Build - Copying to cl_dlls
InputDir=.\Release
ProjDir=.
InputPath=.\Release\client.dll
SOURCE="$(InputPath)"
BuildCmds= \
call ..\..\filecopy.bat $(InputPath) $(ProjDir)\..\..\..\game\mod\cl_dlls\client.dll \
call ..\..\filecopy.bat $(InputDir)\client.pdb $(ProjDir)\..\..\..\game\mod\cl_dlls\client.pdb \
"..\..\..\game\mod\cl_dlls\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"..\..\..\game\mod\cl_dlls\client.pdb" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "cl_dll - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Debug"
# PROP BASE Intermediate_Dir ".\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MTd /W3 /GX /ZI /Od /I "..\..\public" /I "..\engine" /I "..\common" /I "..\utils\vgui\include" /I "..\dlls" /I "..\..\engine" /I "..\..\common" /I "..\pm_shared" /I "..\..\utils\vgui\include" /I "." /I "..\..\game_shared" /I "..\..\external" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /D "DMC_BUILD" /FR /Fp".\Release/cl_dll.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ..\..\utils\vgui\lib\win32_vc6\vgui.lib wsock32.lib ..\..\lib\public\sdl2.lib /nologo /subsystem:windows /dll /profile /map /debug /machine:I386 /out:".\Debug\client.dll"
# Begin Custom Build - Copying to cl_dlls
InputDir=.\Debug
ProjDir=.
InputPath=.\Debug\client.dll
SOURCE="$(InputPath)"
BuildCmds= \
call ..\..\filecopy.bat $(InputPath) $(ProjDir)\..\..\..\game\mod\cl_dlls\client.dll \
call ..\..\filecopy.bat $(InputDir)\client.pdb $(ProjDir)\..\..\..\game\mod\cl_dlls\client.pdb \
"..\..\..\game\mod\cl_dlls\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"..\..\..\game\mod\cl_dlls\client.pdb" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ENDIF
# Begin Target
# Name "cl_dll - Win32 Release"
# Name "cl_dll - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
# Begin Group "quake"
# PROP Default_Filter "*.cpp"
# Begin Source File
SOURCE=.\CTF_FlagStatus.cpp
# End Source File
# Begin Source File
SOURCE=.\CTF_HudMessage.cpp
# End Source File
# Begin Source File
SOURCE=.\DMC_Teleporters.cpp
# End Source File
# Begin Source File
SOURCE=.\ev_hldm.cpp
# End Source File
# Begin Source File
SOURCE=.\quake\quake_baseentity.cpp
# End Source File
# Begin Source File
SOURCE=.\quake\quake_events.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\quake_gun.cpp
# End Source File
# Begin Source File
SOURCE=.\quake\quake_objects.cpp
# End Source File
# Begin Source File
SOURCE=.\quake\quake_weapons.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\quake_weapons_all.cpp
# End Source File
# Begin Source File
SOURCE=.\studio_util.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_SpectatorPanel.cpp
# End Source File
# End Group
# Begin Source File
SOURCE=.\ammo.cpp
# End Source File
# Begin Source File
SOURCE=.\ammo_secondary.cpp
# End Source File
# Begin Source File
SOURCE=.\ammohistory.cpp
# End Source File
# Begin Source File
SOURCE=.\battery.cpp
# End Source File
# Begin Source File
SOURCE=.\cdll_int.cpp
# End Source File
# Begin Source File
SOURCE=.\com_weapons.cpp
# End Source File
# Begin Source File
SOURCE=.\death.cpp
# End Source File
# Begin Source File
SOURCE=.\demo.cpp
# End Source File
# Begin Source File
SOURCE=.\entity.cpp
# End Source File
# Begin Source File
SOURCE=.\ev_common.cpp
# End Source File
# Begin Source File
SOURCE=.\events.cpp
# End Source File
# Begin Source File
SOURCE=.\GameStudioModelRenderer.cpp
# End Source File
# Begin Source File
SOURCE=.\geiger.cpp
# End Source File
# Begin Source File
SOURCE=.\health.cpp
# End Source File
# Begin Source File
SOURCE=.\hud.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_msg.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_redraw.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_servers.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_spectator.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_update.cpp
# End Source File
# Begin Source File
SOURCE=.\in_camera.cpp
# End Source File
# Begin Source File
SOURCE=.\input.cpp
# End Source File
# Begin Source File
SOURCE=.\inputw32.cpp
# End Source File
# Begin Source File
SOURCE=..\..\public\interface.cpp
# End Source File
# Begin Source File
SOURCE=.\menu.cpp
# End Source File
# Begin Source File
SOURCE=.\message.cpp
# End Source File
# Begin Source File
SOURCE=..\..\common\parsemsg.cpp
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_debug.c
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_math.c
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_shared.c
# End Source File
# Begin Source File
SOURCE=.\saytext.cpp
# End Source File
# Begin Source File
SOURCE=.\scoreboard.cpp
# PROP Exclude_From_Build 1
# End Source File
# Begin Source File
SOURCE=.\status_icons.cpp
# End Source File
# Begin Source File
SOURCE=.\statusbar.cpp
# End Source File
# Begin Source File
SOURCE=.\StudioModelRenderer.cpp
# End Source File
# Begin Source File
SOURCE=.\text_message.cpp
# End Source File
# Begin Source File
SOURCE=.\train.cpp
# End Source File
# Begin Source File
SOURCE=.\tri.cpp
# End Source File
# Begin Source File
SOURCE=.\util.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_checkbutton2.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_grid.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_helpers.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_int.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_listbox.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_loadtga.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ScorePanel.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_scrollbar2.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ServerBrowser.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_slider2.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_viewport.cpp
# End Source File
# Begin Source File
SOURCE=.\view.cpp
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\voice_banmgr.cpp
# End Source File
# Begin Source File
SOURCE=.\voice_status.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\ammo.h
# End Source File
# Begin Source File
SOURCE=.\ammohistory.h
# End Source File
# Begin Source File
SOURCE=.\camera.h
# End Source File
# Begin Source File
SOURCE=.\cl_dll.h
# End Source File
# Begin Source File
SOURCE=.\cl_util.h
# End Source File
# Begin Source File
SOURCE=.\com_weapons.h
# End Source File
# Begin Source File
SOURCE=.\demo.h
# End Source File
# Begin Source File
SOURCE=.\DMC_BSPFile.h
# End Source File
# Begin Source File
SOURCE=.\DMC_Teleporters.h
# End Source File
# Begin Source File
SOURCE=.\ev_hldm.h
# End Source File
# Begin Source File
SOURCE=.\eventscripts.h
# End Source File
# Begin Source File
SOURCE=.\GameStudioModelRenderer.h
# End Source File
# Begin Source File
SOURCE=.\health.h
# End Source File
# Begin Source File
SOURCE=.\hud.h
# End Source File
# Begin Source File
SOURCE=.\hud_iface.h
# End Source File
# Begin Source File
SOURCE=.\hud_servers.h
# End Source File
# Begin Source File
SOURCE=.\hud_servers_priv.h
# End Source File
# Begin Source File
SOURCE=.\hud_spectator.h
# End Source File
# Begin Source File
SOURCE=.\in_defs.h
# End Source File
# Begin Source File
SOURCE=.\kbutton.h
# End Source File
# Begin Source File
SOURCE=..\..\common\parsemsg.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_debug.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_defs.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_info.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_materials.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_movevars.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_shared.h
# End Source File
# Begin Source File
SOURCE=..\dlls\quake_gun.h
# End Source File
# Begin Source File
SOURCE=.\StudioModelRenderer.h
# End Source File
# Begin Source File
SOURCE=.\util.h
# End Source File
# Begin Source File
SOURCE=.\util_vector.h
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_checkbutton2.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ControlConfigPanel.h
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_grid.h
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_helpers.h
# End Source File
# Begin Source File
SOURCE=.\vgui_int.h
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_listbox.h
# End Source File
# Begin Source File
SOURCE=..\..\game_shared\vgui_loadtga.h
# End Source File
# Begin Source File
SOURCE=.\vgui_SchemeManager.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ScorePanel.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ServerBrowser.h
# End Source File
# Begin Source File
SOURCE=.\vgui_SpectatorPanel.h
# End Source File
# Begin Source File
SOURCE=.\vgui_viewport.h
# End Source File
# Begin Source File
SOURCE=.\view.h
# End Source File
# Begin Source File
SOURCE=.\voice_status.h
# End Source File
# Begin Source File
SOURCE=.\wrect.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\vgui_CustomObjects.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_MOTDWindow.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_SchemeManager.cpp
# End Source File
# End Target
# End Project

View file

@ -83,6 +83,7 @@ inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int fl
#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) #define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
#define ServerCmd (*gEngfuncs.pfnServerCmd) #define ServerCmd (*gEngfuncs.pfnServerCmd)
#define ClientCmd (*gEngfuncs.pfnClientCmd) #define ClientCmd (*gEngfuncs.pfnClientCmd)
#define FilteredClientCmd (*gEngfuncs.pfnFilteredClientCmd)
#define SetCrosshair (*gEngfuncs.pfnSetCrosshair) #define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
#define AngleVectors (*gEngfuncs.pfnAngleVectors) #define AngleVectors (*gEngfuncs.pfnAngleVectors)
@ -165,8 +166,6 @@ inline int safe_sprintf( char *dst, int len_dst, const char *format, ...)
inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); } inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); }
inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); } inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); }
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define fabs(x) ((x) > 0 ? (x) : 0 - (x)) #define fabs(x) ((x) > 0 ? (x) : 0 - (x))
void ScaleColors( int &r, int &g, int &b, int a ); void ScaleColors( int &r, int &g, int &b, int a );

View file

@ -93,7 +93,7 @@ int CHudDeathNotice :: Init( void )
HOOK_MESSAGE( DeathMsg ); HOOK_MESSAGE( DeathMsg );
CVAR_CREATE( "hud_deathnotice_time", "6", 0 ); CVAR_CREATE( "hud_deathnotice_time", "6", FCVAR_ARCHIVE );
return 1; return 1;
} }

View file

@ -83,6 +83,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
{ {
// hit the world, try to play sound based on texture material type // hit the world, try to play sound based on texture material type
char chTextureType = CHAR_TEX_CONCRETE; char chTextureType = CHAR_TEX_CONCRETE;
cl_entity_t *cl_entity = NULL;
float fvol; float fvol;
float fvolbar; float fvolbar;
char *rgsz[4]; char *rgsz[4];
@ -101,12 +102,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
chTextureType = 0; chTextureType = 0;
// Player // Player
if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) if ( entity == 0 )
{
// hit body
chTextureType = CHAR_TEX_FLESH;
}
else if ( entity == 0 )
{ {
// get texture from entity or world (world is ent(0)) // get texture from entity or world (world is ent(0))
pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd );
@ -135,6 +131,20 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
chTextureType = PM_FindTextureType( szbuffer ); chTextureType = PM_FindTextureType( szbuffer );
} }
} }
else
{
// JoshA: Look up the entity and find the EFLAG_FLESH_SOUND flag.
// This broke at some point then TF:C added prediction.
//
// It used to use Classify of pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE
// to determine what sound to play, but that's server side and isn't available on the client
// and got lost in the translation to that.
// Now the server will replicate that state via an eflag.
cl_entity = gEngfuncs.GetEntityByIndex( entity );
if ( cl_entity && !!( cl_entity->curstate.eflags & EFLAG_FLESH_SOUND ) )
chTextureType = CHAR_TEX_FLESH;
}
switch (chTextureType) switch (chTextureType)
{ {

View file

@ -68,10 +68,14 @@ int CHudGeiger::Draw (float flTime)
int rg[3]; int rg[3];
int i; int i;
if (m_iGeigerRange <= 800 && m_iGeigerRange > 0) if (m_iGeigerRange < 1000 && m_iGeigerRange > 0)
{ {
// peicewise linear is better than continuous formula for this // peicewise linear is better than continuous formula for this
if (m_iGeigerRange > 600) if (m_iGeigerRange > 800)
{
pct = 0; //Con_Printf ( "range > 800\n");
}
else if (m_iGeigerRange > 600)
{ {
pct = 2; pct = 2;
flvol = 0.4; //Con_Printf ( "range > 600\n"); flvol = 0.4; //Con_Printf ( "range > 600\n");

View file

@ -309,49 +309,49 @@ int CHudHealth::DrawPain(float flTime)
if (m_fAttackFront > 0.4) if (m_fAttackFront > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackFront, 0.5 ); shade = a * max( m_fAttackFront, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2; x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2;
y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3; y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3;
SPR_DrawAdditive(0, x, y, NULL); SPR_DrawAdditive(0, x, y, NULL);
m_fAttackFront = max( 0, m_fAttackFront - fFade ); m_fAttackFront = max( 0.0f, m_fAttackFront - fFade );
} else } else
m_fAttackFront = 0; m_fAttackFront = 0;
if (m_fAttackRight > 0.4) if (m_fAttackRight > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackRight, 0.5 ); shade = a * max( m_fAttackRight, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2; x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2;
y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2; y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2;
SPR_DrawAdditive(1, x, y, NULL); SPR_DrawAdditive(1, x, y, NULL);
m_fAttackRight = max( 0, m_fAttackRight - fFade ); m_fAttackRight = max( 0.0f, m_fAttackRight - fFade );
} else } else
m_fAttackRight = 0; m_fAttackRight = 0;
if (m_fAttackRear > 0.4) if (m_fAttackRear > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackRear, 0.5 ); shade = a * max( m_fAttackRear, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2; x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2;
y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2; y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2;
SPR_DrawAdditive(2, x, y, NULL); SPR_DrawAdditive(2, x, y, NULL);
m_fAttackRear = max( 0, m_fAttackRear - fFade ); m_fAttackRear = max( 0.0f, m_fAttackRear - fFade );
} else } else
m_fAttackRear = 0; m_fAttackRear = 0;
if (m_fAttackLeft > 0.4) if (m_fAttackLeft > 0.4)
{ {
GetPainColor(r,g,b); GetPainColor(r,g,b);
shade = a * max( m_fAttackLeft, 0.5 ); shade = a * max( m_fAttackLeft, 0.5f );
ScaleColors(r, g, b, shade); ScaleColors(r, g, b, shade);
SPR_Set(m_hSprite, r, g, b ); SPR_Set(m_hSprite, r, g, b );
@ -359,7 +359,7 @@ int CHudHealth::DrawPain(float flTime)
y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2; y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2;
SPR_DrawAdditive(3, x, y, NULL); SPR_DrawAdditive(3, x, y, NULL);
m_fAttackLeft = max( 0, m_fAttackLeft - fFade ); m_fAttackLeft = max( 0.0f, m_fAttackLeft - fFade );
} else } else
m_fAttackLeft = 0; m_fAttackLeft = 0;

View file

@ -211,8 +211,8 @@ void CHud :: Init( void )
m_iLogo = 0; m_iLogo = 0;
m_iFOV = 0; m_iFOV = 0;
CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 ); CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", FCVAR_ARCHIVE );
default_fov = CVAR_CREATE( "default_fov", "90", 0 ); default_fov = CVAR_CREATE( "default_fov", "90", FCVAR_ARCHIVE );
cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE );
m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE );

View file

@ -50,7 +50,7 @@ void CHud::Think(void)
// think about default fov // think about default fov
if ( m_iFOV == 0 ) if ( m_iFOV == 0 )
{ // only let players adjust up in fov, and only if they are not overriden by something else { // only let players adjust up in fov, and only if they are not overriden by something else
m_iFOV = max( default_fov->value, 90 ); m_iFOV = max<int>( default_fov->value, 90 );;
} }

View file

@ -1,4 +1,4 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ //========= Copyright <EFBFBD> 1996-2001, Valve LLC, All rights reserved. ============
// //
// Purpose: // Purpose:
// //
@ -162,7 +162,8 @@ void UTIL_StringToVector( float * pVector, const char *pString )
char *pstr, *pfront, tempString[128]; char *pstr, *pfront, tempString[128];
int j; int j;
strcpy( tempString, pString ); strncpy( tempString, pString, sizeof( tempString ) );
tempString[ sizeof( tempString ) - 1 ] = '\0';
pstr = pfront = tempString; pstr = pfront = tempString;
for ( j = 0; j < 3; j++ ) for ( j = 0; j < 3; j++ )
@ -578,7 +579,7 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
*/ */
case DRC_CMD_STUFFTEXT: case DRC_CMD_STUFFTEXT:
ClientCmd( READ_STRING() ); FilteredClientCmd( READ_STRING() );
break; break;
default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd ); default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );

View file

@ -9,6 +9,7 @@
// 02/21/97 JCB Added extended DirectInput code to support external controllers. // 02/21/97 JCB Added extended DirectInput code to support external controllers.
#include "port.h" #include "port.h"
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_mouse.h> #include <SDL2/SDL_mouse.h>
#include <SDL2/SDL_gamecontroller.h> #include <SDL2/SDL_gamecontroller.h>
@ -111,7 +112,7 @@ enum _ControlList
DWORD dwAxisMap[ JOY_MAX_AXES ]; DWORD dwAxisMap[ JOY_MAX_AXES ];
DWORD dwControlMap[ JOY_MAX_AXES ]; DWORD dwControlMap[ JOY_MAX_AXES ];
DWORD pdwRawValue[ JOY_MAX_AXES ]; int pdwRawValue[ JOY_MAX_AXES ];
DWORD joy_oldbuttonstate, joy_oldpovstate; DWORD joy_oldbuttonstate, joy_oldpovstate;
int joy_id; int joy_id;
@ -134,6 +135,7 @@ cvar_t *joy_advaxisz;
cvar_t *joy_advaxisr; cvar_t *joy_advaxisr;
cvar_t *joy_advaxisu; cvar_t *joy_advaxisu;
cvar_t *joy_advaxisv; cvar_t *joy_advaxisv;
cvar_t *joy_supported;
cvar_t *joy_forwardthreshold; cvar_t *joy_forwardthreshold;
cvar_t *joy_sidethreshold; cvar_t *joy_sidethreshold;
cvar_t *joy_pitchthreshold; cvar_t *joy_pitchthreshold;
@ -269,6 +271,18 @@ void IN_ResetMouse( void )
{ {
} }
/*
===========
IN_ResetRelativeMouseState
===========
*/
void IN_ResetRelativeMouseState(void)
{
SDL_PumpEvents();
int deltaX, deltaY;
SDL_GetRelativeMouseState(&deltaX, &deltaY);
}
/* /*
=========== ===========
IN_MouseEvent IN_MouseEvent
@ -742,8 +756,6 @@ void IN_JoyMove ( float frametime, usercmd_t *cmd )
{ {
// get the floating point zero-centered, potentially-inverted data for the current axis // get the floating point zero-centered, potentially-inverted data for the current axis
fAxisValue = (float) pdwRawValue[i]; fAxisValue = (float) pdwRawValue[i];
// move centerpoint to zero
fAxisValue -= 32768.0;
if (joy_wwhack2->value != 0.0) if (joy_wwhack2->value != 0.0)
{ {
@ -907,7 +919,7 @@ IN_Init
void IN_Init (void) void IN_Init (void)
{ {
m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE ); m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE );
sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE ); // user mouse sensitivity setting. sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE | FCVAR_FILTERSTUFFTEXT ); // user mouse sensitivity setting.
in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE ); in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE );
joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 ); joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 );
@ -918,6 +930,7 @@ void IN_Init (void)
joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 ); joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 );
joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 ); joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 );
joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 ); joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 );
joy_supported = gEngfuncs.pfnRegisterVariable ( "joysupported", "1", 0 );
joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 ); joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 );
joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 ); joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 );
joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 ); joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 );

Some files were not shown because too many files have changed in this diff Show more