1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-22 17:47:38 +08:00

Added most recent version of unmodified HL2 SDK for Episode 1 engine

This commit is contained in:
Scott Ehlert 2008-09-15 01:00:17 -05:00
commit cb8fd25d1f
3052 changed files with 1217106 additions and 0 deletions

228
Everything_SDK-2003.sln Normal file
View File

@ -0,0 +1,228 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glview", "utils\glview\glview-2003.vcproj", "{BD1604CA-F401-4C4B-821C-251F5AE157FE}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "height2normal", "utils\height2normal\height2normal-2003.vcproj", "{0FDD99E4-130F-493C-8202-4C0236CC47EA}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serverplugin_empty", "utils\serverplugin_sample\serverplugin_empty-2003.vcproj", "{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "studiomdl", "utils\studiomdl\studiomdl-2003.vcproj", "{AE28536E-885A-41BF-99A4-41A7E424B869}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tgadiff", "utils\tgadiff\tgadiff-2003.vcproj", "{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vbsp", "utils\vbsp\vbsp-2003.vcproj", "{B78B6271-B19A-4CF6-926E-40B643548E23}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vice", "utils\vice\vice-2003.vcproj", "{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vprojtomake", "utils\vprojtomake\vprojtomake-2003.vcproj", "{EA55446E-BC04-491C-A9F0-605DFCBB213A}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vrad", "utils\vrad\vrad-2003.vcproj", "{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vrad_launcher", "utils\vrad_launcher\vrad_launcher-2003.vcproj", "{914F19DF-64EC-4E7D-8B01-76477BF06479}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vtf2tga", "utils\vtf2tga\vtf2tga-2003.vcproj", "{2A1F656C-053C-46A4-AE33-304C1D865E0C}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vtfdiff", "utils\vtfdiff\vtfdiff-2003.vcproj", "{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vvis", "utils\vvis\vvis-2003.vcproj", "{5B065E70-6EE0-4B47-BA64-113D2F81220D}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vvis_launcher", "utils\vvis_launcher\vvis_launcher-2003.vcproj", "{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xwad", "utils\xwad\xwad-2003.vcproj", "{B850012C-98A2-42F7-B023-9F65C448D938}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vgui_controls", "vgui2\controls\vgui_controls-2003.vcproj", "{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demoinfo", "utils\demoinfo\demoinfo-2003.vcproj", "{4FE3FDCA-9571-44B3-A521-C81448434490}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "motionmapper", "utils\motionmapper\motionmapper-2003.vcproj", "{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QC_Eyes", "utils\qc_eyes\QC_Eyes-2003.vcproj", "{D373436F-7DBF-468B-A3E4-601FB8556544}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathlib", "mathlib\mathlib-2003.vcproj", "{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tier1", "tier1\tier1-2003.vcproj", "{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phonemeextractor", "utils\phonemeextractor\phonemeextractor-2003.vcproj", "{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlmv", "utils\hlmv\hlmv-2003.vcproj", "{F3704DBF-8055-413C-B027-399E5DBCA4DD}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Debug.ActiveCfg = Debug|Win32
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Debug.Build.0 = Debug|Win32
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Release.ActiveCfg = Release|Win32
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Release.Build.0 = Release|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Debug.ActiveCfg = Debug|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Debug.Build.0 = Debug|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Release.ActiveCfg = Release|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Release.Build.0 = Release|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug.ActiveCfg = Debug|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug.Build.0 = Debug|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release.ActiveCfg = Release|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release.Build.0 = Release|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Debug.ActiveCfg = Debug|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Debug.Build.0 = Debug|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Release.ActiveCfg = Release|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Release.Build.0 = Release|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Debug.ActiveCfg = Debug|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Debug.Build.0 = Debug|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Release.ActiveCfg = Release|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Release.Build.0 = Release|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Debug.ActiveCfg = Debug|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Debug.Build.0 = Debug|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Release.ActiveCfg = Release|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Release.Build.0 = Release|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Debug.ActiveCfg = Debug|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Debug.Build.0 = Debug|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Release.ActiveCfg = Release|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Release.Build.0 = Release|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Debug.ActiveCfg = Debug|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Debug.Build.0 = Debug|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Release.ActiveCfg = Release|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Release.Build.0 = Release|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Debug.ActiveCfg = Debug|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Debug.Build.0 = Debug|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Release.ActiveCfg = Release|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Release.Build.0 = Release|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Debug.ActiveCfg = Debug|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Debug.Build.0 = Debug|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Release.ActiveCfg = Release|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Release.Build.0 = Release|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Debug.ActiveCfg = Debug|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Debug.Build.0 = Debug|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Release.ActiveCfg = Release|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Release.Build.0 = Release|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Debug.ActiveCfg = Debug|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Debug.Build.0 = Debug|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Release.ActiveCfg = Release|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Release.Build.0 = Release|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Debug.ActiveCfg = Debug|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Debug.Build.0 = Debug|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Release.ActiveCfg = Release|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Release.Build.0 = Release|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Debug.ActiveCfg = Debug|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Debug.Build.0 = Debug|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Release.ActiveCfg = Release|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Release.Build.0 = Release|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Debug.ActiveCfg = Debug|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Debug.Build.0 = Debug|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Release.ActiveCfg = Release|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Release.Build.0 = Release|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Debug.ActiveCfg = Debug|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Debug.Build.0 = Debug|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Release.ActiveCfg = Release|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Release.Build.0 = Release|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Debug.ActiveCfg = Debug|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Debug.Build.0 = Debug|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Release.ActiveCfg = Release|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Release.Build.0 = Release|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Debug.ActiveCfg = Debug|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Debug.Build.0 = Debug|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Release.ActiveCfg = Release|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Release.Build.0 = Release|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Debug.ActiveCfg = Debug|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Debug.Build.0 = Debug|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Release.ActiveCfg = Release|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Release.Build.0 = Release|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Debug.ActiveCfg = Debug|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Debug.Build.0 = Debug|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Release.ActiveCfg = Release|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Release.Build.0 = Release|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Debug.ActiveCfg = Debug|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Debug.Build.0 = Debug|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Release.ActiveCfg = Release|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Release.Build.0 = Release|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Debug.ActiveCfg = Debug|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Debug.Build.0 = Debug|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Release.ActiveCfg = Release|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Release.Build.0 = Release|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Debug.ActiveCfg = Debug|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Debug.Build.0 = Debug|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Release.ActiveCfg = Release|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

214
Everything_SDK-2005.sln Normal file
View File

@ -0,0 +1,214 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glview", "utils\glview\glview-2005.vcproj", "{BD1604CA-F401-4C4B-821C-251F5AE157FE}"
ProjectSection(ProjectDependencies) = postProject
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "height2normal", "utils\height2normal\height2normal-2005.vcproj", "{0FDD99E4-130F-493C-8202-4C0236CC47EA}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serverplugin_empty", "utils\serverplugin_sample\serverplugin_empty-2005.vcproj", "{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "studiomdl", "utils\studiomdl\studiomdl-2005.vcproj", "{AE28536E-885A-41BF-99A4-41A7E424B869}"
ProjectSection(ProjectDependencies) = postProject
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tgadiff", "utils\tgadiff\tgadiff-2005.vcproj", "{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vbsp", "utils\vbsp\vbsp-2005.vcproj", "{B78B6271-B19A-4CF6-926E-40B643548E23}"
ProjectSection(ProjectDependencies) = postProject
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vice", "utils\vice\vice-2005.vcproj", "{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vprojtomake", "utils\vprojtomake\vprojtomake-2005.vcproj", "{EA55446E-BC04-491C-A9F0-605DFCBB213A}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vrad", "utils\vrad\vrad-2005.vcproj", "{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vrad_launcher", "utils\vrad_launcher\vrad_launcher-2005.vcproj", "{914F19DF-64EC-4E7D-8B01-76477BF06479}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vtf2tga", "utils\vtf2tga\vtf2tga-2005.vcproj", "{2A1F656C-053C-46A4-AE33-304C1D865E0C}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vtfdiff", "utils\vtfdiff\vtfdiff-2005.vcproj", "{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}"
ProjectSection(ProjectDependencies) = postProject
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vvis", "utils\vvis\vvis-2005.vcproj", "{5B065E70-6EE0-4B47-BA64-113D2F81220D}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vvis_launcher", "utils\vvis_launcher\vvis_launcher-2005.vcproj", "{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xwad", "utils\xwad\xwad-2005.vcproj", "{B850012C-98A2-42F7-B023-9F65C448D938}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vgui_controls", "vgui2\controls\vgui_controls-2005.vcproj", "{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demoinfo", "utils\demoinfo\demoinfo-2005.vcproj", "{4FE3FDCA-9571-44B3-A521-C81448434490}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "motionmapper", "utils\motionmapper\motionmapper-2005.vcproj", "{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}"
ProjectSection(ProjectDependencies) = postProject
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QC_Eyes", "utils\qc_eyes\QC_Eyes-2005.vcproj", "{D373436F-7DBF-468B-A3E4-601FB8556544}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathlib", "mathlib\mathlib-2005.vcproj", "{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tier1", "tier1\tier1-2005.vcproj", "{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phonemeextractor", "utils\phonemeextractor\phonemeextractor-2005.vcproj", "{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}"
ProjectSection(ProjectDependencies) = postProject
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720} = {E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlmv", "utils\hlmv\hlmv-2005.vcproj", "{F3704DBF-8055-413C-B027-399E5DBCA4DD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Debug|Win32.ActiveCfg = Debug|Win32
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Debug|Win32.Build.0 = Debug|Win32
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Release|Win32.ActiveCfg = Release|Win32
{BD1604CA-F401-4C4B-821C-251F5AE157FE}.Release|Win32.Build.0 = Release|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Debug|Win32.ActiveCfg = Debug|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Debug|Win32.Build.0 = Debug|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Release|Win32.ActiveCfg = Release|Win32
{0FDD99E4-130F-493C-8202-4C0236CC47EA}.Release|Win32.Build.0 = Release|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|Win32.ActiveCfg = Debug|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|Win32.Build.0 = Debug|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|Win32.ActiveCfg = Release|Win32
{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|Win32.Build.0 = Release|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Debug|Win32.ActiveCfg = Debug|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Debug|Win32.Build.0 = Debug|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Release|Win32.ActiveCfg = Release|Win32
{AE28536E-885A-41BF-99A4-41A7E424B869}.Release|Win32.Build.0 = Release|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Debug|Win32.ActiveCfg = Debug|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Debug|Win32.Build.0 = Debug|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Release|Win32.ActiveCfg = Release|Win32
{0CE0AF8A-A977-4538-9D63-BCB76DE1BAC6}.Release|Win32.Build.0 = Release|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Debug|Win32.ActiveCfg = Debug|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Debug|Win32.Build.0 = Debug|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Release|Win32.ActiveCfg = Release|Win32
{B78B6271-B19A-4CF6-926E-40B643548E23}.Release|Win32.Build.0 = Release|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Debug|Win32.ActiveCfg = Debug|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Debug|Win32.Build.0 = Debug|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Release|Win32.ActiveCfg = Release|Win32
{3CE6E7A9-89EC-4304-8D72-5B602B4DBD09}.Release|Win32.Build.0 = Release|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Debug|Win32.ActiveCfg = Debug|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Debug|Win32.Build.0 = Debug|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Release|Win32.ActiveCfg = Release|Win32
{EA55446E-BC04-491C-A9F0-605DFCBB213A}.Release|Win32.Build.0 = Release|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Debug|Win32.ActiveCfg = Debug|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Debug|Win32.Build.0 = Debug|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Release|Win32.ActiveCfg = Release|Win32
{FC0F5DE3-F09F-4EF6-98F9-BA762FFF268D}.Release|Win32.Build.0 = Release|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Debug|Win32.ActiveCfg = Debug|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Debug|Win32.Build.0 = Debug|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Release|Win32.ActiveCfg = Release|Win32
{914F19DF-64EC-4E7D-8B01-76477BF06479}.Release|Win32.Build.0 = Release|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Debug|Win32.ActiveCfg = Debug|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Debug|Win32.Build.0 = Debug|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Release|Win32.ActiveCfg = Release|Win32
{2A1F656C-053C-46A4-AE33-304C1D865E0C}.Release|Win32.Build.0 = Release|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Debug|Win32.ActiveCfg = Debug|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Debug|Win32.Build.0 = Debug|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Release|Win32.ActiveCfg = Release|Win32
{0A368DE7-D34A-48D3-B517-996BFF2D0D5D}.Release|Win32.Build.0 = Release|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Debug|Win32.ActiveCfg = Debug|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Debug|Win32.Build.0 = Debug|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Release|Win32.ActiveCfg = Release|Win32
{5B065E70-6EE0-4B47-BA64-113D2F81220D}.Release|Win32.Build.0 = Release|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Debug|Win32.ActiveCfg = Debug|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Debug|Win32.Build.0 = Debug|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Release|Win32.ActiveCfg = Release|Win32
{4C0B9915-E8FF-4089-8927-FC934BFC1E4A}.Release|Win32.Build.0 = Release|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Debug|Win32.ActiveCfg = Debug|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Debug|Win32.Build.0 = Debug|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Release|Win32.ActiveCfg = Release|Win32
{B850012C-98A2-42F7-B023-9F65C448D938}.Release|Win32.Build.0 = Release|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Debug|Win32.ActiveCfg = Debug|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Debug|Win32.Build.0 = Debug|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Release|Win32.ActiveCfg = Release|Win32
{C3CEFD6F-5CDC-41DE-8D43-D932F508F51B}.Release|Win32.Build.0 = Release|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Debug|Win32.ActiveCfg = Debug|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Debug|Win32.Build.0 = Debug|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Release|Win32.ActiveCfg = Release|Win32
{4FE3FDCA-9571-44B3-A521-C81448434490}.Release|Win32.Build.0 = Release|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Debug|Win32.ActiveCfg = Debug|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Debug|Win32.Build.0 = Debug|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Release|Win32.ActiveCfg = Release|Win32
{A882FC08-8B92-4D4F-89BF-75BCEC2BAE11}.Release|Win32.Build.0 = Release|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Debug|Win32.ActiveCfg = Debug|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Debug|Win32.Build.0 = Debug|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Release|Win32.ActiveCfg = Release|Win32
{D373436F-7DBF-468B-A3E4-601FB8556544}.Release|Win32.Build.0 = Release|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Debug|Win32.ActiveCfg = Debug|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Debug|Win32.Build.0 = Debug|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Release|Win32.ActiveCfg = Release|Win32
{E1DA9FB8-FB4C-4B14-91A6-98BCED6B9720}.Release|Win32.Build.0 = Release|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Debug|Win32.ActiveCfg = Debug|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Debug|Win32.Build.0 = Debug|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Release|Win32.ActiveCfg = Release|Win32
{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}.Release|Win32.Build.0 = Release|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Debug|Win32.ActiveCfg = Debug|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Debug|Win32.Build.0 = Debug|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Release|Win32.ActiveCfg = Release|Win32
{8A35F55B-B5C2-47A0-8C4A-5857A8E20385}.Release|Win32.Build.0 = Release|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Debug|Win32.ActiveCfg = Debug|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Debug|Win32.Build.0 = Debug|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Release|Win32.ActiveCfg = Release|Win32
{F3704DBF-8055-413C-B027-399E5DBCA4DD}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

29
Game_HL2-2003.sln Normal file
View File

@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "cl_dll\client_hl2-2003.vcproj", "{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "dlls\server_hl2-2003.vcproj", "{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug HL2 = Debug HL2
Release HL2 = Release HL2
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2.ActiveCfg = Debug HL2|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2.Build.0 = Debug HL2|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2.ActiveCfg = Release HL2|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2.Build.0 = Release HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2.ActiveCfg = Debug HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2.Build.0 = Debug HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2.ActiveCfg = Release HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2.Build.0 = Release HL2|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

25
Game_HL2-2005.sln Normal file
View File

@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_hl2", "cl_dll\client_hl2-2005.vcproj", "{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_hl2", "dlls\server_hl2-2005.vcproj", "{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug HL2|Win32 = Debug HL2|Win32
Release HL2|Win32 = Release HL2|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2|Win32.ActiveCfg = Debug HL2|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2|Win32.Build.0 = Debug HL2|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2|Win32.ActiveCfg = Release HL2|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2|Win32.Build.0 = Release HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2|Win32.ActiveCfg = Debug HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2|Win32.Build.0 = Debug HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2|Win32.ActiveCfg = Release HL2|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2|Win32.Build.0 = Release HL2|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

29
Game_HL2MP-2003.sln Normal file
View File

@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "cl_dll\client_hl2mp-2003.vcproj", "{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "dlls\server_hl2mp-2003.vcproj", "{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug HL2MP = Debug HL2MP
Release HL2MP = Release HL2MP
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2MP.ActiveCfg = Debug HL2MP|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2MP.Build.0 = Debug HL2MP|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2MP.ActiveCfg = Release HL2MP|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2MP.Build.0 = Release HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2MP.ActiveCfg = Debug HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2MP.Build.0 = Debug HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2MP.ActiveCfg = Release HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2MP.Build.0 = Release HL2MP|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

25
Game_HL2MP-2005.sln Normal file
View File

@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_hl2mp", "cl_dll\client_hl2mp-2005.vcproj", "{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_hl2mp", "dlls\server_hl2mp-2005.vcproj", "{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug HL2MP|Win32 = Debug HL2MP|Win32
Release HL2MP|Win32 = Release HL2MP|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2MP|Win32.ActiveCfg = Debug HL2MP|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug HL2MP|Win32.Build.0 = Debug HL2MP|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2MP|Win32.ActiveCfg = Release HL2MP|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release HL2MP|Win32.Build.0 = Release HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2MP|Win32.ActiveCfg = Debug HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug HL2MP|Win32.Build.0 = Debug HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2MP|Win32.ActiveCfg = Release HL2MP|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release HL2MP|Win32.Build.0 = Release HL2MP|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

29
Game_Scratch-2003.sln Normal file
View File

@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "cl_dll\client_scratch-2003.vcproj", "{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "dlls\server_scratch-2003.vcproj", "{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug SDK = Debug SDK
Release SDK = Release SDK
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug SDK.ActiveCfg = Debug SDK|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug SDK.Build.0 = Debug SDK|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release SDK.ActiveCfg = Release SDK|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release SDK.Build.0 = Release SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug SDK.ActiveCfg = Debug SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug SDK.Build.0 = Debug SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release SDK.ActiveCfg = Release SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release SDK.Build.0 = Release SDK|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

25
Game_Scratch-2005.sln Normal file
View File

@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_sdk", "cl_dll\client_scratch-2005.vcproj", "{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_sdk", "dlls\server_scratch-2005.vcproj", "{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug SDK|Win32 = Debug SDK|Win32
Release SDK|Win32 = Release SDK|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug SDK|Win32.ActiveCfg = Debug SDK|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Debug SDK|Win32.Build.0 = Debug SDK|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release SDK|Win32.ActiveCfg = Release SDK|Win32
{E44D6502-2BB4-47F8-85CF-ACDD4FC18329}.Release SDK|Win32.Build.0 = Release SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug SDK|Win32.ActiveCfg = Debug SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Debug SDK|Win32.Build.0 = Debug SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release SDK|Win32.ActiveCfg = Release SDK|Win32
{1AA0213B-2B68-40CD-90F8-CFDFD37C1550}.Release SDK|Win32.Build.0 = Release SDK|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,53 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Acts exactly like "AnimatedTexture", but ONLY if the texture
// it's working on matches the desired texture to work on.
//
// This assumes that some other proxy will be switching out the textures.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/ITexture.h"
#include "BaseAnimatedTextureProxy.h"
#include "utlstring.h"
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimateSpecificTexture : public CBaseAnimatedTextureProxy
{
private:
CUtlString m_OnlyAnimateOnTexture;
public:
virtual float GetAnimationStartTime( void* pBaseEntity ) { return 0; }
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
};
bool CAnimateSpecificTexture::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pszAnimateOnTexture = pKeyValues->GetString( "onlyAnimateOnTexture" );
if( !pszAnimateOnTexture )
return false;
m_OnlyAnimateOnTexture.Set( pszAnimateOnTexture );
return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
}
void CAnimateSpecificTexture::OnBind( void *pC_BaseEntity )
{
if( FStrEq( m_AnimatedTextureVar->GetTextureValue()->GetName(), m_OnlyAnimateOnTexture ) )
{
CBaseAnimatedTextureProxy::OnBind( pC_BaseEntity );
}
//else do nothing
}
EXPOSE_INTERFACE( CAnimateSpecificTexture, IMaterialProxy, "AnimateSpecificTexture" IMATERIAL_PROXY_INTERFACE_VERSION );

View File

@ -0,0 +1,778 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Material Modify control entity.
//
//=============================================================================//
#include "cbase.h"
#include "ProxyEntity.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/ITexture.h"
#include "iviewrender.h"
#include "texture_group_names.h"
#include "BaseAnimatedTextureProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define MATERIAL_MODIFY_STRING_SIZE 255
#define MATERIAL_MODIFY_ANIMATION_UNSET -1
// Must match MaterialModifyControl.cpp
enum MaterialModifyMode_t
{
MATERIAL_MODIFY_MODE_NONE = 0,
MATERIAL_MODIFY_MODE_SETVAR = 1,
MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2,
MATERIAL_MODIFY_MODE_FLOAT_LERP = 3,
};
ConVar debug_materialmodifycontrol_client( "debug_materialmodifycontrol_client", "0" );
struct materialanimcommands_t
{
int iFrameStart;
int iFrameEnd;
bool bWrap;
float flFrameRate;
};
struct materialfloatlerpcommands_t
{
int flStartValue;
int flEndValue;
float flTransitionTime;
};
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
class C_MaterialModifyControl : public C_BaseEntity
{
public:
DECLARE_CLASS( C_MaterialModifyControl, C_BaseEntity );
C_MaterialModifyControl();
void OnPreDataChanged( DataUpdateType_t updateType );
void OnDataChanged( DataUpdateType_t updateType );
bool ShouldDraw();
IMaterial *GetMaterial( void ) { return m_pMaterial; }
const char *GetMaterialVariableName( void ) { return m_szMaterialVar; }
const char *GetMaterialVariableValue( void ) { return m_szMaterialVarValue; }
DECLARE_CLIENTCLASS();
// Animated texture and Float Lerp usage
bool HasNewAnimationCommands( void ) { return m_bHasNewAnimationCommands; }
void ClearAnimationCommands( void ) { m_bHasNewAnimationCommands = false; }
// Animated texture usage
void GetAnimationCommands( materialanimcommands_t *pCommands );
// FloatLerp usage
void GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands );
void SetAnimationStartTime( float flTime )
{
m_flAnimationStartTime = flTime;
}
float GetAnimationStartTime( void ) const
{
return m_flAnimationStartTime;
}
MaterialModifyMode_t GetModifyMode( void ) const
{
return ( MaterialModifyMode_t)m_nModifyMode;
}
private:
char m_szMaterialName[MATERIAL_MODIFY_STRING_SIZE];
char m_szMaterialVar[MATERIAL_MODIFY_STRING_SIZE];
char m_szMaterialVarValue[MATERIAL_MODIFY_STRING_SIZE];
IMaterial *m_pMaterial;
bool m_bHasNewAnimationCommands;
// Animation commands from the server
int m_iFrameStart;
int m_iFrameEnd;
bool m_bWrap;
float m_flFramerate;
bool m_bNewAnimCommandsSemaphore;
bool m_bOldAnimCommandsSemaphore;
// Float lerp commands from the server
float m_flFloatLerpStartValue;
float m_flFloatLerpEndValue;
float m_flFloatLerpTransitionTime;
bool m_bFloatLerpWrap;
float m_flAnimationStartTime;
int m_nModifyMode;
};
IMPLEMENT_CLIENTCLASS_DT(C_MaterialModifyControl, DT_MaterialModifyControl, CMaterialModifyControl)
RecvPropString( RECVINFO( m_szMaterialName ) ),
RecvPropString( RECVINFO( m_szMaterialVar ) ),
RecvPropString( RECVINFO( m_szMaterialVarValue ) ),
RecvPropInt( RECVINFO(m_iFrameStart) ),
RecvPropInt( RECVINFO(m_iFrameEnd) ),
RecvPropInt( RECVINFO(m_bWrap) ),
RecvPropFloat( RECVINFO(m_flFramerate) ),
RecvPropInt( RECVINFO(m_bNewAnimCommandsSemaphore) ),
RecvPropFloat( RECVINFO(m_flFloatLerpStartValue) ),
RecvPropFloat( RECVINFO(m_flFloatLerpEndValue) ),
RecvPropFloat( RECVINFO(m_flFloatLerpTransitionTime) ),
RecvPropInt( RECVINFO(m_bFloatLerpWrap) ),
RecvPropInt( RECVINFO(m_nModifyMode) ),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
C_MaterialModifyControl::C_MaterialModifyControl()
{
m_pMaterial = NULL;
m_bOldAnimCommandsSemaphore = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_bOldAnimCommandsSemaphore = m_bNewAnimCommandsSemaphore;
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void C_MaterialModifyControl::OnDataChanged( DataUpdateType_t updateType )
{
if( updateType == DATA_UPDATE_CREATED )
{
m_pMaterial = materials->FindMaterial( m_szMaterialName, TEXTURE_GROUP_OTHER );
// Clear out our variables
m_bHasNewAnimationCommands = true;
}
// Detect changes in the anim commands
if ( m_bNewAnimCommandsSemaphore != m_bOldAnimCommandsSemaphore )
{
m_bHasNewAnimationCommands = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::GetAnimationCommands( materialanimcommands_t *pCommands )
{
pCommands->iFrameStart = m_iFrameStart;
pCommands->iFrameEnd = m_iFrameEnd;
pCommands->bWrap = m_bWrap;
pCommands->flFrameRate = m_flFramerate;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands )
{
pCommands->flStartValue = m_flFloatLerpStartValue;
pCommands->flEndValue = m_flFloatLerpEndValue;
pCommands->flTransitionTime = m_flFloatLerpTransitionTime;
}
//------------------------------------------------------------------------------
// Purpose: We don't draw.
//------------------------------------------------------------------------------
bool C_MaterialModifyControl::ShouldDraw()
{
return false;
}
//=============================================================================
//
// THE MATERIALMODIFYPROXY ITSELF
//
class CMaterialModifyProxy : public CBaseAnimatedTextureProxy
{
public:
CMaterialModifyProxy();
virtual ~CMaterialModifyProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pEntity );
private:
void OnBindSetVar( C_MaterialModifyControl *pControl );
void OnBindAnimatedTexture( C_MaterialModifyControl *pControl );
void OnBindFloatLerp( C_MaterialModifyControl *pControl );
float GetAnimationStartTime( void* pArg );
void AnimationWrapped( void* pArg );
IMaterial *m_pMaterial;
// texture animation stuff
int m_iFrameStart;
int m_iFrameEnd;
bool m_bReachedEnd;
bool m_bCustomWrap;
float m_flCustomFramerate;
// float lerp stuff
IMaterialVar *m_pMaterialVar;
int m_flStartValue;
int m_flEndValue;
float m_flStartTime;
float m_flTransitionTime;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMaterialModifyProxy::CMaterialModifyProxy()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMaterialModifyProxy::~CMaterialModifyProxy()
{
}
bool CMaterialModifyProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// set var stuff
m_pMaterial = pMaterial;
// float lerp stuff
m_flStartValue = MATERIAL_MODIFY_ANIMATION_UNSET;
m_flEndValue = MATERIAL_MODIFY_ANIMATION_UNSET;
// animated stuff
// m_pMaterial = pMaterial;
// m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
// m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
// m_bReachedEnd = false;
// return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
return true;
}
void CMaterialModifyProxy::OnBind( void *pEntity )
{
// Get the modified material vars from the entity input
IClientRenderable *pRend = (IClientRenderable *)pEntity;
if ( pRend )
{
C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pBaseEntity )
{
if( debug_materialmodifycontrol_client.GetBool() )
{
// DevMsg( 1, "%s\n", pBaseEntity->GetDebugName() );
}
int numChildren = 0;
bool gotOne = false;
for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
{
numChildren++;
C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
if ( !pControl )
continue;
if( debug_materialmodifycontrol_client.GetBool() )
{
// DevMsg( 1, "pControl: 0x%p\n", pControl );
}
switch( pControl->GetModifyMode() )
{
case MATERIAL_MODIFY_MODE_NONE:
break;
case MATERIAL_MODIFY_MODE_SETVAR:
gotOne = true;
OnBindSetVar( pControl );
break;
case MATERIAL_MODIFY_MODE_ANIM_SEQUENCE:
OnBindAnimatedTexture( pControl );
break;
case MATERIAL_MODIFY_MODE_FLOAT_LERP:
OnBindFloatLerp( pControl );
break;
default:
Assert( 0 );
break;
}
}
if( gotOne )
{
// DevMsg( 1, "numChildren: %d\n", numChildren );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindSetVar( C_MaterialModifyControl *pControl )
{
IMaterial *pMaterial = pControl->GetMaterial();
if( !pMaterial )
{
Assert( 0 );
return;
}
if ( pMaterial != m_pMaterial )
{
// Warning( "\t%s!=%s\n", pMaterial->GetName(), m_pMaterial->GetName() );
return;
}
bool bFound;
IMaterialVar *pMaterialVar = pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
if ( !bFound )
return;
if( Q_strcmp( pControl->GetMaterialVariableValue(), "" ) )
{
// const char *pMaterialName = m_pMaterial->GetName();
// const char *pMaterialVarName = pMaterialVar->GetName();
// const char *pMaterialVarValue = pControl->GetMaterialVariableValue();
// if( debug_materialmodifycontrol_client.GetBool()
// && Q_stristr( m_pMaterial->GetName(), "faceandhair" )
// && Q_stristr( pMaterialVar->GetName(), "self" )
// )
// {
// static int count = 0;
// DevMsg( 1, "CMaterialModifyProxy::OnBindSetVar \"%s\" %s=%s %d pControl=0x%p\n",
// m_pMaterial->GetName(), pMaterialVar->GetName(), pControl->GetMaterialVariableValue(), count++, pControl );
// }
pMaterialVar->SetValueAutodetectType( pControl->GetMaterialVariableValue() );
}
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindAnimatedTexture( C_MaterialModifyControl *pControl )
{
assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
return;
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
if ( !pControl )
return;
if ( pControl->HasNewAnimationCommands() )
{
// Read the data from the modify entity
materialanimcommands_t sCommands;
pControl->GetAnimationCommands( &sCommands );
m_iFrameStart = sCommands.iFrameStart;
m_iFrameEnd = sCommands.iFrameEnd;
m_bCustomWrap = sCommands.bWrap;
m_flCustomFramerate = sCommands.flFrameRate;
m_bReachedEnd = false;
m_flStartTime = gpGlobals->curtime;
pControl->ClearAnimationCommands();
}
// Init all the vars based on whether we're using the base material settings,
// or the custom ones from the entity input.
int numFrames;
bool bWrapAnimation;
float flFrameRate;
int iLastFrame;
// Do we have a custom frame section from the server?
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
{
m_iFrameEnd = pTexture->GetNumAnimationFrames();
}
numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
bWrapAnimation = m_bCustomWrap;
flFrameRate = m_flCustomFramerate;
iLastFrame = (m_iFrameEnd - 1);
}
else
{
numFrames = pTexture->GetNumAnimationFrames();
bWrapAnimation = m_WrapAnimation;
flFrameRate = m_FrameRate;
iLastFrame = (numFrames - 1);
}
// Have we already reached the end? If so, stay there.
if ( m_bReachedEnd && !bWrapAnimation )
{
m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
startTime = m_flStartTime;
}
else
{
startTime = GetAnimationStartTime(pControl);
}
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = flFrameRate * deltaTime;
float prevFrame = flFrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
intFrame += m_iFrameStart;
intPrevFrame += m_iFrameStart;
}
// Report wrap situation...
if (intPrevFrame > intFrame)
{
m_bReachedEnd = true;
if (bWrapAnimation)
{
AnimationWrapped( pControl );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pControl );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CMaterialModifyProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindFloatLerp( C_MaterialModifyControl *pControl )
{
if ( !pControl )
return;
if ( pControl->HasNewAnimationCommands() )
{
pControl->SetAnimationStartTime( gpGlobals->curtime );
pControl->ClearAnimationCommands();
}
// Read the data from the modify entity
materialfloatlerpcommands_t sCommands;
pControl->GetFloatLerpCommands( &sCommands );
m_flStartValue = sCommands.flStartValue;
m_flEndValue = sCommands.flEndValue;
m_flTransitionTime = sCommands.flTransitionTime;
m_flStartTime = pControl->GetAnimationStartTime();
bool bFound;
m_pMaterialVar = m_pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
if( bFound )
{
float currentValue;
if( m_flTransitionTime > 0.0f )
{
currentValue = m_flStartValue + ( m_flEndValue - m_flStartValue ) * clamp( ( ( gpGlobals->curtime - m_flStartTime ) / m_flTransitionTime ), 0.0f, 1.0f );
}
else
{
currentValue = m_flEndValue;
}
if( debug_materialmodifycontrol_client.GetBool() && Q_stristr( m_pMaterial->GetName(), "faceandhair" ) && Q_stristr( m_pMaterialVar->GetName(), "warp" ) )
{
static int count = 0;
DevMsg( 1, "CMaterialFloatLerpProxy::OnBind \"%s\" %s=%f %d\n", m_pMaterial->GetName(), m_pMaterialVar->GetName(), currentValue, count++ );
}
m_pMaterialVar->SetFloatValue( currentValue );
}
}
//=============================================================================
//
// MATERIALMODIFYANIMATED PROXY
//
class CMaterialModifyAnimatedProxy : public CBaseAnimatedTextureProxy
{
public:
CMaterialModifyAnimatedProxy() {};
virtual ~CMaterialModifyAnimatedProxy() {};
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pEntity );
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void AnimationWrapped( void* pC_BaseEntity );
private:
IMaterial *m_pMaterial;
int m_iFrameStart;
int m_iFrameEnd;
bool m_bReachedEnd;
float m_flStartTime;
bool m_bCustomWrap;
float m_flCustomFramerate;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CMaterialModifyAnimatedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMaterial = pMaterial;
m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
m_bReachedEnd = false;
return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::OnBind( void *pEntity )
{
assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
return;
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
// Get the modified material vars from the entity input
IClientRenderable *pRend = (IClientRenderable *)pEntity;
if ( pRend )
{
C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pBaseEntity )
{
for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
{
C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
if ( !pControl )
continue;
if ( !pControl->HasNewAnimationCommands() )
continue;
// Read the data from the modify entity
materialanimcommands_t sCommands;
pControl->GetAnimationCommands( &sCommands );
m_iFrameStart = sCommands.iFrameStart;
m_iFrameEnd = sCommands.iFrameEnd;
m_bCustomWrap = sCommands.bWrap;
m_flCustomFramerate = sCommands.flFrameRate;
m_bReachedEnd = false;
m_flStartTime = gpGlobals->curtime;
pControl->ClearAnimationCommands();
}
}
}
// Init all the vars based on whether we're using the base material settings,
// or the custom ones from the entity input.
int numFrames;
bool bWrapAnimation;
float flFrameRate;
int iLastFrame;
// Do we have a custom frame section from the server?
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
{
m_iFrameEnd = pTexture->GetNumAnimationFrames();
}
numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
bWrapAnimation = m_bCustomWrap;
flFrameRate = m_flCustomFramerate;
iLastFrame = (m_iFrameEnd - 1);
}
else
{
numFrames = pTexture->GetNumAnimationFrames();
bWrapAnimation = m_WrapAnimation;
flFrameRate = m_FrameRate;
iLastFrame = (numFrames - 1);
}
// Have we already reached the end? If so, stay there.
if ( m_bReachedEnd && !bWrapAnimation )
{
m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
startTime = m_flStartTime;
}
else
{
startTime = GetAnimationStartTime(pEntity);
}
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = flFrameRate * deltaTime;
float prevFrame = flFrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
intFrame += m_iFrameStart;
intPrevFrame += m_iFrameStart;
}
// Report wrap situation...
if (intPrevFrame > intFrame)
{
m_bReachedEnd = true;
if (bWrapAnimation)
{
AnimationWrapped( pEntity );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pEntity );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CMaterialModifyAnimatedProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}
EXPOSE_INTERFACE( CMaterialModifyProxy, IMaterialProxy, "MaterialModify" IMATERIAL_PROXY_INTERFACE_VERSION );
EXPOSE_INTERFACE( CMaterialModifyAnimatedProxy, IMaterialProxy, "MaterialModifyAnimated" IMATERIAL_PROXY_INTERFACE_VERSION );

231
cl_dll/EffectsClient.cpp Normal file
View File

@ -0,0 +1,231 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility code.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "IEffects.h"
#include "fx.h"
#include "c_te_legacytempents.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Client-server neutral effects interface
//-----------------------------------------------------------------------------
class CEffectsClient : public IEffects
{
public:
CEffectsClient();
virtual ~CEffectsClient();
// Members of the IEffect interface
virtual void Beam( const Vector &Start, const Vector &End, int nModelIndex,
int nHaloIndex, unsigned char frameStart, unsigned char frameRate,
float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength,
unsigned char noise, unsigned char red, unsigned char green,
unsigned char blue, unsigned char brightness, unsigned char speed);
virtual void Smoke( const Vector &origin, int modelIndex, float scale, float framerate );
virtual void Sparks( const Vector &position, int nMagnitude = 1, int nTrailLength = 1, const Vector *pvecDir = NULL );
virtual void Dust( const Vector &pos, const Vector &dir, float size, float speed );
virtual void MuzzleFlash( const Vector &origin, const QAngle &angles, float fScale, int type );
virtual void MetalSparks( const Vector &position, const Vector &direction );
virtual void EnergySplash( const Vector &position, const Vector &direction, bool bExplosive = false );
virtual void Ricochet( const Vector &position, const Vector &direction );
// FIXME: Should these methods remain in this interface? Or go in some
// other client-server neutral interface?
virtual float Time();
virtual bool IsServer();
virtual void SuppressEffectsSounds( bool bSuppress );
private:
//-----------------------------------------------------------------------------
// Purpose: Returning true means don't even call TE func
// Input : filter -
// *suppress_host -
// Output : static bool
//-----------------------------------------------------------------------------
bool SuppressTE( C_RecipientFilter& filter )
{
if ( !CanPredict() )
return true;
if ( !filter.GetRecipientCount() )
{
// Suppress it
return true;
}
// There's at least one recipient
return false;
}
bool m_bSuppressSound;
};
//-----------------------------------------------------------------------------
// Client-server neutral effects interface accessor
//-----------------------------------------------------------------------------
static CEffectsClient s_EffectClient;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEffectsClient, IEffects, IEFFECTS_INTERFACE_VERSION, s_EffectClient);
IEffects *g_pEffects = &s_EffectClient;
ConVar r_decals("r_decals","0");
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CEffectsClient::CEffectsClient()
{
m_bSuppressSound = false;
}
CEffectsClient::~CEffectsClient()
{
}
//-----------------------------------------------------------------------------
// Suppress sound on effects
//-----------------------------------------------------------------------------
void CEffectsClient::SuppressEffectsSounds( bool bSuppress )
{
m_bSuppressSound = bSuppress;
}
//-----------------------------------------------------------------------------
// Generates a beam
//-----------------------------------------------------------------------------
void CEffectsClient::Beam( const Vector &vecStartPoint, const Vector &vecEndPoint,
int nModelIndex, int nHaloIndex, unsigned char frameStart, unsigned char nFrameRate,
float flLife, unsigned char nWidth, unsigned char nEndWidth, unsigned char nFadeLength,
unsigned char noise, unsigned char r, unsigned char g,
unsigned char b, unsigned char brightness, unsigned char nSpeed)
{
Assert(0);
// CBroadcastRecipientFilter filter;
// if ( !SuppressTE( filter ) )
// {
// beams->CreateBeamPoints( vecStartPoint, vecEndPoint, nModelIndex, nHaloIndex,
// m_fHaloScale,
// flLife, 0.1 * nWidth, 0.1 * nEndWidth, nFadeLength, 0.01 * nAmplitude, a, 0.1 * nSpeed,
// m_nStartFrame, 0.1 * nFrameRate, r, g, b );
// }
}
//-----------------------------------------------------------------------------
// Generates various tempent effects
//-----------------------------------------------------------------------------
void CEffectsClient::Smoke( const Vector &vecOrigin, int modelIndex, float scale, float framerate )
{
CPVSFilter filter( vecOrigin );
if ( !SuppressTE( filter ) )
{
int iColor = random->RandomInt(20,35);
color32 color;
color.r = iColor;
color.g = iColor;
color.b = iColor;
color.a = iColor;
QAngle angles;
VectorAngles( Vector(0,0,1), angles );
FX_Smoke( vecOrigin, angles, scale * 0.1f, 4, (unsigned char *)&color, 255 );
}
}
void CEffectsClient::Sparks( const Vector &position, int nMagnitude, int nTrailLength, const Vector *pVecDir )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_ElectricSpark( position, nMagnitude, nTrailLength, pVecDir );
}
}
void CEffectsClient::Dust( const Vector &pos, const Vector &dir, float size, float speed )
{
CPVSFilter filter( pos );
if ( !SuppressTE( filter ) )
{
FX_Dust( pos, dir, size, speed );
}
}
void CEffectsClient::MuzzleFlash( const Vector &vecOrigin, const QAngle &vecAngles, float flScale, int iType )
{
CPVSFilter filter( vecOrigin );
if ( !SuppressTE( filter ) )
{
switch( iType )
{
case MUZZLEFLASH_TYPE_DEFAULT:
FX_MuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
break;
case MUZZLEFLASH_TYPE_GUNSHIP:
FX_GunshipMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
break;
case MUZZLEFLASH_TYPE_STRIDER:
FX_StriderMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
break;
default:
Msg("No case for Muzzleflash type: %d\n", iType );
break;
}
}
}
void CEffectsClient::MetalSparks( const Vector &position, const Vector &direction )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_MetalSpark( position, direction, direction );
}
}
void CEffectsClient::EnergySplash( const Vector &position, const Vector &direction, bool bExplosive )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_EnergySplash( position, direction, bExplosive );
}
}
void CEffectsClient::Ricochet( const Vector &position, const Vector &direction )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_MetalSpark( position, direction, direction );
if ( !m_bSuppressSound )
{
FX_RicochetSound( position );
}
}
}
// FIXME: Should these methods remain in this interface? Or go in some
// other client-server neutral interface?
float CEffectsClient::Time()
{
return gpGlobals->curtime;
}
bool CEffectsClient::IsServer()
{
return false;
}

View File

@ -0,0 +1,60 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
// $monitorTextureVar
class CMonitorMaterialProxy : public IMaterialProxy
{
public:
CMonitorMaterialProxy();
virtual ~CMonitorMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
private:
IMaterialVar *m_pMonitorTextureVar;
};
CMonitorMaterialProxy::CMonitorMaterialProxy()
{
m_pMonitorTextureVar = NULL;
}
CMonitorMaterialProxy::~CMonitorMaterialProxy()
{
m_pMonitorTextureVar = NULL;
}
bool CMonitorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pMonitorTextureVarName = pKeyValues->getString( "$monitorTextureVar" );
if( !pMonitorTextureVarName )
return false;
bool foundVar;
m_pMonitorTextureVar = pMaterial->FindVar( pMonitorTextureVarName, &foundVar, false );
if( !foundVar )
{
m_pMonitorTextureVar = NULL;
return false;
}
return true;
}
void CMonitorMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !m_pMonitorTextureVar )
{
return;
}
}
EXPOSE_INTERFACE( CMonitorMaterialProxy, IMaterialProxy, "Monitor" IMATERIAL_PROXY_INTERFACE_VERSION );

50
cl_dll/ProxyHealth.cpp Normal file
View File

@ -0,0 +1,50 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "FunctionProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Returns the player health (from 0 to 1)
//-----------------------------------------------------------------------------
class CProxyHealth : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CProxyHealth::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CProxyHealth::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Assert( m_pResult );
SetFloatResult( pEntity->HealthFraction() * m_Factor.GetFloat() );
}
EXPOSE_INTERFACE( CProxyHealth, IMaterialProxy, "Health" IMATERIAL_PROXY_INTERFACE_VERSION );

View File

@ -0,0 +1,454 @@
#include "cbase.h"
#include "keyvalues.h"
#include "cdll_client_int.h"
#include "view_scene.h"
#include "viewrender.h"
#include "vstdlib/icommandline.h"
#include "materialsystem/IMesh.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/IColorCorrection.h"
#include "ScreenSpaceEffects.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar mat_colorcorrection( "mat_colorcorrection", "1" );
//------------------------------------------------------------------------------
// CScreenSpaceEffectRegistration code
// Used to register and effect with the IScreenSpaceEffectManager
//------------------------------------------------------------------------------
CScreenSpaceEffectRegistration *CScreenSpaceEffectRegistration::s_pHead = NULL;
CScreenSpaceEffectRegistration::CScreenSpaceEffectRegistration( const char *pName, IScreenSpaceEffect *pEffect )
{
m_pEffectName = pName;
m_pEffect = pEffect;
m_pNext = s_pHead;
s_pHead = this;
}
//------------------------------------------------------------------------------
// CScreenSpaceEffectManager - Implementation of IScreenSpaceEffectManager
//------------------------------------------------------------------------------
class CScreenSpaceEffectManager : public IScreenSpaceEffectManager
{
public:
virtual void InitScreenSpaceEffects( );
virtual void ShutdownScreenSpaceEffects( );
virtual IScreenSpaceEffect *GetScreenSpaceEffect( const char *pEffectName );
virtual void SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params );
virtual void SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params );
virtual void EnableScreenSpaceEffect( const char *pEffectName );
virtual void EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect );
virtual void DisableScreenSpaceEffect( const char *pEffectName );
virtual void DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect );
virtual void DisableAllScreenSpaceEffects( );
virtual void RenderEffects( int x, int y, int w, int h );
};
CScreenSpaceEffectManager g_ScreenSpaceEffectManager;
IScreenSpaceEffectManager *g_pScreenSpaceEffects = &g_ScreenSpaceEffectManager;
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::InitScreenSpaceEffects - Initialise all registered effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::InitScreenSpaceEffects( )
{
if ( CommandLine()->FindParm( "-colorcorrection" ) || CommandLine()->FindParm( "-tools" ) )
{
GetScreenSpaceEffect( "colorcorrection" )->Enable( true );
}
if ( CommandLine()->FindParm( "-filmgrain" ) )
{
GetScreenSpaceEffect( "filmgrain" )->Enable( true );
}
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
bool bIsEnabled = pEffect->IsEnabled( );
pEffect->Init( );
pEffect->Enable( bIsEnabled );
}
}
}
//----------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::ShutdownScreenSpaceEffects - Shutdown all registered effects
//----------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::ShutdownScreenSpaceEffects( )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Shutdown( );
}
}
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::GetScreenSpaceEffect - Returns a point to the named effect
//---------------------------------------------------------------------------------------
IScreenSpaceEffect *CScreenSpaceEffectManager::GetScreenSpaceEffect( const char *pEffectName )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
if( !Q_stricmp( pReg->m_pEffectName, pEffectName ) )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
return pEffect;
}
}
Warning( "Could not find screen space effect %s\n", pEffectName );
return NULL;
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::SetScreenSpaceEffectParams
// - Assign parameters to the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
SetScreenSpaceEffectParams( pEffect, params );
}
void CScreenSpaceEffectManager::SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params )
{
if( pEffect )
pEffect->SetParameters( params );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::EnableScreenSpaceEffect
// - Enables the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::EnableScreenSpaceEffect( const char *pEffectName )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
EnableScreenSpaceEffect( pEffect );
}
void CScreenSpaceEffectManager::EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect )
{
if( pEffect )
pEffect->Enable( true );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::DisableScreenSpaceEffect
// - Disables the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::DisableScreenSpaceEffect( const char *pEffectName )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
DisableScreenSpaceEffect( pEffect );
}
void CScreenSpaceEffectManager::DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect )
{
if( pEffect )
pEffect->Enable( false );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::DisableAllScreenSpaceEffects
// - Disables all registered screen space effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::DisableAllScreenSpaceEffects( )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Enable( false );
}
}
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::RenderEffects
// - Renders all registered screen space effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::RenderEffects( int x, int y, int w, int h )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Render( x, y, w, h );
}
}
}
//------------------------------------------------------------------------------
// Color correction post-processing effect
//------------------------------------------------------------------------------
class CColorCorrectionEffect : public IScreenSpaceEffect
{
public:
CColorCorrectionEffect( );
~CColorCorrectionEffect( );
void Init( );
void Shutdown( );
void SetParameters( KeyValues *params );
void Render( int x, int y, int w, int h );
void Enable( bool bEnable );
bool IsEnabled( );
private:
bool m_bEnable;
CMaterialReference m_Material;
bool m_bSplitScreen;
};
ADD_SCREENSPACE_EFFECT( CColorCorrectionEffect, colorcorrection );
//------------------------------------------------------------------------------
// CColorCorrectionEffect constructor
//------------------------------------------------------------------------------
CColorCorrectionEffect::CColorCorrectionEffect( )
{
m_bSplitScreen = false;
}
//------------------------------------------------------------------------------
// CColorCorrectionEffect destructor
//------------------------------------------------------------------------------
CColorCorrectionEffect::~CColorCorrectionEffect( )
{
}
//------------------------------------------------------------------------------
// CColorCorrectionEffect init
//------------------------------------------------------------------------------
void CColorCorrectionEffect::Init( )
{
m_Material.Init( "engine/colorcorrection", TEXTURE_GROUP_OTHER );
m_bEnable = false;
}
//------------------------------------------------------------------------------
// CColorCorrectionEffect shutdown
//------------------------------------------------------------------------------
void CColorCorrectionEffect::Shutdown( )
{
m_Material.Shutdown();
}
//------------------------------------------------------------------------------
// CColorCorrectionEffect enable
//------------------------------------------------------------------------------
void CColorCorrectionEffect::Enable( bool bEnable )
{
if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel()<90 && bEnable )
{
Msg( "Color correction can not be enabled when not in DX9 mode.\n" );
bEnable = false;
}
else
{
m_bEnable = bEnable;
}
}
bool CColorCorrectionEffect::IsEnabled( )
{
return m_bEnable;
}
//------------------------------------------------------------------------------
// CColorCorrectionEffect SetParameters
//------------------------------------------------------------------------------
void CColorCorrectionEffect::SetParameters( KeyValues *params )
{
if( params->GetDataType( "split_screen" ) == KeyValues::TYPE_STRING )
{
int ival = params->GetInt( "split_screen" );
m_bSplitScreen = ival?true:false;
}
}
//------------------------------------------------------------------------------
// CColorCorrectionEffect render
//------------------------------------------------------------------------------
void CColorCorrectionEffect::Render( int x, int y, int w, int h )
{
// We're releasing the CS:S client before the engine with this interface, so we need to fail gracefully
if( mat_colorcorrection.GetInt()==0 || !colorcorrection )
{
return;
}
if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel()<90 )
{
mat_colorcorrection.SetValue( 0 );
return;
}
colorcorrection->NormalizeWeights();
if( colorcorrection->GetNumLookups()==0 )
{
return;
}
// Set up shader inputs (there has to be a better way to do this)
int paramCount = m_Material->ShaderParamCount();
IMaterialVar **pParams = m_Material->GetShaderParams();
for( int i=0;i<paramCount;i++ )
{
IMaterialVar *pVar = pParams[i];
if( !Q_stricmp( pVar->GetName(), "$weight_default" ) )
{
pVar->SetFloatValue( colorcorrection->GetLookupWeight(-1) );
}
else if( !Q_stricmp( pVar->GetName(), "$weight0" ) )
{
pVar->SetFloatValue( colorcorrection->GetLookupWeight(0) );
}
else if( !Q_stricmp( pVar->GetName(), "$weight1" ) )
{
pVar->SetFloatValue( colorcorrection->GetLookupWeight(1) );
}
else if( !Q_stricmp( pVar->GetName(), "$weight2" ) )
{
pVar->SetFloatValue( colorcorrection->GetLookupWeight(2) );
}
else if( !Q_stricmp( pVar->GetName(), "$weight3" ) )
{
pVar->SetFloatValue( colorcorrection->GetLookupWeight(3) );
}
else if( !Q_stricmp( pVar->GetName(), "$num_lookups" ) )
{
pVar->SetIntValue( colorcorrection->GetNumLookups() );
}
else if( !Q_stricmp( pVar->GetName(), "$use_fb_texture" ) )
{
pVar->SetIntValue( 1 );
}
}
colorcorrection->ResetLookupWeights();
// Render Effect
Rect_t actualRect;
UpdateScreenEffectTexture( 0, x, y, w, h, false, &actualRect );
ITexture *pTexture = GetFullFrameFrameBufferTexture( 0 );
if( m_bSplitScreen )
{
w /= 2;
x += w;
actualRect.x = actualRect.x + actualRect.width/2;
actualRect.width = actualRect.width/2;
}
// Tempororary hack... Color correction was crashing on the first frame
// when run outside the debugger for some mods (DoD). This forces it to skip
// a frame, ensuring we don't get the weird texture crash we otherwise would.
// This will be removed when the true cause is found
static bool bFirstFrame = true;
if( !bFirstFrame )
{
materials->DrawScreenSpaceRectangle( m_Material, x, y, w, h,
actualRect.x, actualRect.y, actualRect.x+actualRect.width-1, actualRect.y+actualRect.height-1,
pTexture->GetActualWidth(), pTexture->GetActualHeight() );
}
bFirstFrame = false;
}
//------------------------------------------------------------------------------
// Console Interface
//------------------------------------------------------------------------------
static void EnableColorCorrection( ConVar *var, char const *pOldString )
{
if( var->GetBool() )
{
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "colorcorrection" );
}
else
{
g_pScreenSpaceEffects->DisableScreenSpaceEffect( "colorcorrection" );
}
}
static void SetScreenEffectParam()
{
if( engine->Cmd_Argc() >= 4 )
{
const char *effect_type = engine->Cmd_Argv(1);
int num_params = (engine->Cmd_Argc()-2)/2;
if( engine->Cmd_Argc() != num_params*2+2 )
{
Msg( "Missing hald of key/value pair.\n" );
return;
}
KeyValues *params = new KeyValues( "params" );
for( int i=0;i<num_params;i++ )
{
params->SetString( engine->Cmd_Argv( i*2 + 2 ), engine->Cmd_Argv( i*2 + 3 ) );
}
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( effect_type, params );
}
}
// Console interface for setting screen space effect parameters
// Format:
// set_effect_param effect_type param_name param_value
// eg set_effect_param 1 $noise_scale "255 255 255 0"
static ConCommand set_screen_effect_param( "set_screen_effect_param", SetScreenEffectParam, "Set a parameter for one of the screen space effects.", FCVAR_CHEAT );

View File

@ -0,0 +1,88 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=====================================================================================//
#ifndef SCREENSPACEEFFECTS_H
#define SCREENSPACEEFFECTS_H
#ifdef _WIN32
#pragma once
#endif
class KeyValues;
//------------------------------------------------------------------------------
// Simple base class for screen space post-processing effects
//------------------------------------------------------------------------------
abstract_class IScreenSpaceEffect
{
public:
virtual void Init( ) = 0;
virtual void Shutdown( ) = 0;
virtual void SetParameters( KeyValues *params ) = 0;
virtual void Render( int x, int y, int w, int h ) = 0;
virtual void Enable( bool bEnable ) = 0;
virtual bool IsEnabled( ) = 0;
};
//------------------------------------------------------------------------------
// Interface class for managing screen space post-processing effects
//------------------------------------------------------------------------------
abstract_class IScreenSpaceEffectManager
{
public:
virtual void InitScreenSpaceEffects( ) = 0;
virtual void ShutdownScreenSpaceEffects( ) = 0;
virtual IScreenSpaceEffect *GetScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params ) = 0;
virtual void SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params ) = 0;
virtual void EnableScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect ) = 0;
virtual void DisableScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect ) = 0;
virtual void DisableAllScreenSpaceEffects( ) = 0;
virtual void RenderEffects( int x, int y, int w, int h ) = 0;
};
extern IScreenSpaceEffectManager *g_pScreenSpaceEffects;
//-------------------------------------------------------------------------------------
// Registration class for adding screen space effects to the IScreenSpaceEffectManager
//-------------------------------------------------------------------------------------
class CScreenSpaceEffectRegistration
{
public:
CScreenSpaceEffectRegistration( const char *pName, IScreenSpaceEffect *pEffect );
const char *m_pEffectName;
IScreenSpaceEffect *m_pEffect;
CScreenSpaceEffectRegistration *m_pNext;
static CScreenSpaceEffectRegistration *s_pHead;
};
#define ADD_SCREENSPACE_EFFECT( CEffect, pEffectName ) CEffect pEffectName##_effect; \
CScreenSpaceEffectRegistration pEffectName##_reg( #pEffectName, &pEffectName##_effect );
#endif

172
cl_dll/TeamBitmapImage.cpp Normal file
View File

@ -0,0 +1,172 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "teambitmapimage.h"
#include <KeyValues.h>
#include "vgui_BitmapImage.h"
#include "PanelMetaClassMgr.h"
#include "vguimatsurface/IMatSystemSurface.h"
#include <vgui_controls/Panel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// A multiplexer bitmap that chooses a bitmap based on team
//-----------------------------------------------------------------------------
CTeamBitmapImage::CTeamBitmapImage() : m_Alpha(1.0f)
{
memset( m_ppImage, 0, BITMAP_COUNT * sizeof(BitmapImage*) );
m_pEntity = NULL;
m_bRelativeTeams = 0;
}
CTeamBitmapImage::~CTeamBitmapImage()
{
int i;
for ( i = 0; i < BITMAP_COUNT; ++i )
{
if (m_ppImage[i])
delete m_ppImage[i];
}
}
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
bool CTeamBitmapImage::Init( vgui::Panel *pParent, KeyValues* pInitData, C_BaseEntity* pEntity )
{
static char *pRelativeTeamNames[BITMAP_COUNT] =
{
"NoTeam",
"MyTeam",
"EnemyTeam",
};
static char *pAbsoluteTeamNames[BITMAP_COUNT] =
{
"Team0",
"Team1",
"Team2",
};
m_pEntity = pEntity;
m_bRelativeTeams = (pInitData->GetInt( "relativeteam" ) != 0);
char **ppTeamNames = m_bRelativeTeams ? pRelativeTeamNames : pAbsoluteTeamNames;
int i;
for ( i = 0 ; i < BITMAP_COUNT; ++i )
{
// Default to null
m_ppImage[i] = NULL;
// Look for team section
KeyValues *pTeamKV = pInitData->FindKey( ppTeamNames[i] );
if ( !pTeamKV )
continue;
char const* pClassImage = pTeamKV->GetString( "material" );
if ( !pClassImage || !pClassImage[ 0 ] )
return false;
// modulation color
Color color;
if (!ParseRGBA( pTeamKV, "color", color ))
color.SetColor( 255, 255, 255, 255 );
// hook in the bitmap
m_ppImage[i] = new BitmapImage( pParent->GetVPanel(), pClassImage );
m_ppImage[i]->SetColor( color );
}
return true;
}
//-----------------------------------------------------------------------------
// Alpha modulate...
//-----------------------------------------------------------------------------
void CTeamBitmapImage::SetAlpha( float alpha )
{
m_Alpha = clamp( alpha, 0.0f, 1.0f );
}
//-----------------------------------------------------------------------------
// draw
//-----------------------------------------------------------------------------
void CTeamBitmapImage::Paint( float yaw /*= 0.0f*/ )
{
if (m_Alpha == 0.0f)
return;
int team = 0;
if (m_bRelativeTeams)
{
if (GetEntity())
{
if (GetEntity()->GetTeamNumber() != 0)
{
team = GetEntity()->InLocalTeam() ? 1 : 2;
}
}
}
else
{
if (GetEntity())
team = GetEntity()->GetTeamNumber();
}
// Paint the image for the current team
if (m_ppImage[team])
{
// Modulate the color based on the alpha....
Color color = m_ppImage[team]->GetColor();
int alpha = color[3];
color[3] = (alpha * m_Alpha);
m_ppImage[team]->SetColor( color );
if ( yaw != 0.0f )
{
g_pMatSystemSurface->DisableClipping( true );
m_ppImage[team]->DoPaint( m_ppImage[team]->GetRenderSizePanel(), yaw );
g_pMatSystemSurface->DisableClipping( false );
}
else
{
// Paint
m_ppImage[team]->Paint();
}
// restore previous color
color[3] = alpha;
m_ppImage[team]->SetColor( color );
}
}
//-----------------------------------------------------------------------------
// Helper method to initialize a team image from KeyValues data..
//-----------------------------------------------------------------------------
bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName, vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pTeamImage )
{
KeyValues *pTeamImageSection = pInitData;
if (pSectionName)
{
pTeamImageSection = pInitData->FindKey( pSectionName );
if ( !pTeamImageSection )
return false;
}
return pTeamImage->Init( pParent, pTeamImageSection, pEntity );
}

80
cl_dll/TeamBitmapImage.h Normal file
View File

@ -0,0 +1,80 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef TEAMBITMAPIMAGE_H
#define TEAMBITMAPIMAGE_H
#ifdef _WIN32
#pragma once
#endif
//#include "tf_shareddefs.h"
#include <vgui/VGUI.h>
namespace vgui
{
class Panel;
}
class BitmapImage;
class C_BaseEntity;
class KeyValues;
//-----------------------------------------------------------------------------
// A multiplexer bitmap that chooses a bitmap based on team
//-----------------------------------------------------------------------------
class CTeamBitmapImage
{
public:
// construction, destruction
CTeamBitmapImage();
~CTeamBitmapImage();
// initialization
bool Init( vgui::Panel *pParent, KeyValues* pInitData, C_BaseEntity* pEntity );
// Alpha override...
void SetAlpha( float alpha );
// Paint the sucka. Paint it the size of the parent panel
void Paint( float yaw = 0.0f );
protected:
// Wrapper so we can implement this with EHANDLES some day
C_BaseEntity *GetEntity() { return m_pEntity; }
private:
enum
{
// NOTE: Was MAX_TF_TEAMS not 4, but I don't like the dependency here.
BITMAP_COUNT = 4 + 1
};
BitmapImage *m_ppImage[ BITMAP_COUNT ];
C_BaseEntity *m_pEntity;
float m_Alpha;
bool m_bRelativeTeams;
};
//-----------------------------------------------------------------------------
// Helper method to initialize a team image from KeyValues data..
// KeyValues contains the bitmap data. pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pBitmapImage );
#endif // TEAMBITMAPIMAGE_H

83
cl_dll/ViewConeImage.cpp Normal file
View File

@ -0,0 +1,83 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ViewConeImage.h"
#include <KeyValues.h>
#include <vgui_controls/Panel.h>
#include "vguimatsurface/IMatSystemSurface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
bool CViewConeImage::Init( vgui::Panel *pParent, KeyValues* pInitData )
{
Assert( pParent );
// Load viewcone material
if (!m_Image.Init( pParent->GetVPanel(), pInitData ))
return false;
// Position the view cone...
int viewconesize = pInitData->GetInt( "size", 32 );
m_Image.SetRenderSize( viewconesize, viewconesize );
int cx, cy;
pParent->GetSize( cx, cy );
m_Image.SetPos( (cx - viewconesize) / 2, (cy - viewconesize) / 2 );
return true;
}
//-----------------------------------------------------------------------------
// Paint the sucka
//-----------------------------------------------------------------------------
void CViewConeImage::Paint( float yaw )
{
g_pMatSystemSurface->DisableClipping( true );
m_Image.DoPaint( NULL, yaw );
g_pMatSystemSurface->DisableClipping( false );
}
void CViewConeImage::SetColor( int r, int g, int b )
{
m_Image.SetColor( Color( r, g, b, 255 ) );
}
//-----------------------------------------------------------------------------
// Helper method to initialize a view cone image from KeyValues data..
// KeyValues contains the bitmap data, pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage )
{
KeyValues *pViewConeImageSection;
if (pSectionName)
{
pViewConeImageSection = pInitData->FindKey( pSectionName );
if ( !pViewConeImageSection )
return false;
}
else
{
pViewConeImageSection = pInitData;
}
return pViewConeImage->Init( pParent, pViewConeImageSection );
}

56
cl_dll/ViewConeImage.h Normal file
View File

@ -0,0 +1,56 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which draws a viewcone
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef VIEWCONEIMAGE_H
#define VIEWCONEIMAGE_H
#include "shareddefs.h"
#include "VGUI_BitmapImage.h"
namespace vgui
{
class Panel;
}
class C_BaseEntity;
class KeyValues;
//-----------------------------------------------------------------------------
// A bitmap that renders a view cone based on angles
//-----------------------------------------------------------------------------
class CViewConeImage
{
public:
// initialization
bool Init( vgui::Panel *pParent, KeyValues* pInitData );
// Paint the sucka
void Paint( float yaw );
void SetColor( int r, int g, int b );
private:
BitmapImage m_Image;
};
//-----------------------------------------------------------------------------
// Helper method to initialize a view cone image from KeyValues data..
// KeyValues contains the bitmap data, pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage );
#endif // VIEWCONEIMAGE_H

View File

@ -0,0 +1,68 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "iviewrender.h"
//#include "VMatrix.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// no inputs, assumes that the results go into $CHEAPWATERSTARTDISTANCE and $CHEAPWATERENDDISTANCE
class CWaterLODMaterialProxy : public IMaterialProxy
{
public:
CWaterLODMaterialProxy();
virtual ~CWaterLODMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
private:
IMaterialVar *m_pCheapWaterStartDistanceVar;
IMaterialVar *m_pCheapWaterEndDistanceVar;
};
CWaterLODMaterialProxy::CWaterLODMaterialProxy()
{
m_pCheapWaterStartDistanceVar = NULL;
m_pCheapWaterEndDistanceVar = NULL;
}
CWaterLODMaterialProxy::~CWaterLODMaterialProxy()
{
}
bool CWaterLODMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool foundVar;
m_pCheapWaterStartDistanceVar = pMaterial->FindVar( "$CHEAPWATERSTARTDISTANCE", &foundVar, false );
if( !foundVar )
return false;
m_pCheapWaterEndDistanceVar = pMaterial->FindVar( "$CHEAPWATERENDDISTANCE", &foundVar, false );
if( !foundVar )
return false;
return true;
}
void CWaterLODMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !m_pCheapWaterStartDistanceVar || !m_pCheapWaterEndDistanceVar )
{
return;
}
float start, end;
view->GetWaterLODParams( start, end );
m_pCheapWaterStartDistanceVar->SetFloatValue( start );
m_pCheapWaterEndDistanceVar->SetFloatValue( end );
}
EXPOSE_INTERFACE( CWaterLODMaterialProxy, IMaterialProxy, "WaterLOD" IMATERIAL_PROXY_INTERFACE_VERSION );

63
cl_dll/WorldDimsProxy.cpp Normal file
View File

@ -0,0 +1,63 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "c_world.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CWorldDimsProxy : public IMaterialProxy
{
public:
CWorldDimsProxy();
virtual ~CWorldDimsProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
public:
IMaterialVar *m_pMinsVar;
IMaterialVar *m_pMaxsVar;
};
CWorldDimsProxy::CWorldDimsProxy()
{
m_pMinsVar = m_pMaxsVar = NULL;
}
CWorldDimsProxy::~CWorldDimsProxy()
{
}
bool CWorldDimsProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMinsVar = pMaterial->FindVar( "$world_mins", NULL, false );
m_pMaxsVar = pMaterial->FindVar( "$world_maxs", NULL, false );
return true;
}
void CWorldDimsProxy::OnBind( void *pC_BaseEntity )
{
if ( m_pMinsVar && m_pMaxsVar )
{
C_World *pWorld = GetClientWorldEntity();
if ( pWorld )
{
m_pMinsVar->SetVecValue( (const float*)&pWorld->m_WorldMins, 3 );
m_pMaxsVar->SetVecValue( (const float*)&pWorld->m_WorldMaxs, 3 );
}
}
}
EXPOSE_INTERFACE( CWorldDimsProxy, IMaterialProxy, "WorldDims" IMATERIAL_PROXY_INTERFACE_VERSION );

View File

@ -0,0 +1,53 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ProxyEntity.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// $sineVar : name of variable that controls the alpha level (float)
class CAlphaMaterialProxy : public CEntityMaterialProxy
{
public:
CAlphaMaterialProxy();
virtual ~CAlphaMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( C_BaseEntity *pEntity );
private:
IMaterialVar *m_AlphaVar;
};
CAlphaMaterialProxy::CAlphaMaterialProxy()
{
m_AlphaVar = NULL;
}
CAlphaMaterialProxy::~CAlphaMaterialProxy()
{
}
bool CAlphaMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool foundVar;
m_AlphaVar = pMaterial->FindVar( "$alpha", &foundVar, false );
return foundVar;
}
void CAlphaMaterialProxy::OnBind( C_BaseEntity *pEnt )
{
if (m_AlphaVar)
{
m_AlphaVar->SetFloatValue( pEnt->m_clrRender->a );
}
}
EXPOSE_INTERFACE( CAlphaMaterialProxy, IMaterialProxy, "Alpha" IMATERIAL_PROXY_INTERFACE_VERSION );

View File

@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedEntityTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedEntityTextureProxy() {}
virtual ~CAnimatedEntityTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void AnimationWrapped( void* pC_BaseEntity );
};
EXPOSE_INTERFACE( CAnimatedEntityTextureProxy, IMaterialProxy, "AnimatedEntityTexture" IMATERIAL_PROXY_INTERFACE_VERSION );
float CAnimatedEntityTextureProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
void CAnimatedEntityTextureProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}

View File

@ -0,0 +1,56 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedOffsetTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedOffsetTextureProxy() : m_flFrameOffset( 0.0f ) {}
virtual ~CAnimatedOffsetTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void OnBind( void *pBaseEntity );
protected:
float m_flFrameOffset;
};
EXPOSE_INTERFACE( CAnimatedOffsetTextureProxy, IMaterialProxy, "AnimatedOffsetTexture" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Purpose:
// Input : pArg -
// Output : float
//-----------------------------------------------------------------------------
float CAnimatedOffsetTextureProxy::GetAnimationStartTime( void* pArg )
{
return m_flFrameOffset;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pBaseEntity -
//-----------------------------------------------------------------------------
void CAnimatedOffsetTextureProxy::OnBind( void *pBaseEntity )
{
C_BaseEntity* pEntity = (C_BaseEntity*)pBaseEntity;
if ( pEntity )
{
m_flFrameOffset = pEntity->GetTextureAnimationStartTime();
}
// Call into the base class
CBaseAnimatedTextureProxy::OnBind( pBaseEntity );
}

View File

@ -0,0 +1,29 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedTextureProxy() {}
virtual ~CAnimatedTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
};
EXPOSE_INTERFACE( CAnimatedTextureProxy, IMaterialProxy, "AnimatedTexture" IMATERIAL_PROXY_INTERFACE_VERSION );
#pragma warning (disable : 4100)
float CAnimatedTextureProxy::GetAnimationStartTime( void* pBaseEntity )
{
return 0;
}

167
cl_dll/animationlayer.h Normal file
View File

@ -0,0 +1,167 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef ANIMATIONLAYER_H
#define ANIMATIONLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "rangecheckedvar.h"
#include "lerp_functions.h"
class C_AnimationLayer
{
public:
// This allows the datatables to access private members.
ALLOW_DATATABLES_PRIVATE_ACCESS();
C_AnimationLayer();
void SetOrder( int order );
public:
bool IsActive( void );
CRangeCheckedVar<int, -1, 2048, 0> m_nSequence;
CRangeCheckedVar<float, -2, 2, 0> m_flPrevCycle;
CRangeCheckedVar<float, -5, 5, 0> m_flWeight;
int m_nOrder;
// used for automatic crossfades between sequence changes
CRangeCheckedVar<float, -50, 50, 1> m_flPlaybackRate;
CRangeCheckedVar<float, -2, 2, 0> m_flCycle;
float GetFadeout( float flCurTime );
float m_flLayerAnimtime;
float m_flLayerFadeOuttime;
};
#ifdef CLIENT_DLL
#define CAnimationLayer C_AnimationLayer
#endif
inline C_AnimationLayer::C_AnimationLayer()
{
m_nSequence = 0;
m_flPrevCycle = 0;
m_flWeight = 0;
m_flPlaybackRate = 0;
m_flCycle = 0;
m_flLayerAnimtime = 0;
m_flLayerFadeOuttime = 0;
}
inline void C_AnimationLayer::SetOrder( int order )
{
m_nOrder = order;
}
inline float C_AnimationLayer::GetFadeout( float flCurTime )
{
float s;
if (m_flLayerFadeOuttime <= 0.0f)
{
s = 0;
}
else
{
// blend in over 0.2 seconds
s = 1.0 - (flCurTime - m_flLayerAnimtime) / m_flLayerFadeOuttime;
if (s > 0 && s <= 1.0)
{
// do a nice spline curve
s = 3 * s * s - 2 * s * s * s;
}
else if ( s > 1.0f )
{
// Shouldn't happen, but maybe curtime is behind animtime?
s = 1.0f;
}
}
return s;
}
inline C_AnimationLayer LoopingLerp( float flPercent, C_AnimationLayer from, C_AnimationLayer to )
{
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = LoopingLerp( flPercent, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
return output;
}
inline C_AnimationLayer Lerp( float flPercent, const C_AnimationLayer& from, const C_AnimationLayer& to )
{
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = Lerp( flPercent, from.m_flCycle, to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
return output;
}
inline C_AnimationLayer LoopingLerp_Hermite( float flPercent, C_AnimationLayer prev, C_AnimationLayer from, C_AnimationLayer to )
{
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = LoopingLerp_Hermite( flPercent, (float)prev.m_flCycle, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
return output;
}
// YWB: Specialization for interpolating euler angles via quaternions...
inline C_AnimationLayer Lerp_Hermite( float flPercent, const C_AnimationLayer& prev, const C_AnimationLayer& from, const C_AnimationLayer& to )
{
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = Lerp_Hermite( flPercent, prev.m_flCycle, from.m_flCycle, to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
return output;
}
inline void Lerp_Clamp( C_AnimationLayer &val )
{
Lerp_Clamp( val.m_nSequence );
Lerp_Clamp( val.m_flCycle );
Lerp_Clamp( val.m_flPrevCycle );
Lerp_Clamp( val.m_flWeight );
Lerp_Clamp( val.m_nOrder );
Lerp_Clamp( val.m_flLayerAnimtime );
Lerp_Clamp( val.m_flLayerFadeOuttime );
}
#endif // ANIMATIONLAYER_H

View File

@ -0,0 +1,124 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/ITexture.h"
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Constructor, destructor:
//-----------------------------------------------------------------------------
CBaseAnimatedTextureProxy::CBaseAnimatedTextureProxy()
{
Cleanup();
}
CBaseAnimatedTextureProxy::~CBaseAnimatedTextureProxy()
{
Cleanup();
}
//-----------------------------------------------------------------------------
// Initialization, shutdown
//-----------------------------------------------------------------------------
bool CBaseAnimatedTextureProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pAnimatedTextureVarName = pKeyValues->GetString( "animatedTextureVar" );
if( !pAnimatedTextureVarName )
return false;
bool foundVar;
m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false );
if( !foundVar )
return false;
char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" );
if( !pAnimatedTextureFrameNumVarName )
return false;
m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false );
if( !foundVar )
return false;
m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 );
m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 );
return true;
}
void CBaseAnimatedTextureProxy::Cleanup()
{
m_AnimatedTextureVar = NULL;
m_AnimatedTextureFrameNumVar = NULL;
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CBaseAnimatedTextureProxy::OnBind( void *pEntity )
{
Assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
{
return;
}
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
int numFrames = pTexture->GetNumAnimationFrames();
if ( numFrames <= 0 )
{
Assert( !"0 frames in material calling animated texture proxy" );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime = GetAnimationStartTime(pEntity);
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = m_FrameRate * deltaTime;
float prevFrame = m_FrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
// Report wrap situation...
if (intPrevFrame > intFrame)
{
if (m_WrapAnimation)
{
AnimationWrapped( pEntity );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pEntity );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}

View File

@ -0,0 +1,46 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BASEANIMATEDTEXTUREPROXY
#define BASEANIMATEDTEXTUREPROXY
#include "materialsystem/IMaterialProxy.h"
class IMaterial;
class IMaterialVar;
#pragma warning (disable : 4100)
class CBaseAnimatedTextureProxy : public IMaterialProxy
{
public:
CBaseAnimatedTextureProxy();
virtual ~CBaseAnimatedTextureProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
protected:
// derived classes must implement this; it returns the time
// that the animation began
virtual float GetAnimationStartTime( void* pBaseEntity ) = 0;
// Derived classes may implement this if they choose;
// this method is called whenever the animation wraps...
virtual void AnimationWrapped( void* pBaseEntity ) {}
protected:
void Cleanup();
IMaterialVar *m_AnimatedTextureVar;
IMaterialVar *m_AnimatedTextureFrameNumVar;
float m_FrameRate;
bool m_WrapAnimation;
};
#endif // BASEANIMATEDTEXTUREPROXY

View File

@ -0,0 +1,81 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation for CBaseClientRenderTargets class.
// Provides Init functions for common render textures used by the engine.
// Mod makers can inherit from this class, and call the Create functions for
// only the render textures the want for their mod.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseclientrendertargets.h" // header
#include "materialsystem/imaterialsystemhardwareconfig.h" // Hardware config checks
ITexture* CBaseClientRenderTargets::CreateWaterReflectionTexture( IMaterialSystem* pMaterialSystem )
{
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_WaterReflection",
1024, 1024, RT_SIZE_PICMIP,
pMaterialSystem->GetBackBufferFormat(),
MATERIAL_RT_DEPTH_SHARED,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
}
ITexture* CBaseClientRenderTargets::CreateWaterRefractionTexture( IMaterialSystem* pMaterialSystem )
{
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_WaterRefraction",
1024, 1024, RT_SIZE_PICMIP,
// This is different than reflection because it has to have alpha for fog factor.
IMAGE_FORMAT_RGBA8888,
MATERIAL_RT_DEPTH_SHARED,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
}
ITexture* CBaseClientRenderTargets::CreateCameraTexture( IMaterialSystem* pMaterialSystem )
{
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_Camera",
256, 256, RT_SIZE_DEFAULT,
pMaterialSystem->GetBackBufferFormat(),
MATERIAL_RT_DEPTH_SHARED,
0,
CREATERENDERTARGETFLAGS_HDR );
}
//-----------------------------------------------------------------------------
// Purpose: Called by the engine in material system init and shutdown.
// Clients should override this in their inherited version, but the base
// is to init all standard render targets for use.
// Input : pMaterialSystem - the engine's material system (our singleton is not yet inited at the time this is called)
// pHardwareConfig - the user hardware config, useful for conditional render target setup
//-----------------------------------------------------------------------------
void CBaseClientRenderTargets::InitClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig )
{
// Water effects
m_WaterReflectionTexture.Init( CreateWaterReflectionTexture( pMaterialSystem ) );
m_WaterRefractionTexture.Init ( CreateWaterRefractionTexture( pMaterialSystem ) );
// Monitors
m_CameraTexture.Init ( CreateCameraTexture( pMaterialSystem ) );
}
//-----------------------------------------------------------------------------
// Purpose: Shut down each CTextureReference we created in InitClientRenderTargets.
// Called by the engine in material system shutdown.
// Input : -
//-----------------------------------------------------------------------------
void CBaseClientRenderTargets::ShutdownClientRenderTargets()
{
// Water effects
m_WaterReflectionTexture.Shutdown();
m_WaterRefractionTexture.Shutdown();
// Monitors
m_CameraTexture.Shutdown();
}

View File

@ -0,0 +1,61 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Has init functions for all the standard render targets used by most games.
// Mods who wish to make their own render targets can inherit from this class
// and in the 'InitClientRenderTargets' interface called by the engine, set up
// their own render targets as well as calling the init functions for various
// common render targets provided by this class.
//
// Note: Unless the client defines a singleton interface by inheriting from
// this class and exposing the singleton instance, these init and shutdown
// functions WILL NOT be called by the engine.
//
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef CLIENTRENDERTARTETS_H_
#define CLIENTRENDERTARTETS_H_
#ifdef _WIN32
#pragma once
#endif
#include "cl_dll\iclientrendertargets.h" // base class with interfaces called by the engine
#include "materialsystem\imaterialsystem.h" // for material system classes and interfaces
// Externs
class IMaterialSystem;
class IMaterialSystemHardwareConfig;
class CBaseClientRenderTargets : public IClientRenderTargets
{
// no networked vars
DECLARE_CLASS_GAMEROOT( CBaseClientRenderTargets, IClientRenderTargets );
public:
// Interface called by engine during material system startup.
virtual void InitClientRenderTargets ( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig );
// Shutdown all custom render targets here.
virtual void ShutdownClientRenderTargets ( void );
protected:
// Standard render textures used by most mods-- Classes inheriting from
// this can choose to init these or not depending on their needs.
// For reflective and refracting water
CTextureReference m_WaterReflectionTexture;
CTextureReference m_WaterRefractionTexture;
// Used for monitors
CTextureReference m_CameraTexture;
// Init functions for the common render targets
ITexture* CreateWaterReflectionTexture( IMaterialSystem* pMaterialSystem );
ITexture* CreateWaterRefractionTexture( IMaterialSystem* pMaterialSystem );
ITexture* CreateCameraTexture( IMaterialSystem* pMaterialSystem );
};
#endif // CLIENTRENDERTARTETS_H_

1733
cl_dll/beamdraw.cpp Normal file

File diff suppressed because it is too large Load Diff

219
cl_dll/beamdraw.h Normal file
View File

@ -0,0 +1,219 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( BEAMDRAW_H )
#define BEAMDRAW_H
#ifdef _WIN32
#pragma once
#endif
#include "materialsystem/imaterial.h"
#include "materialsystem/imesh.h"
#include "vector.h"
#include "c_pixel_visibility.h"
#define NOISE_DIVISIONS 128
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct model_t;
struct BeamTrail_t;
//-----------------------------------------------------------------------------
// Purpose: Beams fill out this data structure
// This is also used for rendering
//-----------------------------------------------------------------------------
class Beam_t : public CDefaultClientRenderable
{
public:
Beam_t();
// Methods of IClientRenderable
virtual const Vector& GetRenderOrigin( void );
virtual const QAngle& GetRenderAngles( void );
virtual const matrix3x4_t &RenderableToWorldTransform();
virtual void GetRenderBounds( Vector& mins, Vector& maxs );
virtual bool ShouldDraw( void );
virtual bool IsTransparent( void );
virtual int DrawModel( int flags );
virtual void ComputeFxBlend( );
virtual int GetFxBlend( );
// Resets the beam state
void Reset();
// Method to computing the bounding box
void ComputeBounds();
// Bounding box...
Vector m_Mins;
Vector m_Maxs;
pixelvis_handle_t *m_queryHandleHalo;
float m_haloProxySize;
// Data is below..
// Next beam in list
Beam_t* next;
// Type of beam
int type;
int flags;
// Control points for the beam
int numAttachments;
Vector attachment[MAX_BEAM_ENTS];
Vector delta;
// 0 .. 1 over lifetime of beam
float t;
float freq;
// Time when beam should die
float die;
float width;
float endWidth;
float fadeLength;
float amplitude;
float life;
// Color
float r, g, b;
float brightness;
// Speed
float speed;
// Animation
float frameRate;
float frame;
int segments;
// Attachment entities for the beam
EHANDLE entity[MAX_BEAM_ENTS];
int attachmentIndex[MAX_BEAM_ENTS];
// Model info
int modelIndex;
int haloIndex;
float haloScale;
int frameCount;
float rgNoise[NOISE_DIVISIONS+1];
// Popcorn trail for beam follows to use
BeamTrail_t* trail;
// for TE_BEAMRINGPOINT
float start_radius;
float end_radius;
// for FBEAM_ONLYNOISEONCE
bool m_bCalculatedNoise;
float m_flHDRColorScale;
};
// ---------------------------------------------------------------- //
// CBeamSegDraw is a simple interface to beam rendering.
// ---------------------------------------------------------------- //
class CBeamSeg
{
public:
Vector m_vPos;
Vector m_vColor;
float m_flTexCoord; // Y texture coordinate
float m_flWidth;
float m_flAlpha;
};
class CBeamSegDraw
{
public:
// Pass null for pMaterial if you have already set the material you want.
void Start( int nSegs, IMaterial *pMaterial=0, CMeshBuilder *pMeshBuilder = NULL, int nMeshVertCount = 0 );
virtual void NextSeg( CBeamSeg *pSeg );
void End();
protected:
void SpecifySeg( const Vector &vNextPos );
void ComputeNormal( const Vector &vStartPos, const Vector &vNextPos, Vector *pNormal );
CMeshBuilder *m_pMeshBuilder;
int m_nMeshVertCount;
CMeshBuilder m_Mesh;
CBeamSeg m_Seg;
int m_nTotalSegs;
int m_nSegsDrawn;
Vector m_vNormalLast;
};
class CBeamSegDrawArbitrary : public CBeamSegDraw
{
public:
void SetNormal( const Vector &normal );
void NextSeg( CBeamSeg *pSeg );
protected:
CBeamSeg m_PrevSeg;
void SpecifySeg( const Vector &vNextPos );
};
int ScreenTransform( const Vector& point, Vector& screen );
void DrawSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawTeslaSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawSplineSegs( int noise_divisions, float *prgNoise,
const model_t* beammodel, const model_t* halomodel, float flHaloScale,
float frame, int rendermode, int numAttachments, Vector* attachment,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawHalo(IMaterial* pMaterial, const Vector& source, float scale, float const* color, float flHDRColorScale = 1.0f );
void BeamDrawHalo( const model_t* spritemodel, float frame, int rendermode, const Vector& source,
float scale, float* color, float flHDRColorScale = 1.0f );
void DrawDisk( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float width, float scale, float freq, float speed,
int segments, float* color, float flHDRColorScale = 1.0f );
void DrawCylinder( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source,
const Vector& delta, float width, float scale, float freq,
float speed, int segments, float* color, float flHDRColorScale = 1.0f );
void DrawRing( int noise_divisions, float *prgNoise, void (*pfnNoise)( float *noise, int divs, float scale ),
const model_t* spritemodel, float frame, int rendermode,
const Vector& source, const Vector& delta, float width, float amplitude,
float freq, float speed, int segments, float* color, float flHDRColorScale = 1.0f );
void DrawBeamFollow( const model_t* spritemodel, BeamTrail_t* pHead, int frame, int rendermode, Vector& delta,
Vector& screen, Vector& screenLast, float die, const Vector& source,
int flags, float width, float amplitude, float freq, float* color, float flHDRColorScale = 1.0f );
void DrawBeamQuadratic( const Vector &start, const Vector &control, const Vector &end, float width, const Vector &color, float scrollOffset, float flHDRColorScale = 1.0f );
class CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode );
//-----------------------------------------------------------------------------
// Assumes the material has already been bound
//-----------------------------------------------------------------------------
void DrawSprite( const Vector &vecOrigin, float flWidth, float flHeight, color32 color );
#endif // BEAMDRAW_H

164
cl_dll/bone_merge_cache.cpp Normal file
View File

@ -0,0 +1,164 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "bone_merge_cache.h"
#include "bone_setup.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// CBoneMergeCache
//-----------------------------------------------------------------------------
CBoneMergeCache::CBoneMergeCache()
{
m_pOwner = NULL;
m_pFollow = NULL;
m_pFollowHdr = NULL;
m_pOwnerHdr = NULL;
m_nFollowBoneSetupMask = 0;
}
void CBoneMergeCache::Init( C_BaseAnimating *pOwner )
{
m_pOwner = pOwner;
m_pFollow = NULL;
m_pFollowHdr = NULL;
m_pOwnerHdr = NULL;
m_nFollowBoneSetupMask = 0;
}
void CBoneMergeCache::UpdateCache()
{
if ( !m_pOwner )
return;
CStudioHdr *pOwnerHdr = m_pOwner->GetModelPtr();
if ( !pOwnerHdr )
return;
C_BaseAnimating *pTestFollow = m_pOwner->FindFollowedEntity();
CStudioHdr *pTestHdr = (pTestFollow ? pTestFollow->GetModelPtr() : NULL);
if ( pTestFollow != m_pFollow || pTestHdr != m_pFollowHdr || pOwnerHdr != m_pOwnerHdr )
{
m_MergedBones.Purge();
m_BoneMergeBits.Purge();
// Update the cache.
if ( pTestFollow && pTestHdr && pOwnerHdr )
{
m_pFollow = pTestFollow;
m_pFollowHdr = pTestHdr;
m_pOwnerHdr = pOwnerHdr;
m_BoneMergeBits.SetSize( pOwnerHdr->numbones() / 8 + 1 );
memset( m_BoneMergeBits.Base(), 0, m_BoneMergeBits.Count() );
mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 );
m_nFollowBoneSetupMask = BONE_USED_BY_BONE_MERGE;
for ( int i = 0; i < m_pOwnerHdr->numbones(); i++ )
{
int parentBoneIndex = Studio_BoneIndexByName( m_pFollowHdr, pOwnerBones[i].pszName() );
if ( parentBoneIndex < 0 )
continue;
// Add a merged bone here.
CMergedBone mergedBone;
mergedBone.m_iMyBone = i;
mergedBone.m_iParentBone = parentBoneIndex;
m_MergedBones.AddToTail( mergedBone );
m_BoneMergeBits[i>>3] |= ( 1 << ( i & 7 ) );
if ( ( m_pFollowHdr->pBone( parentBoneIndex )->flags & BONE_USED_BY_BONE_MERGE ) == 0 )
{
m_nFollowBoneSetupMask = BONE_USED_BY_ANYTHING;
Warning("Performance warning: Mark bone '%s' in model '%s' as being used by bone merge in the .qc!\n",
m_pFollowHdr->pBone( parentBoneIndex )->pszName(), m_pFollowHdr->pszName() );
}
}
// No merged bones found? Slam the mask to 0
if ( !m_MergedBones.Count() )
{
m_nFollowBoneSetupMask = 0;
}
}
else
{
m_pFollow = NULL;
m_pFollowHdr = NULL;
m_pOwnerHdr = NULL;
m_nFollowBoneSetupMask = 0;
}
}
}
void CBoneMergeCache::MergeMatchingBones( int boneMask )
{
UpdateCache();
// If this is set, then all the other cache data is set.
if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
return;
// Have the entity we're following setup its bones.
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
// Now copy the bone matrices.
for ( int i=0; i < m_MergedBones.Count(); i++ )
{
int iOwnerBone = m_MergedBones[i].m_iMyBone;
int iParentBone = m_MergedBones[i].m_iParentBone;
// Only update bones reference by the bone mask.
if ( !( m_pOwnerHdr->pBone( iOwnerBone )->flags & boneMask ) )
continue;
MatrixCopy( m_pFollow->GetBone( iParentBone ), m_pOwner->GetBoneForWrite( iOwnerBone ) );
}
}
bool CBoneMergeCache::GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles )
{
UpdateCache();
// If this is set, then all the other cache data is set.
if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
return false;
// We want the abs origin such that if we put the entity there, the first merged bone
// will be aligned. This way the entity will be culled in the correct position.
//
// ie: mEntity * mBoneLocal = mFollowBone
// so: mEntity = mFollowBone * Inverse( mBoneLocal )
//
// Note: the code below doesn't take animation into account. If the attached entity animates
// all over the place, then this won't get the right results.
// Get mFollowBone.
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
const matrix3x4_t &mFollowBone = m_pFollow->GetBone( m_MergedBones[0].m_iParentBone );
// Get Inverse( mBoneLocal )
matrix3x4_t mBoneLocal, mBoneLocalInv;
SetupSingleBoneMatrix( m_pOwnerHdr, m_pOwner->GetSequence(), 0, m_MergedBones[0].m_iMyBone, mBoneLocal );
MatrixInvert( mBoneLocal, mBoneLocalInv );
// Now calculate mEntity = mFollowBone * Inverse( mBoneLocal )
matrix3x4_t mEntity;
ConcatTransforms( mFollowBone, mBoneLocalInv, mEntity );
MatrixAngles( mEntity, *pAbsAngles, *pAbsOrigin );
return true;
}

79
cl_dll/bone_merge_cache.h Normal file
View File

@ -0,0 +1,79 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BONE_MERGE_CACHE_H
#define BONE_MERGE_CACHE_H
#ifdef _WIN32
#pragma once
#endif
class C_BaseAnimating;
class CStudioHdr;
#include "vector.h"
class CBoneMergeCache
{
public:
CBoneMergeCache();
void Init( C_BaseAnimating *pOwner );
// Updates the lookups that let it merge bones quickly.
void UpdateCache();
// This copies the transform from all bones in the followed entity that have
// names that match our bones.
void MergeMatchingBones( int boneMask );
// Returns true if the specified bone is one that gets merged in MergeMatchingBones.
int CBoneMergeCache::IsBoneMerged( int iBone ) const;
// Gets the origin for the first merge bone on the parent.
bool GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles );
private:
// This is the entity that we're keeping the cache updated for.
C_BaseAnimating *m_pOwner;
// All the cache data is based off these. When they change, the cache data is regenerated.
// These are either all valid pointers or all NULL.
C_BaseAnimating *m_pFollow;
CStudioHdr *m_pFollowHdr;
CStudioHdr *m_pOwnerHdr;
// This is the mask we need to use to set up bones on the followed entity to do the bone merge
int m_nFollowBoneSetupMask;
// Cache data.
class CMergedBone
{
public:
unsigned short m_iMyBone;
unsigned short m_iParentBone;
};
CUtlVector<CMergedBone> m_MergedBones;
CUtlVector<unsigned char> m_BoneMergeBits; // One bit for each bone. The bit is set if the bone gets merged.
};
inline int CBoneMergeCache::IsBoneMerged( int iBone ) const
{
if ( m_pOwnerHdr )
return m_BoneMergeBits[iBone >> 3] & ( 1 << ( iBone & 7 ) );
else
return 0;
}
#endif // BONE_MERGE_CACHE_H

View File

@ -0,0 +1,169 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if 0
class C_AI_BaseHumanoid : public C_AI_BaseNPC
{
public:
DECLARE_CLASS( C_AI_BaseHumanoid, C_AI_BaseNPC );
DECLARE_CLIENTCLASS();
C_AI_BaseHumanoid();
// model specific
virtual bool Interpolate( float currentTime );
virtual void StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask );
float m_recanimtime[3];
AnimationLayer_t m_Layer[4][3];
};
C_AI_BaseHumanoid::C_AI_BaseHumanoid()
{
memset(m_recanimtime, 0, sizeof(m_recanimtime));
memset(m_Layer, 0, sizeof(m_Layer));
}
BEGIN_RECV_TABLE_NOBASE(AnimationLayer_t, DT_Animationlayer)
RecvPropInt(RECVINFO_NAME(nSequence,sequence)),
RecvPropFloat(RECVINFO_NAME(flCycle,cycle)),
RecvPropFloat(RECVINFO_NAME(flPlaybackrate,playbackrate)),
RecvPropFloat(RECVINFO_NAME(flWeight,weight))
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT(C_AI_BaseHumanoid, DT_BaseHumanoid, CAI_BaseHumanoid)
/*
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[0][2],m_Layer0),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[1][2],m_Layer1),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[2][2],m_Layer2),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[3][2],m_Layer3),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
*/
RecvPropInt(RECVINFO_NAME(m_Layer[0][2].nSequence,sequence0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flCycle,cycle0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flPlaybackrate,playbackrate0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flWeight,weight0)),
RecvPropInt(RECVINFO_NAME(m_Layer[1][2].nSequence,sequence1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flCycle,cycle1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flPlaybackrate,playbackrate1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flWeight,weight1)),
RecvPropInt(RECVINFO_NAME(m_Layer[2][2].nSequence,sequence2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flCycle,cycle2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flPlaybackrate,playbackrate2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flWeight,weight2)),
RecvPropInt(RECVINFO_NAME(m_Layer[3][2].nSequence,sequence3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flCycle,cycle3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flPlaybackrate,playbackrate3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flWeight,weight3))
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_AI_BaseHumanoid::StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask )
{
VPROF( "C_AI_BaseHumanoid::StandardBlendingRules" );
BaseClass::StandardBlendingRules( pStudioHdr, pos, q, currentTime, boneMask );
if ( !hdr )
{
return;
}
#if 0
float poseparam[MAXSTUDIOPOSEPARAM];
if ( GetSequence() >= hdr->numseq )
{
SetSequence( 0 );
}
// interpolate pose parameters
for (int i = 0; i < hdr->numposeparameters; i++)
{
poseparam[ i ] = m_flPoseParameter[i];
}
// build root animation
float fCycle = GetCycle();
CalcPose( hdr, NULL, pos, q, GetSequence(), fCycle, poseparam );
// debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, "%30s %6.2f : %6.2f", hdr->pSeqdesc( GetSequence() )->pszLabel( ), fCycle, 1.0 );
MaintainSequenceTransitions( hdr, fCycle, poseparam, pos, q, boneMask );
#if 1
for (i = 0; i < 4; i++)
{
if (m_Layer[i][2].nSequence != m_Layer[i][1].nSequence)
{
if (m_Layer[i][2].flWeight > 0.5) m_Layer[i][1].flWeight = 1.0; else m_Layer[i][1].flWeight = 0;
}
}
#endif
#if 1
for (i = 0; i < 4; i++)
{
Vector pos2[MAXSTUDIOBONES];
Quaternion q2[MAXSTUDIOBONES];
float fWeight = m_Layer[i][1].flWeight * (1 - dadt) + m_Layer[i][2].flWeight * dadt;
/*
debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -i - 1, 0,
"%2d %6.2f %6.2f : %2d %6.2f %6.2f : %2d %6.2f %6.2f",
m_Layer[i][0].nSequence, m_Layer[i][0].flCycle, m_Layer[i][0].flWeight,
m_Layer[i][1].nSequence, m_Layer[i][1].flCycle, m_Layer[i][1].flWeight,
m_Layer[i][2].nSequence, m_Layer[i][2].flCycle, m_Layer[i][2].flWeight );
*/
if (fWeight > 0)
{
mstudioseqdesc_t *pseqdesc = hdr->pSeqdesc( m_Layer[i][2].nSequence );
float fCycle = m_Layer[i][2].flCycle;
// UNDONE: Do IK here.
CalcPose( hdr, NULL, pos2, q2, m_Layer[i][2].nSequence, fCycle, poseparam );
if (fWeight > 1)
fWeight = 1;
SlerpBones( hdr, q, pos, pseqdesc, q2, pos2, fWeight );
engine->Con_NPrintf( 10 + i, "%30s %6.2f : %6.2f", pseqdesc->pszLabel(), fCycle, fWeight );
}
else
{
engine->Con_NPrintf( 10 + i, "%30s %6.2f : %6.2f", " ", 0, 0 );
}
}
#endif
CIKContext auto_ik;
auto_ik.Init( hdr, GetRenderAngles(), GetRenderOrigin(), gpGlobals->curtime );
CalcAutoplaySequences( hdr, &auto_ik, pos, q, poseparam, boneMask, currentTime );
float controllers[MAXSTUDIOBONECTRLS];
GetBoneControllers(controllers);
CalcBoneAdj( hdr, pos, q, controllers );
#endif
}
#endif

116
cl_dll/c_ai_basenpc.cpp Normal file
View File

@ -0,0 +1,116 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_AI_BaseNPC.h"
#include "engine/IVDebugOverlay.h"
#ifdef HL2_DLL
#include "c_basehlplayer.h"
#endif
#include "death_pose.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC )
RecvPropInt( RECVINFO( m_lifeState ) ),
RecvPropBool( RECVINFO( m_bPerformAvoidance ) ),
RecvPropBool( RECVINFO( m_bIsMoving ) ),
RecvPropBool( RECVINFO( m_bFadeCorpse ) ),
RecvPropInt( RECVINFO ( m_iDeathPose) ),
RecvPropInt( RECVINFO( m_iDeathFrame) ),
RecvPropInt( RECVINFO( m_iSpeedModRadius ) ),
RecvPropInt( RECVINFO( m_iSpeedModSpeed ) ),
RecvPropInt( RECVINFO( m_bSpeedModActive ) ),
RecvPropBool( RECVINFO( m_bImportanRagdoll ) ),
END_RECV_TABLE()
extern ConVar cl_npc_speedmod_intime;
bool NPC_IsImportantNPC( C_BaseAnimating *pAnimating )
{
C_AI_BaseNPC *pBaseNPC = dynamic_cast < C_AI_BaseNPC* > ( pAnimating );
if ( pBaseNPC == NULL )
return false;
return pBaseNPC->ImportantRagdoll();
}
C_AI_BaseNPC::C_AI_BaseNPC()
{
}
//-----------------------------------------------------------------------------
// Makes ragdolls ignore npcclip brushes
//-----------------------------------------------------------------------------
unsigned int C_AI_BaseNPC::PhysicsSolidMaskForEntity( void ) const
{
// This allows ragdolls to move through npcclip brushes
if ( !IsRagdoll() )
{
return MASK_NPCSOLID;
}
return MASK_SOLID;
}
void C_AI_BaseNPC::ClientThink( void )
{
BaseClass::ClientThink();
#ifdef HL2_DLL
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( ShouldModifyPlayerSpeed() == true )
{
if ( pPlayer )
{
float flDist = (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr();
if ( flDist <= GetSpeedModifyRadius() )
{
if ( pPlayer->m_hClosestNPC )
{
if ( pPlayer->m_hClosestNPC != this )
{
float flDistOther = (pPlayer->m_hClosestNPC->GetAbsOrigin() - pPlayer->GetAbsOrigin()).Length();
//If I'm closer than the other NPC then replace it with myself.
if ( flDist < flDistOther )
{
pPlayer->m_hClosestNPC = this;
pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
}
}
}
else
{
pPlayer->m_hClosestNPC = this;
pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
}
}
}
}
#endif // HL2_DLL
}
void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( ShouldModifyPlayerSpeed() == true )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
void C_AI_BaseNPC::GetRagdollCurSequence( matrix3x4_t *curBones, float flTime )
{
GetRagdollCurSequenceWithDeathPose( this, curBones, flTime, m_iDeathPose, m_iDeathFrame );
}

60
cl_dll/c_ai_basenpc.h Normal file
View File

@ -0,0 +1,60 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_AI_BASENPC_H
#define C_AI_BASENPC_H
#ifdef _WIN32
#pragma once
#endif
#include "c_basecombatcharacter.h"
// NOTE: MOved all controller code into c_basestudiomodel
class C_AI_BaseNPC : public C_BaseCombatCharacter
{
DECLARE_CLASS( C_AI_BaseNPC, C_BaseCombatCharacter );
public:
DECLARE_CLIENTCLASS();
C_AI_BaseNPC();
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
virtual bool IsNPC( void ) { return true; }
bool IsMoving( void ){ return m_bIsMoving; }
bool ShouldAvoidObstacle( void ){ return m_bPerformAvoidance; }
virtual bool AddRagdollToFadeQueue( void ) { return m_bFadeCorpse; }
virtual void GetRagdollCurSequence( matrix3x4_t *curBones, float flTime );
int GetDeathPose( void ) { return m_iDeathPose; }
bool ShouldModifyPlayerSpeed( void ) { return m_bSpeedModActive; }
int GetSpeedModifyRadius( void ) { return m_iSpeedModRadius; }
int GetSpeedModifySpeed( void ) { return m_iSpeedModSpeed; }
void ClientThink( void );
void OnDataChanged( DataUpdateType_t type );
bool ImportantRagdoll( void ) { return m_bImportanRagdoll; }
private:
C_AI_BaseNPC( const C_AI_BaseNPC & ); // not defined, not accessible
bool m_bPerformAvoidance;
bool m_bIsMoving;
bool m_bFadeCorpse;
int m_iDeathPose;
int m_iDeathFrame;
int m_iSpeedModRadius;
int m_iSpeedModSpeed;
bool m_bSpeedModActive;
bool m_bImportanRagdoll;
};
#endif // C_AI_BASENPC_H

5071
cl_dll/c_baseanimating.cpp Normal file

File diff suppressed because it is too large Load Diff

647
cl_dll/c_baseanimating.h Normal file
View File

@ -0,0 +1,647 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASEANIMATING_H
#define C_BASEANIMATING_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "studio.h"
#include "UtlVector.h"
#include "ragdoll.h"
#include "mouthinfo.h"
// Shared activities
#include "ai_activity.h"
#include "animationlayer.h"
#include "sequence_transitioner.h"
#include "bone_accessor.h"
#include "bone_merge_cache.h"
#include "ragdoll_shared.h"
#define LIPSYNC_POSEPARAM_NAME "mouth"
#define NUM_HITBOX_FIRES 10
/*
class C_BaseClientShader
{
virtual void RenderMaterial( C_BaseEntity *pEntity, int count, const vec4_t *verts, const vec4_t *normals, const vec2_t *texcoords, vec4_t *lightvalues );
};
*/
class IRagdoll;
class CIKContext;
class CIKState;
class ConVar;
class C_RopeKeyframe;
class CBoneBitList;
class CBoneList;
class KeyValues;
FORWARD_DECLARE_HANDLE( memhandle_t );
extern ConVar vcollide_wireframe;
struct RagdollInfo_t
{
bool m_bActive;
float m_flSaveTime;
int m_nNumBones;
Vector m_rgBonePos[MAXSTUDIOBONES];
Quaternion m_rgBoneQuaternion[MAXSTUDIOBONES];
};
class CAttachmentData
{
public:
Vector m_vOrigin;
QAngle m_angRotation;
};
typedef unsigned int ClientSideAnimationListHandle_t;
#define INVALID_CLIENTSIDEANIMATION_LIST_HANDLE (ClientSideAnimationListHandle_t)~0
class C_BaseAnimating : public C_BaseEntity
{
public:
DECLARE_CLASS( C_BaseAnimating, C_BaseEntity );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
enum
{
NUM_POSEPAREMETERS = 24,
NUM_BONECTRLS = 4
};
C_BaseAnimating();
~C_BaseAnimating();
virtual C_BaseAnimating* GetBaseAnimating() { return this; }
bool UsesFrameBufferTexture( void );
virtual bool Interpolate( float currentTime );
virtual void Simulate();
virtual void Release();
float GetAnimTimeInterval( void ) const;
virtual unsigned char GetClientSideFade( void );
// Get bone controller values.
virtual void GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS]);
virtual float SetBoneController ( int iController, float flValue );
int GetNumFlexControllers( void );
const char *GetFlexDescFacs( int iFlexDesc );
const char *GetFlexControllerName( int iFlexController );
const char *GetFlexControllerType( int iFlexController );
virtual void GetAimEntOrigin( IClientEntity *pAttachedTo, Vector *pAbsOrigin, QAngle *pAbsAngles );
// Computes a box that surrounds all hitboxes
bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Gets the hitbox-to-world transforms, returns false if there was a problem
bool HitboxToWorldTransforms( matrix3x4_t *pHitboxToWorld[MAXSTUDIOBONES] );
// base model functionality
float ClampCycle( float cycle, bool isLooping );
virtual void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] );
virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform );
virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax );
// model specific
virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime );
virtual void UpdateIKLocks( float currentTime );
virtual void CalculateIKLocks( float currentTime );
virtual int DrawModel( int flags );
virtual int InternalDrawModel( int flags );
//
virtual CMouthInfo *GetMouth();
virtual void ControlMouth( CStudioHdr *pStudioHdr );
// override in sub-classes
virtual void DoAnimationEvents( CStudioHdr *pStudio );
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
// Parses and distributes muzzle flash events
virtual bool DispatchMuzzleEffect( const char *options, bool isFirstPerson );
// virtual void AllocateMaterials( void );
// virtual void FreeMaterials( void );
virtual CStudioHdr *OnNewModel( void );
CStudioHdr *GetModelPtr() const;
virtual void SetPredictable( bool state );
// C_BaseClientShader **p_ClientShaders;
virtual void StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask );
void UnragdollBlend( CStudioHdr *hdr, Vector pos[], Quaternion q[], float currentTime );
void MaintainSequenceTransitions( CStudioHdr *hdr, float flCycle, float flPoseParameter[], Vector pos[], Quaternion q[], int boneMask );
virtual void AccumulateLayers( CStudioHdr *hdr, Vector pos[], Quaternion q[], float poseparam[], float currentTime, int boneMask );
// Attachments
int LookupAttachment( const char *pAttachmentName );
int LookupRandomAttachment( const char *pAttachmentNameSubstring );
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
inline int LookupPoseParameter( const char *szName ) { return LookupPoseParameter(GetModelPtr(), szName); }
float SetPoseParameter( CStudioHdr *pStudioHdr, const char *szName, float flValue );
inline float SetPoseParameter( const char *szName, float flValue ) { return SetPoseParameter( GetModelPtr(), szName, flValue ); }
float SetPoseParameter( CStudioHdr *pStudioHdr, int iParameter, float flValue );
inline float SetPoseParameter( int iParameter, float flValue ) { return SetPoseParameter( GetModelPtr(), iParameter, flValue ); }
float GetPoseParameter( int iPoseParameter );
bool GetPoseParameterRange( int iPoseParameter, float &minValue, float &maxValue );
int LookupBone( const char *szName );
void GetBonePosition( int iBone, Vector &origin, QAngle &angles );
void GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld );
//bool solveIK(float a, float b, const Vector &Foot, const Vector &Knee1, Vector &Knee2);
//void DebugIK( mstudioikchain_t *pikchain );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void AddEntity( void );
// This can be used to force client side animation to be on. Only use if you know what you're doing!
// Normally, the server entity should set this.
void ForceClientSideAnimationOn();
void AddToClientSideAnimationList();
void RemoveFromClientSideAnimationList();
virtual bool IsSelfAnimating();
virtual void ResetLatched();
// implements these so ragdolls can handle frustum culling & leaf visibility
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual const Vector& GetRenderOrigin( void );
virtual const QAngle& GetRenderAngles( void );
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
// Attachments.
bool GetAttachment( int number, Vector &origin, QAngle &angles );
virtual bool GetAttachment( int number, matrix3x4_t &matrix );
// Returns the attachment in local space
bool GetAttachmentLocal( int iAttachment, matrix3x4_t &attachmentToLocal );
bool GetAttachmentLocal( int iAttachment, Vector &origin, QAngle &angles );
// Should this object cast render-to-texture shadows?
virtual ShadowType_t ShadowCastType();
// Should we collide?
virtual CollideType_t ShouldCollide( );
virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
// returns true if we're currently being ragdolled
bool IsRagdoll() const;
virtual C_BaseAnimating * BecomeRagdollOnClient( bool bCopyEntity = true ); // returns ragdoll-owning entity
void IgniteRagdoll( C_BaseAnimating *pSource );
void TransferDissolveFrom( C_BaseAnimating *pSource );
virtual void SaveRagdollInfo( int numbones, const matrix3x4_t &cameraTransform, CBoneAccessor &pBoneToWorld );
virtual bool RetrieveRagdollInfo( Vector *pos, Quaternion *q );
virtual void Clear( void );
void ClearRagdoll();
void CreateUnragdollInfo( C_BaseAnimating *pRagdoll );
// For shadows rendering the correct body + sequence...
virtual int GetBody() { return m_nBody; }
virtual int GetSkin() { return m_nSkin; }
bool IsOnFire() { return ( (GetFlags() & FL_ONFIRE) != 0 ); }
inline float GetPlaybackRate();
inline void SetPlaybackRate( float rate );
void SetModelWidthScale( float scale );
float GetModelWidthScale() const;
int GetSequence();
void SetSequence(int nSequence);
inline void ResetSequence(int nSequence);
float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence );
inline float GetSequenceGroundSpeed( int iSequence ) { return GetSequenceGroundSpeed(GetModelPtr(), iSequence); }
bool IsSequenceLooping( CStudioHdr *pStudioHdr, int iSequence );
inline bool IsSequenceLooping( int iSequence ) { return IsSequenceLooping(GetModelPtr(),iSequence); }
float GetSequenceMoveDist( CStudioHdr *pStudioHdr, int iSequence );
void GetSequenceLinearMotion( int iSequence, Vector *pVec );
void GetBlendedLinearVelocity( Vector *pVec );
int LookupSequence ( const char *label );
int LookupActivity( const char *label );
char const *GetSequenceName( int iSequence );
char const *GetSequenceActivityName( int iSequence );
Activity GetSequenceActivity( int iSequence );
virtual void StudioFrameAdvance(); // advance animation frame to some time in the future
// Clientside animation
virtual float FrameAdvance( float flInterval = 0.0f );
virtual float GetSequenceCycleRate( CStudioHdr *pStudioHdr, int iSequence );
virtual void UpdateClientSideAnimation();
void ClientSideAnimationChanged();
virtual unsigned int ComputeClientSideAnimationFlags();
void SetCycle( float flCycle );
float GetCycle() const;
void SetBodygroup( int iGroup, int iValue );
int GetBodygroup( int iGroup );
const char *GetBodygroupName( int iGroup );
int FindBodygroupByName( const char *name );
int GetBodygroupCount( int iGroup );
int GetNumBodyGroups( void );
class CBoneCache *GetBoneCache( CStudioHdr *pStudioHdr );
void SetHitboxSet( int setnum );
void SetHitboxSetByName( const char *setname );
int GetHitboxSet( void );
char const *GetHitboxSetName( void );
int GetHitboxSetCount( void );
void DrawClientHitboxes( float duration = 0.0f, bool monocolor = false );
C_BaseAnimating* FindFollowedEntity();
virtual bool IsActivityFinished( void ) { return m_bSequenceFinished; }
inline bool IsSequenceFinished( void );
// All view model attachments origins are stretched so you can place entities at them and
// they will match up with where the attachment winds up being drawn on the view model, since
// the view models are drawn with a different FOV.
//
// If you're drawing something inside of a view model's DrawModel() function, then you want the
// original attachment origin instead of the adjusted one. To get that, call this on the
// adjusted attachment origin.
virtual void UncorrectViewModelAttachment( Vector &vOrigin ) {}
// Call this if SetupBones() has already been called this frame but you need to move the
// entity and rerender.
void InvalidateBoneCache();
bool IsBoneCacheValid() const; // Returns true if the bone cache is considered good for this frame.
void GetCachedBoneMatrix( int boneIndex, matrix3x4_t &out );
// Wrappers for CBoneAccessor.
const matrix3x4_t& GetBone( int iBone ) const;
matrix3x4_t& GetBoneForWrite( int iBone );
// Used for debugging. Will produce asserts if someone tries to setup bones or
// attachments before it's allowed.
static void AllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels );
static void PushAllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels );
static void PopBoneAccess( void );
// Invalidate bone caches so all SetupBones() calls force bone transforms to be regenerated.
static void InvalidateBoneCaches();
// Purpose: My physics object has been updated, react or extract data
virtual void VPhysicsUpdate( IPhysicsObject *pPhysics );
void DisableMuzzleFlash(); // Turn off the muzzle flash (ie: signal that we handled the server's event).
virtual void DoMuzzleFlash(); // Force a muzzle flash event. Note: this only QUEUES an event, so
// ProcessMuzzleFlashEvent will get called later.
bool ShouldMuzzleFlash() const; // Is the muzzle flash event on?
// This is called to do the actual muzzle flash effect.
virtual void ProcessMuzzleFlashEvent();
// Update client side animations
static void UpdateClientSideAnimations();
void InitRopes();
// Sometimes the server wants to update the client's cycle to get the two to run in sync (for proper hit detection)
virtual void SetServerIntendedCycle( float intended ) { intended; }
virtual float GetServerIntendedCycle( void ) { return -1.0f; }
// For prediction
int SelectWeightedSequence ( int activity );
void ResetSequenceInfo( void );
float SequenceDuration( void );
float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence );
inline float SequenceDuration( int iSequence ) { return SequenceDuration(GetModelPtr(), iSequence); }
int FindTransitionSequence( int iCurrentSequence, int iGoalSequence, int *piDir );
virtual void GetRagdollPreSequence( matrix3x4_t *preBones, float flTime );
virtual void GetRagdollCurSequence( matrix3x4_t *curBones, float flTime );
void RagdollMoved( void );
virtual void GetToolRecordingState( KeyValues *msg );
virtual void CleanupToolRecordingState( KeyValues *msg );
void RecordBones( CStudioHdr *hdr, KeyValues *kvBones );
protected:
// View models scale their attachment positions to account for FOV. To get the unmodified
// attachment position (like if you're rendering something else during the view model's DrawModel call),
// use TransformViewModelAttachmentToWorld.
virtual void FormatViewModelAttachment( int nAttachment, Vector &vecOrigin, QAngle &angle ) {}
// View models say yes to this.
virtual bool IsViewModel() const;
bool IsBoneAccessAllowed() const;
CMouthInfo& MouthInfo();
// Allow studio models to tell C_BaseEntity what their m_nBody value is
virtual int GetStudioBody( void ) { return m_nBody; }
private:
CBoneList* RecordBones( CStudioHdr *hdr );
virtual bool CalcAttachments();
bool PutAttachment( int number, const Vector &origin, const QAngle &angles );
void TermRopes();
void UpdateRelevantInterpolatedVars();
void AddBaseAnimatingInterpolatedVars();
void RemoveBaseAnimatingInterpolatedVars();
public:
CRagdoll *m_pRagdoll;
// Texture group to use
int m_nSkin;
// Object bodygroup
int m_nBody;
// Hitbox set to use (default 0)
int m_nHitboxSet;
CSequenceTransitioner m_SequenceTransitioner;
protected:
CIKContext *m_pIk;
int m_iEyeAttachment;
// Animation playback framerate
float m_flPlaybackRate;
// Decomposed ragdoll info
bool m_bStoreRagdollInfo;
RagdollInfo_t *m_pRagdollInfo;
// Is bone cache valid
// bone transformation matrix
unsigned long m_iMostRecentModelBoneCounter;
int m_iPrevBoneMask;
int m_iAccumulatedBoneMask;
CBoneAccessor m_BoneAccessor;
ClientSideAnimationListHandle_t m_ClientSideAnimationListHandle;
// Client-side animation
bool m_bClientSideFrameReset;
protected:
float m_fadeMinDist;
float m_fadeMaxDist;
float m_flFadeScale;
private:
float m_flGroundSpeed; // computed linear movement rate for current sequence
float m_flLastEventCheck; // cycle index of when events were last checked
bool m_bSequenceFinished;// flag set when StudioAdvanceFrame moves across a frame boundry
Vector m_vecForce;
int m_nForceBone;
// Mouth lipsync/envelope following values
CMouthInfo m_mouth;
CNetworkVar( float, m_flModelWidthScale );
// Animation blending factors
float m_flPoseParameter[MAXSTUDIOPOSEPARAM];
CInterpolatedVarArray< float, MAXSTUDIOPOSEPARAM > m_iv_flPoseParameter;
int m_nPrevSequence;
int m_nRestoreSequence;
// Ropes that got spawned when the model was created.
CUtlLinkedList<C_RopeKeyframe*,unsigned short> m_Ropes;
// event processing info
float m_flPrevEventCycle;
int m_nEventSequence;
float m_flEncodedController[MAXSTUDIOBONECTRLS];
CInterpolatedVarArray< float, MAXSTUDIOBONECTRLS > m_iv_flEncodedController;
// Clientside animation
bool m_bClientSideAnimation;
bool m_bLastClientSideFrameReset;
int m_nNewSequenceParity;
int m_nResetEventsParity;
int m_nPrevNewSequenceParity;
int m_nPrevResetEventsParity;
bool m_builtRagdoll;
Vector m_vecPreRagdollMins;
Vector m_vecPreRagdollMaxs;
// Current animation sequence
int m_nSequence;
// Current cycle location from server
float m_flCycle;
CInterpolatedVar< float > m_iv_flCycle;
float m_flOldCycle;
int m_nOldSequence;
CBoneMergeCache *m_pBoneMergeCache; // This caches the strcmp lookups that it has to do
// when merg
CUtlVector< matrix3x4_t > m_CachedBoneData; // never access this directly. Use m_BoneAccessor.
memhandle_t m_hitboxBoneCacheHandle;
// Calculated attachment points
CUtlVector<CAttachmentData> m_Attachments;
void SetupBones_AttachmentHelper( CStudioHdr *pStudioHdr );
EHANDLE m_hLightingOrigin;
EHANDLE m_hLightingOriginRelative;
// These are compared against each other to determine if the entity should muzzle flash.
CNetworkVar( unsigned char, m_nMuzzleFlashParity );
unsigned char m_nOldMuzzleFlashParity;
private:
mutable CStudioHdr *m_pStudioHdr;
};
enum
{
RAGDOLL_FRICTION_OFF = -2,
RAGDOLL_FRICTION_NONE,
RAGDOLL_FRICTION_IN,
RAGDOLL_FRICTION_HOLD,
RAGDOLL_FRICTION_OUT,
};
class C_ClientRagdoll : public C_BaseAnimating, public IPVSNotify
{
public:
C_ClientRagdoll( bool bRestoring = true );
DECLARE_CLASS( C_ClientRagdoll, C_BaseAnimating );
DECLARE_DATADESC();
// inherited from IPVSNotify
virtual void OnPVSStatusChanged( bool bInPVS );
virtual void Release( void );
virtual void SetupWeights( void );
virtual void ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName );
void ClientThink( void );
void ReleaseRagdoll( void ) { m_bReleaseRagdoll = true; }
bool ShouldSavePhysics( void ) { return true; }
virtual void OnSave();
virtual void OnRestore();
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_SAVE_NON_NETWORKABLE; }
virtual IPVSNotify* GetPVSNotifyInterface() { return this; }
void HandleAnimatedFriction( void );
virtual void SUB_Remove( void );
void FadeOut( void );
bool m_bFadeOut;
bool m_bImportant;
float m_flEffectTime;
private:
int m_iCurrentFriction;
int m_iMinFriction;
int m_iMaxFriction;
float m_flFrictionModTime;
float m_flFrictionTime;
int m_iFrictionAnimState;
bool m_bReleaseRagdoll;
bool m_bFadingOut;
float m_flScaleEnd[NUM_HITBOX_FIRES];
float m_flScaleTimeStart[NUM_HITBOX_FIRES];
float m_flScaleTimeEnd[NUM_HITBOX_FIRES];
};
//-----------------------------------------------------------------------------
// Purpose: Serves the 90% case of calling SetSequence / ResetSequenceInfo.
//-----------------------------------------------------------------------------
inline void C_BaseAnimating::ResetSequence(int nSequence)
{
SetSequence( nSequence );
ResetSequenceInfo();
}
inline float C_BaseAnimating::GetPlaybackRate()
{
return m_flPlaybackRate;
}
inline void C_BaseAnimating::SetPlaybackRate( float rate )
{
m_flPlaybackRate = rate;
}
inline const matrix3x4_t& C_BaseAnimating::GetBone( int iBone ) const
{
return m_BoneAccessor.GetBone( iBone );
}
inline matrix3x4_t& C_BaseAnimating::GetBoneForWrite( int iBone )
{
return m_BoneAccessor.GetBoneForWrite( iBone );
}
inline bool C_BaseAnimating::ShouldMuzzleFlash() const
{
return m_nOldMuzzleFlashParity != m_nMuzzleFlashParity;
}
inline float C_BaseAnimating::GetCycle() const
{
return m_flCycle;
}
//-----------------------------------------------------------------------------
// Sequence access
//-----------------------------------------------------------------------------
inline int C_BaseAnimating::GetSequence()
{
return m_nSequence;
}
inline bool C_BaseAnimating::IsSequenceFinished( void )
{
return m_bSequenceFinished;
}
inline float C_BaseAnimating::SequenceDuration( void )
{
return SequenceDuration( GetSequence() );
}
//-----------------------------------------------------------------------------
// Mouth
//-----------------------------------------------------------------------------
inline CMouthInfo& C_BaseAnimating::MouthInfo()
{
return m_mouth;
}
// FIXME: move these to somewhere that makes sense
void GetColumn( matrix3x4_t& src, int column, Vector &dest );
void SetColumn( Vector &src, int column, matrix3x4_t& dest );
EXTERN_RECV_TABLE(DT_BaseAnimating);
extern void DevMsgRT( char const* pMsg, ... );
#endif // C_BASEANIMATING_H

View File

@ -0,0 +1,521 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseanimatingoverlay.h"
#include "bone_setup.h"
#include "tier0/vprof.h"
#include "engine/IVDebugOverlay.h"
#include "datacache/imdlcache.h"
#include "eventlist.h"
#include "dt_utlvector_recv.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar r_sequence_debug;
C_BaseAnimatingOverlay::C_BaseAnimatingOverlay()
{
// FIXME: where does this initialization go now?
//for ( int i=0; i < MAX_OVERLAYS; i++ )
//{
// memset( &m_Layer[i], 0, sizeof(m_Layer[0]) );
// m_Layer[i].m_nOrder = MAX_OVERLAYS;
//}
// FIXME: where does this initialization go now?
// AddVar( m_Layer, &m_iv_AnimOverlay, LATCH_ANIMATION_VAR );
}
#undef CBaseAnimatingOverlay
BEGIN_RECV_TABLE_NOBASE(CAnimationLayer, DT_Animationlayer)
RecvPropInt( RECVINFO_NAME(m_nSequence, m_nSequence)),
RecvPropFloat( RECVINFO_NAME(m_flCycle, m_flCycle)),
RecvPropFloat( RECVINFO_NAME(m_flPrevCycle, m_flPrevCycle)),
RecvPropFloat( RECVINFO_NAME(m_flWeight, m_flWeight)),
RecvPropInt( RECVINFO_NAME(m_nOrder, m_nOrder))
END_RECV_TABLE()
const char *s_m_iv_AnimOverlayNames[C_BaseAnimatingOverlay::MAX_OVERLAYS] =
{
"C_BaseAnimatingOverlay::m_iv_AnimOverlay00",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay01",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay02",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay03",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay04",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay05",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay06",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay07",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay08",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay09",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay10",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay11",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay12",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay13",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay14"
};
void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len )
{
C_BaseAnimatingOverlay *pEnt = (C_BaseAnimatingOverlay*)pStruct;
CUtlVector < C_AnimationLayer > *pVec = &pEnt->m_AnimOverlay;
CUtlVector< CInterpolatedVar< C_AnimationLayer > > *pVecIV = &pEnt->m_iv_AnimOverlay;
Assert( (char*)pVec - (char*)pEnt == offsetToUtlVector );
Assert( pVec->Count() == pVecIV->Count() );
Assert( pVec->Count() <= C_BaseAnimatingOverlay::MAX_OVERLAYS );
int diff = len - pVec->Count();
if ( diff == 0 )
return;
// remove all entries
for ( int i=0; i < pVec->Count(); i++ )
{
pEnt->RemoveVar( &pVec->Element( i ) );
}
// adjust vector sizes
if ( diff > 0 )
{
pVec->AddMultipleToTail( diff );
pVecIV->AddMultipleToTail( diff );
}
else
{
pVec->RemoveMultiple( len, -diff );
pVecIV->RemoveMultiple( len, -diff );
}
// Rebind all the variables in the ent's list.
for ( int i=0; i < len; i++ )
{
IInterpolatedVar *pWatcher = &pVecIV->Element( i );
pWatcher->SetDebugName( s_m_iv_AnimOverlayNames[i] );
pEnt->AddVar( &pVec->Element( i ), pWatcher, LATCH_ANIMATION_VAR, true );
}
// FIXME: need to set historical values of nOrder in pVecIV to MAX_OVERLAY
}
BEGIN_RECV_TABLE_NOBASE( C_BaseAnimatingOverlay, DT_OverlayVars )
RecvPropUtlVector(
RECVINFO_UTLVECTOR_SIZEFN( m_AnimOverlay, ResizeAnimationLayerCallback ),
C_BaseAnimatingOverlay::MAX_OVERLAYS,
RecvPropDataTable(NULL, 0, 0, &REFERENCE_RECV_TABLE( DT_Animationlayer ) ) )
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT( C_BaseAnimatingOverlay, DT_BaseAnimatingOverlay, CBaseAnimatingOverlay )
RecvPropDataTable( "overlay_vars", 0, 0, &REFERENCE_RECV_TABLE( DT_OverlayVars ) )
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseAnimatingOverlay )
/*
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flWeight, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flWeight, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flWeight, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flWeight, FIELD_FLOAT),
*/
END_PREDICTION_DATA()
C_AnimationLayer* C_BaseAnimatingOverlay::GetAnimOverlay( int i )
{
Assert( i >= 0 && i < MAX_OVERLAYS );
return &m_AnimOverlay[i];
}
void C_BaseAnimatingOverlay::SetNumAnimOverlays( int num )
{
if ( m_AnimOverlay.Count() < num )
{
m_AnimOverlay.AddMultipleToTail( num - m_AnimOverlay.Count() );
}
else if ( m_AnimOverlay.Count() > num )
{
m_AnimOverlay.RemoveMultiple( num, m_AnimOverlay.Count() - num );
}
}
int C_BaseAnimatingOverlay::GetNumAnimOverlays() const
{
return m_AnimOverlay.Count();
}
void C_BaseAnimatingOverlay::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
BaseClass::GetRenderBounds( theMins, theMaxs );
if ( !IsRagdoll() )
{
CStudioHdr *pStudioHdr = GetModelPtr();
if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
return;
int nSequences = pStudioHdr->GetNumSeq();
int i;
for (i = 0; i < m_AnimOverlay.Count(); i++)
{
if (m_AnimOverlay[i].m_flWeight > 0.0)
{
if ( m_AnimOverlay[i].m_nSequence >= nSequences )
{
continue;
}
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[i].m_nSequence );
VectorMin( seqdesc.bbmin, theMins, theMins );
VectorMax( seqdesc.bbmax, theMaxs, theMaxs );
}
}
}
}
void C_BaseAnimatingOverlay::CheckForLayerChanges( CStudioHdr *hdr, float currentTime )
{
CDisableRangeChecks disableRangeChecks;
// FIXME: damn, there has to be a better way than this.
int i;
for (i = 0; i < m_iv_AnimOverlay.Count(); i++)
{
CDisableRangeChecks disableRangeChecks;
int iHead, iPrev1, iPrev2;
m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 );
// fake up previous cycle values.
float t0;
C_AnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 );
// reset previous
float t1;
C_AnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 );
// reset previous previous
float t2;
C_AnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 );
if ( pHead && pPrev1 && pHead->m_nSequence != pPrev1->m_nSequence )
{
#if _DEBUG
if (Q_stristr( hdr->pszName(), r_sequence_debug.GetString()) != NULL)
{
DevMsgRT( "(%5.2f : %30s : %5.3f : %4.2f : %1d)\n", t0, hdr->pSeqdesc( pHead->m_nSequence ).pszLabel(), (float)pHead->m_flCycle, (float)pHead->m_flWeight, i );
DevMsgRT( "(%5.2f : %30s : %5.3f : %4.2f : %1d)\n", t1, hdr->pSeqdesc( pPrev1->m_nSequence ).pszLabel(), (float)pPrev1->m_flCycle, (float)pPrev1->m_flWeight, i );
if (pPrev2)
DevMsgRT( "(%5.2f : %30s : %5.3f : %4.2f : %1d)\n", t2, hdr->pSeqdesc( pPrev2->m_nSequence ).pszLabel(), (float)pPrev2->m_flCycle, (float)pPrev2->m_flWeight, i );
}
#endif
if (pPrev1)
{
pPrev1->m_nSequence = pHead->m_nSequence;
pPrev1->m_flCycle = pHead->m_flPrevCycle;
pPrev1->m_flWeight = pHead->m_flWeight;
}
if (pPrev2)
{
float num = 0;
if ( fabs( t0 - t1 ) > 0.001f )
num = (t2 - t1) / (t0 - t1);
pPrev2->m_nSequence = pHead->m_nSequence;
float flTemp;
if (IsSequenceLooping( hdr, pHead->m_nSequence ))
{
flTemp = LoopingLerp( num, (float)pHead->m_flPrevCycle, (float)pHead->m_flCycle );
}
else
{
flTemp = Lerp( num, (float)pHead->m_flPrevCycle, (float)pHead->m_flCycle );
}
pPrev2->m_flCycle = flTemp;
pPrev2->m_flWeight = pHead->m_flWeight;
}
/*
if (stricmp( r_seq_overlay_debug.GetString(), hdr->name ) == 0)
{
DevMsgRT( "(%30s %6.2f : %6.2f : %6.2f)\n", hdr->pSeqdesc( pHead->nSequence ).pszLabel(), (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle );
}
*/
m_iv_AnimOverlay[i].SetLooping( IsSequenceLooping( hdr, pHead->m_nSequence ) );
m_iv_AnimOverlay[i].Interpolate( currentTime );
// reset event indexes
m_flOverlayPrevEventCycle[i] = pHead->m_flPrevCycle - 0.01;
}
}
}
void C_BaseAnimatingOverlay::AccumulateLayers( CStudioHdr *hdr, Vector pos[], Quaternion q[], float poseparam[], float currentTime, int boneMask )
{
BaseClass::AccumulateLayers( hdr, pos, q, poseparam, currentTime, boneMask );
int i;
// resort the layers
int layer[MAX_OVERLAYS];
for (i = 0; i < MAX_OVERLAYS; i++)
{
layer[i] = MAX_OVERLAYS;
}
for (i = 0; i < m_AnimOverlay.Count(); i++)
{
if (m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS)
{
/*
Assert( layer[m_AnimOverlay[i].m_nOrder] == MAX_OVERLAYS );
layer[m_AnimOverlay[i].m_nOrder] = i;
*/
// hacky code until initialization of new layers is finished
if (layer[m_AnimOverlay[i].m_nOrder] != MAX_OVERLAYS)
{
m_AnimOverlay[i].m_nOrder = MAX_OVERLAYS;
}
else
{
layer[m_AnimOverlay[i].m_nOrder] = i;
}
}
}
CheckForLayerChanges( hdr, currentTime );
int nSequences = hdr->GetNumSeq();
// add in the overlay layers
int j;
for (j = 0; j < MAX_OVERLAYS; j++)
{
i = layer[ j ];
if (i < m_AnimOverlay.Count())
{
if ( m_AnimOverlay[i].m_nSequence >= nSequences )
{
continue;
}
/*
DevMsgRT( 1 , "%.3f %.3f %.3f\n", currentTime, fWeight, dadt );
debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -j - 1, 0,
"%2d(%s) : %6.2f : %6.2f",
m_AnimOverlay[i].m_nSequence,
hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence )->pszLabel(),
m_AnimOverlay[i].m_flCycle,
m_AnimOverlay[i].m_flWeight
);
*/
float fWeight = m_AnimOverlay[i].m_flWeight;
if (fWeight > 0)
{
// check to see if the sequence changed
// FIXME: move this to somewhere more reasonable
// do a nice spline interpolation of the values
// if ( m_AnimOverlay[i].m_nSequence != m_iv_AnimOverlay.GetPrev( i )->nSequence )
float fCycle = m_AnimOverlay[ i ].m_flCycle;
fCycle = ClampCycle( fCycle, IsSequenceLooping( m_AnimOverlay[i].m_nSequence ) );
if (fWeight > 1)
fWeight = 1;
AccumulatePose( hdr, m_pIk, pos, q, m_AnimOverlay[i].m_nSequence, fCycle, poseparam, boneMask, fWeight, currentTime );
#if _DEBUG
if (Q_stristr( hdr->pszName(), r_sequence_debug.GetString()) != NULL)
{
if (1)
{
DevMsgRT( "%6.2f : %30s : %5.3f : %4.2f : %1d\n", currentTime, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i );
}
else
{
int iHead, iPrev1, iPrev2;
m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 );
// fake up previous cycle values.
float t0;
C_AnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 );
// reset previous
float t1;
C_AnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 );
// reset previous previous
float t2;
C_AnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 );
if ( pHead && pPrev1 && pPrev2 )
{
DevMsgRT( "%6.2f : %30s %6.2f (%6.2f:%6.2f:%6.2f) : %6.2f (%6.2f:%6.2f:%6.2f) : %1d\n", currentTime, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(),
fCycle, (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle,
fWeight, (float)pPrev2->m_flWeight, (float)pPrev1->m_flWeight, (float)pHead->m_flWeight,
i );
}
else
{
DevMsgRT( "%6.2f : %30s %6.2f : %6.2f : %1d\n", currentTime, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i );
}
}
}
#endif
}
}
}
}
void C_BaseAnimatingOverlay::DoAnimationEvents( CStudioHdr *pStudioHdr )
{
if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
return;
MDLCACHE_CRITICAL_SECTION();
int nSequences = pStudioHdr->GetNumSeq();
BaseClass::DoAnimationEvents( pStudioHdr );
bool watch = false; // Q_strstr( hdr->name, "rifle" ) ? true : false;
CheckForLayerChanges( pStudioHdr, gpGlobals->curtime ); // !!!
int j;
for (j = 0; j < m_AnimOverlay.Count(); j++)
{
if ( m_AnimOverlay[j].m_nSequence >= nSequences )
{
continue;
}
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[j].m_nSequence );
if ( seqdesc.numevents == 0 )
continue;
// stalled?
if (m_AnimOverlay[j].m_flCycle == m_flOverlayPrevEventCycle[j])
continue;
// check for looping
BOOL bLooped = false;
if (m_AnimOverlay[j].m_flCycle <= m_flOverlayPrevEventCycle[j])
{
if (m_flOverlayPrevEventCycle[j] - m_AnimOverlay[j].m_flCycle > 0.5)
{
bLooped = true;
}
else
{
// things have backed up, which is bad since it'll probably result in a hitch in the animation playback
// but, don't play events again for the same time slice
return;
}
}
mstudioevent_t *pevent = seqdesc.pEvent( 0 );
// This makes sure events that occur at the end of a sequence occur are
// sent before events that occur at the beginning of a sequence.
if (bLooped)
{
for (int i = 0; i < (int)seqdesc.numevents; i++)
{
// ignore all non-client-side events
if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
{
if ( !( pevent[i].type & AE_TYPE_CLIENT ) )
continue;
}
else if ( pevent[i].event < 5000 ) //Adrian - Support the old event system
continue;
if ( pevent[i].cycle <= m_flOverlayPrevEventCycle[j] )
continue;
if ( watch )
{
Msg( "%i FE %i Looped cycle %f, prev %f ev %f (time %.3f)\n",
gpGlobals->tickcount,
pevent[i].event,
pevent[i].cycle,
m_flOverlayPrevEventCycle[j],
m_AnimOverlay[j].m_flCycle,
gpGlobals->curtime );
}
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
// Necessary to get the next loop working
m_flOverlayPrevEventCycle[j] = -0.01;
}
for (int i = 0; i < (int)seqdesc.numevents; i++)
{
if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
{
if ( !( pevent[i].type & AE_TYPE_CLIENT ) )
continue;
}
else if ( pevent[i].event < 5000 ) //Adrian - Support the old event system
continue;
if ( (pevent[i].cycle > m_flOverlayPrevEventCycle[j] && pevent[i].cycle <= m_AnimOverlay[j].m_flCycle) )
{
if ( watch )
{
Msg( "%i (seq: %d) FE %i Normal cycle %f, prev %f ev %f (time %.3f)\n",
gpGlobals->tickcount,
m_AnimOverlay[j].m_nSequence,
pevent[i].event,
pevent[i].cycle,
m_flOverlayPrevEventCycle[j],
m_AnimOverlay[j].m_flCycle,
gpGlobals->curtime );
}
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
}
m_flOverlayPrevEventCycle[j] = m_AnimOverlay[j].m_flCycle;
}
}

View File

@ -0,0 +1,66 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef C_BASEANIMATINGOVERLAY_H
#define C_BASEANIMATINGOVERLAY_H
#pragma once
#include "c_baseanimating.h"
// For shared code.
#define CBaseAnimatingOverlay C_BaseAnimatingOverlay
class C_BaseAnimatingOverlay : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_BaseAnimatingOverlay, C_BaseAnimating );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_BaseAnimatingOverlay();
C_AnimationLayer* GetAnimOverlay( int i );
void SetNumAnimOverlays( int num ); // This makes sure there is space for this # of layers.
int GetNumAnimOverlays() const;
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
void CheckForLayerChanges( CStudioHdr *hdr, float currentTime );
// model specific
virtual void AccumulateLayers( CStudioHdr *hdr, Vector pos[], Quaternion q[], float poseparam[], float currentTime, int boneMask );
virtual void DoAnimationEvents( CStudioHdr *pStudioHdr );
enum
{
MAX_OVERLAYS = 15,
};
CUtlVector < C_AnimationLayer > m_AnimOverlay;
CUtlVector < CInterpolatedVar< C_AnimationLayer > > m_iv_AnimOverlay;
float m_flOverlayPrevEventCycle[ MAX_OVERLAYS ];
private:
C_BaseAnimatingOverlay( const C_BaseAnimatingOverlay & ); // not defined, not accessible
};
EXTERN_RECV_TABLE(DT_BaseAnimatingOverlay);
#endif // C_BASEANIMATINGOVERLAY_H

View File

@ -0,0 +1,72 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's C_BaseCombatCharacter entity
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basecombatcharacter.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if defined( CBaseCombatCharacter )
#undef CBaseCombatCharacter
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseCombatCharacter::C_BaseCombatCharacter()
{
for ( int i=0; i < m_iAmmo.Count(); i++ )
m_iAmmo.Set( i, 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseCombatCharacter::~C_BaseCombatCharacter()
{
}
/*
//-----------------------------------------------------------------------------
// Purpose: Returns the amount of ammunition of the specified type the character's carrying
//-----------------------------------------------------------------------------
int C_BaseCombatCharacter::GetAmmoCount( char *szName ) const
{
return GetAmmoCount( g_pGameRules->GetAmmoDef()->Index(szName) );
}
*/
IMPLEMENT_CLIENTCLASS(C_BaseCombatCharacter, DT_BaseCombatCharacter, CBaseCombatCharacter);
// Only send active weapon index to local player
BEGIN_RECV_TABLE_NOBASE( C_BaseCombatCharacter, DT_BCCLocalPlayerExclusive )
RecvPropTime( RECVINFO( m_flNextAttack ) ),
RecvPropArray3( RECVINFO_ARRAY(m_hMyWeapons), RecvPropEHandle( RECVINFO( m_hMyWeapons[0] ) ) ),
END_RECV_TABLE();
BEGIN_RECV_TABLE(C_BaseCombatCharacter, DT_BaseCombatCharacter)
RecvPropDataTable( "bcc_localdata", 0, 0, &REFERENCE_RECV_TABLE(DT_BCCLocalPlayerExclusive) ),
RecvPropEHandle( RECVINFO( m_hActiveWeapon ) ),
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseCombatCharacter )
DEFINE_PRED_ARRAY( m_iAmmo, FIELD_INTEGER, MAX_AMMO_TYPES, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flNextAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_hActiveWeapon, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_ARRAY( m_hMyWeapons, FIELD_EHANDLE, MAX_WEAPONS, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()

View File

@ -0,0 +1,101 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines the client-side representation of CBaseCombatCharacter.
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASECOMBATCHARACTER_H
#define C_BASECOMBATCHARACTER_H
#ifdef _WIN32
#pragma once
#endif
#include "shareddefs.h"
#include "c_baseflex.h"
class C_BaseCombatWeapon;
class C_WeaponCombatShield;
class C_BaseCombatCharacter : public C_BaseFlex
{
DECLARE_CLASS( C_BaseCombatCharacter, C_BaseFlex );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_BaseCombatCharacter( void );
virtual ~C_BaseCombatCharacter( void );
virtual bool IsBaseCombatCharacter( void ) { return true; };
virtual C_BaseCombatCharacter *MyCombatCharacterPointer( void ) { return this; }
// -----------------------
// Ammo
// -----------------------
void RemoveAmmo( int iCount, int iAmmoIndex );
void RemoveAmmo( int iCount, const char *szName );
void RemoveAllAmmo( );
int GetAmmoCount( int iAmmoIndex ) const;
int GetAmmoCount( char *szName ) const;
C_BaseCombatWeapon* Weapon_OwnsThisType( const char *pszWeapon, int iSubType = 0 ) const; // True if already owns a weapon of this class
virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 );
virtual bool Weapon_CanSwitchTo(C_BaseCombatWeapon *pWeapon);
// I can't use my current weapon anymore. Switch me to the next best weapon.
bool SwitchToNextBestWeapon(C_BaseCombatWeapon *pCurrent);
virtual C_BaseCombatWeapon *GetActiveWeapon( void ) const;
int WeaponCount() const;
C_BaseCombatWeapon *GetWeapon( int i ) const;
// This is a sort of hack back-door only used by physgun!
void SetAmmoCount( int iCount, int iAmmoIndex );
float GetNextAttack() const { return m_flNextAttack; }
void SetNextAttack( float flWait ) { m_flNextAttack = flWait; }
virtual int BloodColor();
// Blood color (see BLOOD_COLOR_* macros in baseentity.h)
void SetBloodColor( int nBloodColor );
public:
float m_flNextAttack;
protected:
int m_bloodColor; // color of blood particless
private:
CNetworkArray( int, m_iAmmo, MAX_AMMO_TYPES );
CHandle<C_BaseCombatWeapon> m_hMyWeapons[MAX_WEAPONS];
CHandle< C_BaseCombatWeapon > m_hActiveWeapon;
private:
C_BaseCombatCharacter( const C_BaseCombatCharacter & ); // not defined, not accessible
//-----------------------
};
inline C_BaseCombatCharacter *ToBaseCombatCharacter( C_BaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsBaseCombatCharacter() )
return NULL;
#if _DEBUG
return dynamic_cast<C_BaseCombatCharacter *>( pEntity );
#else
return static_cast<C_BaseCombatCharacter *>( pEntity );
#endif
}
EXTERN_RECV_TABLE(DT_BaseCombatCharacter);
#endif // C_BASECOMBATCHARACTER_H

View File

@ -0,0 +1,496 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side implementation of CBaseCombatWeapon.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "history_resource.h"
#include "iclientmode.h"
#include "iinput.h"
#include "weapon_selection.h"
#include "hud_crosshair.h"
#include "engine/ivmodelinfo.h"
#include "tier0/vprof.h"
#include "hltvcamera.h"
#include "tier1/KeyValues.h"
#include "toolframework/itoolframework.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Gets the local client's active weapon, if any.
//-----------------------------------------------------------------------------
C_BaseCombatWeapon *GetActiveWeapon( void )
{
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
if ( !player )
return NULL;
return player->GetActiveWeapon();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::SetDormant( bool bDormant )
{
// If I'm going from active to dormant and I'm carried by another player, holster me.
if ( !IsDormant() && bDormant && !IsCarriedByLocalPlayer() )
{
Holster( NULL );
}
BaseClass::SetDormant( bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::NotifyShouldTransmit( ShouldTransmitState_t state )
{
BaseClass::NotifyShouldTransmit(state);
if (state == SHOULDTRANSMIT_END)
{
if (m_iState == WEAPON_IS_ACTIVE)
{
m_iState = WEAPON_IS_CARRIED_BY_PLAYER;
}
}
else if( state == SHOULDTRANSMIT_START )
{
if( m_iState == WEAPON_IS_CARRIED_BY_PLAYER )
{
if( GetOwner() && GetOwner()->GetActiveWeapon() == this )
{
// Restore the Activeness of the weapon if we client-twiddled it off in the first case above.
m_iState = WEAPON_IS_ACTIVE;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
static inline bool ShouldDrawLocalPlayer( void )
{
return C_BasePlayer::ShouldDrawLocalPlayer();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnRestore()
{
BaseClass::OnRestore();
// if the player is holding this weapon,
// mark it as just restored so it won't show as a new pickup
if (GetOwner() == C_BasePlayer::GetLocalPlayer())
{
m_bJustRestored = true;
}
}
int C_BaseCombatWeapon::GetWorldModelIndex( void )
{
return m_iWorldModelIndex;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged(updateType);
CHandle< C_BaseCombatWeapon > handle = this;
// If it's being carried by the *local* player, on the first update,
// find the registered weapon for this ID
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
C_BaseCombatCharacter *pOwner = GetOwner();
// check if weapon is carried by local player
bool bIsLocalPlayer = pPlayer && pPlayer == pOwner;
if ( bIsLocalPlayer && !ShouldDrawLocalPlayer() )
{
// If I was just picked up, or created & immediately carried, add myself to this client's list of weapons
if ( (m_iState != WEAPON_NOT_CARRIED ) && (m_iOldState == WEAPON_NOT_CARRIED) )
{
// Tell the HUD this weapon's been picked up
if ( ShouldDrawPickup() )
{
CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection();
if ( pHudSelection )
{
pHudSelection->OnWeaponPickup( this );
}
pPlayer->EmitSound( "Player.PickupWeapon" );
}
}
}
else // weapon carried by other player or not at all
{
// BRJ 10/14/02
// FIXME: Remove when Yahn's client-side prediction is done
// It's a hacky workaround for the model indices fighting
// (GetRenderBounds uses the model index, which is for the view model)
SetModelIndex( GetWorldModelIndex() );
}
UpdateVisibility();
m_iOldState = m_iState;
m_bJustRestored = false;
}
//-----------------------------------------------------------------------------
// Is anyone carrying it?
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsBeingCarried() const
{
return ( m_hOwner.Get() != NULL );
}
//-----------------------------------------------------------------------------
// Is the carrier alive?
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsCarrierAlive() const
{
if ( !m_hOwner.Get() )
return false;
return m_hOwner.Get()->GetHealth() > 0;
}
//-----------------------------------------------------------------------------
// Should this object cast shadows?
//-----------------------------------------------------------------------------
ShadowType_t C_BaseCombatWeapon::ShadowCastType()
{
if (!IsBeingCarried())
return SHADOWS_RENDER_TO_TEXTURE;
if (IsCarriedByLocalPlayer())
return SHADOWS_NONE;
return (m_iState != WEAPON_IS_CARRIED_BY_PLAYER) ? SHADOWS_RENDER_TO_TEXTURE : SHADOWS_NONE;
}
//-----------------------------------------------------------------------------
// Purpose: This weapon is the active weapon, and it should now draw anything
// it wants to. This gets called every frame.
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::Redraw()
{
if ( g_pClientMode->ShouldDrawCrosshair() )
{
DrawCrosshair();
}
// ammo drawing has been moved into hud_ammo.cpp
}
//-----------------------------------------------------------------------------
// Purpose: Draw the weapon's crosshair
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::DrawCrosshair()
{
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
if ( !player )
return;
Color clr = gHUD.m_clrNormal;
/*
// TEST: if the thing under your crosshair is on a different team, light the crosshair with a different color.
Vector vShootPos, vShootAngles;
GetShootPosition( vShootPos, vShootAngles );
Vector vForward;
AngleVectors( vShootAngles, &vForward );
// Change the color depending on if we're looking at a friend or an enemy.
CPartitionFilterListMask filter( PARTITION_ALL_CLIENT_EDICTS );
trace_t tr;
traceline->TraceLine( vShootPos, vShootPos + vForward * 10000, COLLISION_GROUP_NONE, MASK_SHOT, &tr, true, ~0, &filter );
if ( tr.index != 0 && tr.index != INVALID_CLIENTENTITY_HANDLE )
{
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( tr.index );
if ( pEnt )
{
if ( pEnt->GetTeamNumber() != player->GetTeamNumber() )
{
g = b = 0;
}
}
}
*/
CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair );
if ( !crosshair )
return;
// Check to see if the player is in VGUI mode...
if (player->IsInVGuiInputMode())
{
CHudTexture *pArrow = gHUD.GetIcon( "arrow" );
crosshair->SetCrosshair( pArrow, gHUD.m_clrNormal );
return;
}
// Find out if this weapon's auto-aimed onto a target
bool bOnTarget = ( m_iState == WEAPON_IS_ONTARGET );
if ( player->GetFOV() >= 90 )
{
// normal crosshairs
if ( bOnTarget && GetWpnData().iconAutoaim )
{
clr[3] = 255;
crosshair->SetCrosshair( GetWpnData().iconAutoaim, clr );
}
else if ( GetWpnData().iconCrosshair )
{
clr[3] = 255;
crosshair->SetCrosshair( GetWpnData().iconCrosshair, clr );
}
else
{
crosshair->ResetCrosshair();
}
}
else
{
Color white( 255, 255, 255, 255 );
// zoomed crosshairs
if (bOnTarget && GetWpnData().iconZoomedAutoaim)
crosshair->SetCrosshair(GetWpnData().iconZoomedAutoaim, white);
else if ( GetWpnData().iconZoomedCrosshair )
crosshair->SetCrosshair( GetWpnData().iconZoomedCrosshair, white );
else
crosshair->ResetCrosshair();
}
}
//-----------------------------------------------------------------------------
// Purpose: This weapon is the active weapon, and the viewmodel for it was just drawn.
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::ViewModelDrawn( C_BaseViewModel *pViewModel )
{
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this client's carrying this weapon
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsCarriedByLocalPlayer( void )
{
if ( !GetOwner() )
return false;
return ( GetOwner() == C_BasePlayer::GetLocalPlayer() );
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this weapon is the local client's currently wielded weapon
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsActiveByLocalPlayer( void )
{
if ( IsCarriedByLocalPlayer() )
{
return (m_iState == WEAPON_IS_ACTIVE);
}
return false;
}
bool C_BaseCombatWeapon::GetShootPosition( Vector &vOrigin, QAngle &vAngles )
{
// Get the entity because the weapon doesn't have the right angles.
C_BaseCombatCharacter *pEnt = ToBaseCombatCharacter( GetOwner() );
if ( pEnt )
{
if ( pEnt == C_BasePlayer::GetLocalPlayer() )
{
vAngles = pEnt->EyeAngles();
}
else
{
vAngles = pEnt->GetRenderAngles();
}
}
else
{
vAngles.Init();
}
QAngle vDummy;
if ( IsActiveByLocalPlayer() && !ShouldDrawLocalPlayer() )
{
C_BasePlayer *player = ToBasePlayer( pEnt );
C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL;
if ( vm )
{
int iAttachment = vm->LookupAttachment( "muzzle" );
if ( vm->GetAttachment( iAttachment, vOrigin, vDummy ) )
{
return true;
}
}
}
else
{
// Thirdperson
int iAttachment = LookupAttachment( "muzzle" );
if ( GetAttachment( iAttachment, vOrigin, vDummy ) )
{
return true;
}
}
vOrigin = GetRenderOrigin();
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::ShouldDraw( void )
{
if ( m_iWorldModelIndex == 0 )
return false;
// FIXME: All weapons with owners are set to transmit in CBaseCombatWeapon::UpdateTransmitState,
// even if they have EF_NODRAW set, so we have to check this here. Ideally they would never
// transmit except for the weapons owned by the local player.
if ( IsEffectActive( EF_NODRAW ) )
return false;
C_BaseCombatCharacter *pOwner = GetOwner();
// weapon has no owner, always draw it
if ( !pOwner )
return true;
bool bIsActive = ( m_iState == WEAPON_IS_ACTIVE );
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
// carried by local player?
if ( pOwner == pLocalPlayer )
{
// Only ever show the active weapon
if ( !bIsActive )
return false;
// 3rd person mode
if ( ShouldDrawLocalPlayer() )
return true;
// don't draw active weapon if not in some kind of 3rd person mode, the viewmodel will do that
return false;
}
// If it's a player, then only show active weapons
if ( pOwner->IsPlayer() )
{
// Show it if it's active...
return bIsActive;
}
// FIXME: We may want to only show active weapons on NPCs
// These are carried by AIs; always show them
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if a weapon-pickup icon should be displayed when this weapon is received
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::ShouldDrawPickup( void )
{
if ( m_bJustRestored )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried
// by this player, otherwise draw the worldmodel.
//-----------------------------------------------------------------------------
int C_BaseCombatWeapon::DrawModel( int flags )
{
VPROF_BUDGET( "C_BaseCombatWeapon::DrawModel", VPROF_BUDGETGROUP_MODEL_RENDERING );
if ( !m_bReadyToDraw )
return 0;
if ( !IsVisible() )
return 0;
// check if local player chases owner of this weapon in first person
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer && localplayer->IsObserver() && GetOwner() )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return false;
}
return BaseClass::DrawModel( flags );
}
//-----------------------------------------------------------------------------
// tool recording
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::GetToolRecordingState( KeyValues *msg )
{
if ( !ToolsEnabled() )
return;
int nModelIndex = GetModelIndex();
int nWorldModelIndex = GetWorldModelIndex();
if ( nModelIndex != nWorldModelIndex )
{
SetModelIndex( nWorldModelIndex );
}
BaseClass::GetToolRecordingState( msg );
if ( m_iState == WEAPON_IS_ACTIVE )
{
BaseEntityRecordingState_t *pBaseEntity = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );
pBaseEntity->m_bVisible = true;
}
else if ( m_iState == WEAPON_NOT_CARRIED )
{
BaseEntityRecordingState_t *pBaseEntity = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );
pBaseEntity->m_nOwner = 0;
}
if ( nModelIndex != nWorldModelIndex )
{
SetModelIndex( nModelIndex );
}
}

View File

@ -0,0 +1,26 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CBaseCombatWeapon entity
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASECOMBATWEAPON_H
#define C_BASECOMBATWEAPON_H
#ifdef _WIN32
#pragma once
#endif
#include "basecombatweapon_shared.h"
#include "weapons_resource.h"
class CViewSetup;
class C_BaseViewModel;
// Accessors for local weapons
C_BaseCombatWeapon *GetActiveWeapon( void );
#endif // C_BASECOMBATWEAPON

28
cl_dll/c_basedoor.cpp Normal file
View File

@ -0,0 +1,28 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basedoor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef CBaseDoor
#undef CBaseDoor
#endif
IMPLEMENT_CLIENTCLASS_DT(C_BaseDoor, DT_BaseDoor, CBaseDoor)
RecvPropFloat(RECVINFO(m_flWaveHeight)),
END_RECV_TABLE()
C_BaseDoor::C_BaseDoor( void )
{
m_flWaveHeight = 0.0f;
}
C_BaseDoor::~C_BaseDoor( void )
{
}

32
cl_dll/c_basedoor.h Normal file
View File

@ -0,0 +1,32 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( C_BASEDOOR_H )
#define C_BASEDOOR_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#if defined( CLIENT_DLL )
#define CBaseDoor C_BaseDoor
#endif
class C_BaseDoor : public C_BaseEntity
{
public:
DECLARE_CLASS( C_BaseDoor, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_BaseDoor( void );
~C_BaseDoor( void );
public:
float m_flWaveHeight;
};
#endif // C_BASEDOOR_H

5736
cl_dll/c_baseentity.cpp Normal file

File diff suppressed because it is too large Load Diff

2027
cl_dll/c_baseentity.h Normal file

File diff suppressed because it is too large Load Diff

1730
cl_dll/c_baseflex.cpp Normal file

File diff suppressed because it is too large Load Diff

276
cl_dll/c_baseflex.h Normal file
View File

@ -0,0 +1,276 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// Client-side CBasePlayer
#ifndef C_STUDIOFLEX_H
#define C_STUDIOFLEX_H
#pragma once
#include "c_baseanimating.h"
#include "c_baseanimatingoverlay.h"
#include "sceneentity_shared.h"
#include "UtlVector.h"
//-----------------------------------------------------------------------------
// Purpose: Item in list of loaded scene files
//-----------------------------------------------------------------------------
class CFlexSceneFile
{
public:
enum
{
MAX_FLEX_FILENAME = 128,
};
char filename[ MAX_FLEX_FILENAME ];
void *buffer;
};
// For phoneme emphasis track
struct Emphasized_Phoneme;
class CSentence;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BaseFlex : public C_BaseAnimatingOverlay
{
DECLARE_CLASS( C_BaseFlex, C_BaseAnimatingOverlay );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_BaseFlex();
virtual ~C_BaseFlex();
virtual CStudioHdr *OnNewModel( void );
// model specific
virtual void SetupWeights( );
virtual void RunFlexRules( CStudioHdr *pStudioHdr, float *dest );
virtual Vector SetViewTarget( CStudioHdr *pStudioHdr );
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
virtual void GetToolRecordingState( KeyValues *msg );
// Called at the lowest level to actually apply a flex animation
void AddFlexAnimation( CSceneEventInfo *info );
void SetFlexWeight( int index, float value );
float GetFlexWeight( int index );
// Look up flex controller index by global name
int FindFlexController( const char *szName );
public:
Vector m_viewtarget;
CInterpolatedVar< Vector > m_iv_viewtarget;
float m_flexWeight[64];
CInterpolatedVarArray< float, 64 > m_iv_flexWeight;
int m_blinktoggle;
static int AddGlobalFlexController( char *szName );
static char const *GetGlobalFlexControllerName( int idx );
// bah, this should be unified with all prev/current stuff.
public:
// Keep track of what scenes are being played
void StartChoreoScene( CChoreoScene *scene );
void RemoveChoreoScene( CChoreoScene *scene );
// Start the specifics of an scene event
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget );
// Manipulation of events for the object
// Should be called by think function to process all scene events
// The default implementation resets m_flexWeight array and calls
// AddSceneEvents
virtual void ProcessSceneEvents( bool bFlexEvents );
// Assumes m_flexWeight array has been set up, this adds the actual currently playing
// expressions to the flex weights and adds other scene events as needed
virtual bool ProcessSceneEvent( bool bFlexEvents, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
// Remove all playing events
void ClearSceneEvents( CChoreoScene *scene, bool canceled );
// Stop specifics of event
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
// Add the event to the queue for this actor
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL );
// Remove the event from the queue for this actor
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );
// Checks to see if the event should be considered "completed"
bool CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
// Checks to see if a event should be considered "completed"
virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event );
int FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key );
void EnsureTranslations( const flexsettinghdr_t *pSettinghdr );
private:
bool ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool ProcessFlexSettingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
void AddFlexSetting( const char *expr, float scale,
const flexsettinghdr_t *pSettinghdr, const flexsettinghdr_t *pOverrideHdr, bool newexpression );
// Array of active SceneEvents, in order oldest to newest
CUtlVector < CSceneEventInfo > m_SceneEvents;
CUtlVector < CChoreoScene * > m_ActiveChoreoScenes;
bool HasSceneEvents() const;
private:
// Mapping for each loaded scene file used by this actor
struct FS_LocalToGlobal_t
{
explicit FS_LocalToGlobal_t() :
m_Key( 0 ),
m_nCount( 0 ),
m_Mapping( 0 )
{
}
explicit FS_LocalToGlobal_t( const flexsettinghdr_t *key ) :
m_Key( key ),
m_nCount( 0 ),
m_Mapping( 0 )
{
}
void SetCount( int count )
{
Assert( !m_Mapping );
Assert( count > 0 );
m_nCount = count;
m_Mapping = new int[ m_nCount ];
Q_memset( m_Mapping, 0, m_nCount * sizeof( int ) );
}
FS_LocalToGlobal_t( const FS_LocalToGlobal_t& src )
{
m_Key = src.m_Key;
delete m_Mapping;
m_Mapping = new int[ src.m_nCount ];
Q_memcpy( m_Mapping, src.m_Mapping, src.m_nCount * sizeof( int ) );
m_nCount = src.m_nCount;
}
~FS_LocalToGlobal_t()
{
delete m_Mapping;
m_nCount = 0;
m_Mapping = 0;
}
const flexsettinghdr_t *m_Key;
int m_nCount;
int *m_Mapping;
};
static bool FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs );
CUtlRBTree< FS_LocalToGlobal_t, unsigned short > m_LocalToGlobal;
float m_blinktime;
int m_prevblinktoggle;
int m_iBlink;
int m_iEyeUpdown;
int m_iEyeRightleft;
int m_iMouthAttachment;
float *m_flFlexDelayedWeight;
// shared flex controllers
static int g_numflexcontrollers;
static char *g_flexcontroller[MAXSTUDIOFLEXCTRL*4]; // room for global set of flexcontrollers
static float g_flexweight[MAXSTUDIOFLEXDESC];
private:
C_BaseFlex( const C_BaseFlex & ); // not defined, not accessible
enum
{
PHONEME_CLASS_WEAK = 0,
PHONEME_CLASS_NORMAL,
PHONEME_CLASS_STRONG,
NUM_PHONEME_CLASSES
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct Emphasized_Phoneme
{
// Global fields, setup at start
char classname[ 64 ];
bool required;
// Global fields setup first time tracks played
bool basechecked;
const flexsettinghdr_t *base;
#if !defined( NO_ENTITY_PREDICTION )
bool overridechecked;
const flexsettinghdr_t *override;
#endif
const flexsetting_t *exp;
// Local fields, processed for each sentence
bool valid;
float amount;
};
// For handling scene files
void *FindSceneFile( const char *filename );
const flexsetting_t *FindNamedSetting( const flexsettinghdr_t *pSettinghdr, const char *expr );
void ProcessVisemes( Emphasized_Phoneme *classes );
void AddVisemesForSentence( Emphasized_Phoneme *classes, float emphasis_intensity, CSentence *sentence, float t, float dt, bool juststarted );
void AddViseme( Emphasized_Phoneme *classes, float emphasis_intensity, int phoneme, float scale, bool newexpression );
bool SetupEmphasisBlend( Emphasized_Phoneme *classes, int phoneme );
void ComputeBlendedSetting( Emphasized_Phoneme *classes, float emphasis_intensity );
Emphasized_Phoneme m_PhonemeClasses[ NUM_PHONEME_CLASSES ];
};
//-----------------------------------------------------------------------------
// Do we have active expressions?
//-----------------------------------------------------------------------------
inline bool C_BaseFlex::HasSceneEvents() const
{
return m_SceneEvents.Count() != 0;
}
EXTERN_RECV_TABLE(DT_BaseFlex);
float *GetVisemeWeights( int phoneme );
#endif // C_STUDIOFLEX_H

2011
cl_dll/c_baseplayer.cpp Normal file

File diff suppressed because it is too large Load Diff

533
cl_dll/c_baseplayer.h Normal file
View File

@ -0,0 +1,533 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client-side CBasePlayer.
//
// - Manages the player's flashlight effect.
//
//=============================================================================//
#ifndef C_BASEPLAYER_H
#define C_BASEPLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "c_playerlocaldata.h"
#include "c_basecombatcharacter.h"
#include "playerstate.h"
#include "usercmd.h"
#include "shareddefs.h"
#include "timedevent.h"
#include "smartptr.h"
#include "fx_water.h"
class C_BaseCombatWeapon;
class C_BaseViewModel;
class C_FuncLadder;
class CFlashlightEffect;
extern int g_nKillCamMode;
extern int g_nKillCamTarget1;
extern int g_nKillCamTarget2;
extern int g_nUsedPrediction;
class C_CommandContext
{
public:
bool needsprocessing;
CUserCmd cmd;
int command_number;
};
class C_PredictionError
{
public:
float time;
Vector error;
};
#define CHASE_CAM_DISTANCE 96.0f
#define WALL_OFFSET 6.0f
//-----------------------------------------------------------------------------
// Purpose: Base Player class
//-----------------------------------------------------------------------------
class C_BasePlayer : public C_BaseCombatCharacter
{
public:
DECLARE_CLASS( C_BasePlayer, C_BaseCombatCharacter );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_BasePlayer();
virtual ~C_BasePlayer();
virtual void Spawn( void );
virtual void SharedSpawn(); // Shared between client and server.
// IClientEntity overrides.
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void OnRestore();
virtual void AddEntity( void );
virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
virtual void GetToolRecordingState( KeyValues *msg );
void SetAnimationExtension( const char *pExtension );
C_BaseViewModel *GetViewModel( int viewmodelindex = 0 );
C_BaseCombatWeapon *GetActiveWeapon( void ) const;
// View model prediction setup
virtual void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
virtual void CalcViewModelView( const Vector& eyeOrigin, const QAngle& eyeAngles);
// Handle view smoothing when going up stairs
void SmoothViewOnStairs( Vector& eyeOrigin );
virtual float CalcRoll (const QAngle& angles, const Vector& velocity, float rollangle, float rollspeed);
void CalcViewRoll( QAngle& eyeAngles );
void CreateWaterEffects( void );
virtual Vector Weapon_ShootPosition();
virtual void Weapon_DropPrimary( void ) {}
virtual Vector GetAutoaimVector( float flScale );
void SetSuitUpdate(char *name, int fgroup, int iNoRepeat);
// Input handling
virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd );
virtual void AvoidPhysicsProps( CUserCmd *pCmd );
virtual void PlayerUse( void );
CBaseEntity *FindUseEntity( void );
virtual bool IsUseableEntity( CBaseEntity *pEntity, unsigned int requiredCaps );
// Data handlers
virtual bool IsPlayer( void ) const { return true; };
virtual int GetHealth() const { return m_iHealth; };
// observer mode
virtual int GetObserverMode() const;
virtual CBaseEntity *GetObserverTarget() const;
void SetObserverTarget( EHANDLE hObserverTarget );
bool IsObserver() const;
bool IsHLTV() const;
void ResetObserverMode();
bool IsBot( void ) const { return false; }
// Eye position..
virtual Vector EyePosition();
virtual const QAngle &EyeAngles(); // Direction of eyes
void EyePositionAndVectors( Vector *pPosition, Vector *pForward, Vector *pRight, Vector *pUp );
virtual const QAngle &LocalEyeAngles(); // Direction of eyes
// This can be overridden to return something other than m_pRagdoll if the mod uses separate
// entities for ragdolls.
virtual IRagdoll* GetRepresentativeRagdoll() const;
// Returns eye vectors
void EyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL );
bool IsSuitEquipped( void ) { return m_Local.m_bWearingSuit; };
// Team handlers
virtual void TeamChange( int iNewTeam );
// Flashlight
void Flashlight( void );
void UpdateFlashlight( void );
// Weapon selection code
virtual bool IsAllowedToSwitchWeapons( void ) { return !IsObserver(); }
virtual C_BaseCombatWeapon *GetActiveWeaponForSelection( void );
// Returns the view model if this is the local player. If you're in third person or
// this is a remote player, it returns the active weapon
//
virtual C_BaseAnimating* GetRenderedWeaponModel();
virtual bool IsOverridingViewmodel( void ) { return false; };
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags ) { return 0; };
virtual float GetDefaultAnimSpeed( void ) { return 1.0; }
void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; }
float MaxSpeed() const { return m_flMaxspeed; }
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }
bool ShouldReceiveProjectedTextures( int flags )
{
return false;
}
bool IsLocalPlayer( void ) const;
// Global/static methods
static bool ShouldDrawLocalPlayer();
static C_BasePlayer *GetLocalPlayer( void );
int GetUserID( void );
// Called by the view model if its rendering is being overridden.
virtual bool ViewModel_IsTransparent( void );
#if !defined( NO_ENTITY_PREDICTION )
void AddToPlayerSimulationList( C_BaseEntity *other );
void SimulatePlayerSimulatedEntities( void );
void RemoveFromPlayerSimulationList( C_BaseEntity *ent );
void ClearPlayerSimulationList( void );
#endif
virtual void PhysicsSimulate( void );
virtual unsigned int PhysicsSolidMaskForEntity( void ) const { return MASK_PLAYERSOLID; }
// Prediction stuff
virtual bool ShouldPredict( void );
virtual void PreThink( void );
virtual void PostThink( void );
virtual void ItemPreFrame( void );
virtual void ItemPostFrame( void );
virtual void AbortReload( void );
virtual void SelectLastItem(void);
virtual void Weapon_SetLast( C_BaseCombatWeapon *pWeapon );
virtual bool Weapon_ShouldSetLast( C_BaseCombatWeapon *pOldWeapon, C_BaseCombatWeapon *pNewWeapon ) { return true; }
virtual bool Weapon_ShouldSelectItem( C_BaseCombatWeapon *pWeapon );
virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed)
virtual C_BaseCombatWeapon *GetLastWeapon( void ) { return m_hLastWeapon.Get(); }
void ResetAutoaim( void );
virtual void SelectItem( const char *pstr, int iSubType = 0 );
virtual void UpdateClientData( void );
virtual float GetFOV( void );
int GetDefaultFOV( void ) const;
virtual bool IsZoomed( void ) { return false; }
float GetFOVDistanceAdjustFactor();
virtual void ViewPunch( const QAngle &angleOffset );
void ViewPunchReset( float tolerance = 0 );
void UpdateButtonState( int nUserCmdButtonMask );
int GetImpulse( void ) const;
virtual void Simulate();
virtual bool ShouldInterpolate();
virtual bool ShouldDraw();
virtual int DrawModel( int flags );
// Called when not in tactical mode. Allows view to be overriden for things like driving a tank.
virtual void OverrideView( CViewSetup *pSetup );
// returns the player name
const char * GetPlayerName();
virtual const Vector GetPlayerMins( void ) const; // uses local player
virtual const Vector GetPlayerMaxs( void ) const; // uses local player
// Is the player dead?
bool IsPlayerDead();
bool IsPoisoned( void ) { return m_Local.m_bPoisoned; }
// Vehicles...
IClientVehicle *GetVehicle();
bool IsInAVehicle() const { return ( NULL != m_hVehicle.Get() ) ? true : false; }
virtual void SetVehicleRole( int nRole );
void LeaveVehicle( void );
bool UsingStandardWeaponsInVehicle( void );
virtual void SetAnimation( PLAYER_ANIM playerAnim );
float GetTimeBase( void ) const;
float GetFinalPredictedTime() const;
bool IsInVGuiInputMode() const;
C_CommandContext *GetCommandContext();
// Get the command number associated with the current usercmd we're running (if in predicted code).
int CurrentCommandNumber() const;
const CUserCmd *GetCurrentUserCommand() const;
const QAngle& GetPunchAngle();
void SetPunchAngle( const QAngle &angle );
float GetWaterJumpTime() const;
void SetWaterJumpTime( float flWaterJumpTime );
float GetSwimSoundTime( void ) const;
void SetSwimSoundTime( float flSwimSoundTime );
// CS wants to allow small FOVs for zoomed-in AWPs.
virtual float GetMinFOV() const;
virtual void DoMuzzleFlash();
virtual void PlayPlayerJingle();
virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity );
virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force );
virtual surfacedata_t * GetFootstepSurface( const Vector &origin, const char *surfaceName );
// Called by prediction when it detects a prediction correction.
// vDelta is the line from where the client had predicted the player to at the usercmd in question,
// to where the server says the client should be at said usercmd.
void NotePredictionError( const Vector &vDelta );
// Called by the renderer to apply the prediction error smoothing.
void GetPredictionErrorSmoothingVector( Vector &vOffset );
virtual void ExitLadder() {}
surfacedata_t *GetSurfaceData( void ) { return m_pSurfaceData; }
void SetLadderNormal( Vector vecLadderNormal ) { m_vecLadderNormal = vecLadderNormal; }
public:
int m_StuckLast;
// Data for only the local player
CNetworkVarEmbedded( CPlayerLocalData, m_Local );
// Data common to all other players, too
CPlayerState pl;
// Player FOV values
int m_iFOV; // field of view
int m_iFOVStart; // starting value of the FOV changing over time (client only)
float m_flFOVTime; // starting time of the FOV zoom
int m_iDefaultFOV; // default FOV if no other zooms are occurring
// For weapon prediction
bool m_fOnTarget; //Is the crosshair on a target?
char m_szAnimExtension[32];
int m_afButtonLast;
int m_afButtonPressed;
int m_afButtonReleased;
int m_nButtons;
CUserCmd *m_pCurrentCommand;
// Movement constraints
EHANDLE m_hConstraintEntity;
Vector m_vecConstraintCenter;
float m_flConstraintRadius;
float m_flConstraintWidth;
float m_flConstraintSpeedFactor;
protected:
void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcVehicleView(IClientVehicle *pVehicle, Vector& eyeOrigin, QAngle& eyeAngles,
float& zNear, float& zFar, float& fov );
virtual void CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcChaseCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcInEyeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcDeathCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcRoamingView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov);
// Check to see if we're in vgui input mode...
void DetermineVguiInputMode( CUserCmd *pCmd );
// Used by prediction, sets the view angles for the player
void SetLocalViewAngles( const QAngle &viewAngles );
// used by client side player footsteps
surfacedata_t* GetGroundSurface();
protected:
// Did we just enter a vehicle this frame?
bool JustEnteredVehicle();
// DATA
int m_iObserverMode; // if in spectator mode != 0
EHANDLE m_hObserverTarget; // current observer target
float m_flObserverChaseDistance; // last distance to observer traget
float m_flDeathTime; // last time player died
float m_flStepSoundTime;
private:
// Make sure no one calls this...
C_BasePlayer& operator=( const C_BasePlayer& src );
C_BasePlayer( const C_BasePlayer & ); // not defined, not accessible
// Vehicle stuff.
EHANDLE m_hVehicle;
EHANDLE m_hOldVehicle;
EHANDLE m_hUseEntity;
float m_flMaxspeed;
int m_iHealth;
CInterpolatedVar< Vector > m_iv_vecViewOffset;
// Not replicated
Vector m_vecWaterJumpVel;
float m_flWaterJumpTime; // used to be called teleport_time
int m_nImpulse;
float m_flSwimSoundTime;
Vector m_vecLadderNormal;
QAngle m_vecOldViewAngles;
bool m_bWasFrozen;
int m_flPhysics;
int m_nTickBase;
int m_nFinalPredictedTick;
EHANDLE m_pCurrentVguiScreen;
// Player flashlight dynamic light pointers
CFlashlightEffect *m_pFlashlight;
typedef CHandle<C_BaseCombatWeapon> CBaseCombatWeaponHandle;
CNetworkVar( CBaseCombatWeaponHandle, m_hLastWeapon );
#if !defined( NO_ENTITY_PREDICTION )
CUtlVector< CHandle< C_BaseEntity > > m_SimulatedByThisPlayer;
#endif
// players own view models, left & right hand
CHandle< C_BaseViewModel > m_hViewModel[ MAX_VIEWMODELS ];
float m_flOldPlayerZ;
float m_flOldPlayerViewOffsetZ;
// For UI purposes...
int m_iOldAmmo[ MAX_AMMO_TYPES ];
C_CommandContext m_CommandContext;
// For underwater effects
float m_flWaterSurfaceZ;
bool m_bResampleWaterSurface;
TimedEvent m_tWaterParticleTimer;
CSmartPtr<WaterDebrisEffect> m_pWaterEmitter;
friend class CPrediction;
friend class CTFGameMovementRecon;
friend class CGameMovement;
friend class CTFGameMovement;
friend class CHL1GameMovement;
friend class CCSGameMovement;
friend class CHL2GameMovement;
friend class CDODGameMovement;
// Accessors for gamemovement
float GetStepSize( void ) const { return m_Local.m_flStepSize; }
float m_flNextAvoidanceTime;
float m_flAvoidanceRight;
float m_flAvoidanceForward;
float m_flAvoidanceDotForward;
float m_flAvoidanceDotRight;
protected:
virtual bool IsDucked( void ) const { return m_Local.m_bDucked; }
virtual bool IsDucking( void ) const { return m_Local.m_bDucking; }
virtual float GetFallVelocity( void ) { return m_Local.m_flFallVelocity; }
float m_flLaggedMovementValue;
// These are used to smooth out prediction corrections. They're most useful when colliding with
// vphysics objects. The server will be sending constant prediction corrections, and these can help
// the errors not be so jerky.
Vector m_vecPredictionError;
float m_flPredictionErrorTime;
char m_szLastPlaceName[MAX_PLACE_NAME_LENGTH]; // received from the server
// Texture names and surface data, used by CGameMovement
int m_surfaceProps;
surfacedata_t* m_pSurfaceData;
float m_surfaceFriction;
char m_chTextureType;
public:
const char *GetLastKnownPlaceName( void ) const { return m_szLastPlaceName; } // return the last nav place name the player occupied
float GetLaggedMovementValue( void ){ return m_flLaggedMovementValue; }
bool ShouldGoSouth( Vector vNPCForward, Vector vNPCRight ); //Such a bad name.
void SetOldPlayerZ( float flOld ) { m_flOldPlayerZ = flOld; }
};
EXTERN_RECV_TABLE(DT_BasePlayer);
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline C_BasePlayer *ToBasePlayer( C_BaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsPlayer() )
return NULL;
#if _DEBUG
Assert( dynamic_cast<C_BasePlayer *>( pEntity ) != NULL );
#endif
return static_cast<C_BasePlayer *>( pEntity );
}
inline IClientVehicle *C_BasePlayer::GetVehicle()
{
C_BaseEntity *pVehicleEnt = m_hVehicle.Get();
return pVehicleEnt ? pVehicleEnt->GetClientVehicle() : NULL;
}
inline bool C_BasePlayer::IsObserver() const
{
return (GetObserverMode() != OBS_MODE_NONE);
}
inline int C_BasePlayer::GetImpulse( void ) const
{
return m_nImpulse;
}
inline C_CommandContext* C_BasePlayer::GetCommandContext()
{
return &m_CommandContext;
}
inline int CBasePlayer::CurrentCommandNumber() const
{
Assert( m_pCurrentCommand );
return m_pCurrentCommand->command_number;
}
inline const CUserCmd *CBasePlayer::GetCurrentUserCommand() const
{
Assert( m_pCurrentCommand );
return m_pCurrentCommand;
}
#endif // C_BASEPLAYER_H

200
cl_dll/c_basetempentity.cpp Normal file
View File

@ -0,0 +1,200 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Core Temp Entity client implementation.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basetempentity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS(C_BaseTempEntity, DT_BaseTempEntity, CBaseTempEntity);
BEGIN_RECV_TABLE_NOBASE(C_BaseTempEntity, DT_BaseTempEntity)
END_RECV_TABLE()
// Global list of temp entity classes
C_BaseTempEntity *C_BaseTempEntity::s_pTempEntities = NULL;
// Global list of dynamic temp entities
C_BaseTempEntity *C_BaseTempEntity::s_pDynamicEntities = NULL;
//-----------------------------------------------------------------------------
// Purpose: Returns head of list
// Output : CBaseTempEntity * -- head of list
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetDynamicList( void )
{
return s_pDynamicEntities;
}
//-----------------------------------------------------------------------------
// Purpose: Returns head of list
// Output : CBaseTempEntity * -- head of list
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetList( void )
{
return s_pTempEntities;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
C_BaseTempEntity::C_BaseTempEntity( void )
{
// Add to list
m_pNext = s_pTempEntities;
s_pTempEntities = this;
m_pNextDynamic = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
C_BaseTempEntity::~C_BaseTempEntity( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Get next temp ent in chain
// Output : CBaseTempEntity *
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetNext( void )
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Purpose: Get next temp ent in chain
// Output : CBaseTempEntity *
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetNextDynamic( void )
{
return m_pNextDynamic;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseTempEntity::Precache( void )
{
// Nothing...
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup to allow temp entities to precache any models/sounds that they need
//-----------------------------------------------------------------------------
void C_BaseTempEntity::PrecacheTempEnts( void )
{
C_BaseTempEntity *te = GetList();
while ( te )
{
te->Precache();
te = te->GetNext();
}
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup and level load to clear out leftover temp entities
//-----------------------------------------------------------------------------
void C_BaseTempEntity::ClearDynamicTempEnts( void )
{
C_BaseTempEntity *next;
C_BaseTempEntity *te = s_pDynamicEntities;
while ( te )
{
next = te->GetNextDynamic();
delete te;
te = next;
}
s_pDynamicEntities = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup and level load to clear out leftover temp entities
//-----------------------------------------------------------------------------
void C_BaseTempEntity::CheckDynamicTempEnts( void )
{
C_BaseTempEntity *next, *newlist = NULL;
C_BaseTempEntity *te = s_pDynamicEntities;
while ( te )
{
next = te->GetNextDynamic();
if ( te->ShouldDestroy() )
{
delete te;
}
else
{
te->m_pNextDynamic = newlist;
newlist = te;
}
te = next;
}
s_pDynamicEntities = newlist;
}
//-----------------------------------------------------------------------------
// Purpose: Dynamic/non-singleton temp entities are initialized by
// calling into here. They should be added to a list of C_BaseTempEntities so
// that their memory can be deallocated appropriately.
// Input : *pEnt -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseTempEntity::Init( int entnum, int iSerialNum )
{
if ( entnum != -1 )
{
Assert( 0 );
}
// Link into dynamic entity list
m_pNextDynamic = s_pDynamicEntities;
s_pDynamicEntities = this;
return true;
}
void C_BaseTempEntity::Release()
{
Assert( !"C_BaseTempEntity::Release should never be called" );
}
void C_BaseTempEntity::NotifyShouldTransmit( ShouldTransmitState_t state )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bool -
//-----------------------------------------------------------------------------
void C_BaseTempEntity::PreDataUpdate( DataUpdateType_t updateType )
{
// TE's may or may not implement this
}
int C_BaseTempEntity::entindex( void ) const { Assert( 0 ); return 0; }
void C_BaseTempEntity::PostDataUpdate( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::OnPreDataChanged( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::OnDataChanged( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::SetDormant( bool bDormant ) { Assert( 0 ); }
bool C_BaseTempEntity::IsDormant( void ) { Assert( 0 ); return false; };
void C_BaseTempEntity::ReceiveMessage( int classID, bf_read &msg ) { Assert( 0 ); }
void* C_BaseTempEntity::GetDataTableBasePtr()
{
return this;
}

121
cl_dll/c_basetempentity.h Normal file
View File

@ -0,0 +1,121 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASETEMPENTITY_H
#define C_BASETEMPENTITY_H
#ifdef _WIN32
#pragma once
#endif
#include "client_class.h"
#include "iclientnetworkable.h"
#include "c_recipientfilter.h"
//-----------------------------------------------------------------------------
// Purpose: Base class for TEs. All TEs should derive from this and at
// least implement OnDataChanged to be notified when the TE has been received
// from the server
//-----------------------------------------------------------------------------
class C_BaseTempEntity : public IClientUnknown, public IClientNetworkable
{
public:
DECLARE_CLASS_NOBASE( C_BaseTempEntity );
DECLARE_CLIENTCLASS();
C_BaseTempEntity( void );
virtual ~C_BaseTempEntity( void );
// IClientUnknown implementation.
public:
virtual void SetRefEHandle( const CBaseHandle &handle ) { Assert( false ); }
virtual const CBaseHandle& GetRefEHandle() const { return *((CBaseHandle*)0); }
virtual IClientUnknown* GetIClientUnknown() { return this; }
virtual ICollideable* GetCollideable() { return 0; }
virtual IClientNetworkable* GetClientNetworkable() { return this; }
virtual IClientRenderable* GetClientRenderable() { return 0; }
virtual IClientEntity* GetIClientEntity() { return 0; }
virtual C_BaseEntity* GetBaseEntity() { return 0; }
virtual IClientThinkable* GetClientThinkable() { return 0; }
// IClientNetworkable overrides.
public:
virtual void Release();
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void SetDormant( bool bDormant );
virtual bool IsDormant( void );
virtual int entindex( void ) const;
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void* GetDataTableBasePtr();
public:
// Dummy for CNetworkVars.
void NetworkStateChanged() {}
void NetworkStateChanged( void *pVar ) {}
virtual bool Init(int entnum, int iSerialNum);
virtual void Precache( void );
// For dynamic entities, return true to allow destruction
virtual bool ShouldDestroy( void ) { return false; };
C_BaseTempEntity *GetNext( void );
// Get list of tempentities
static C_BaseTempEntity *GetList( void );
C_BaseTempEntity *GetNextDynamic( void );
// Determine the color modulation amount
void GetColorModulation( float* color )
{
assert(color);
color[0] = color[1] = color[2] = 1.0f;
}
// Should this object be able to have shadows cast onto it?
virtual bool ShouldReceiveProjectedTextures( int flags ) { return false; }
// Static members
public:
// List of dynamically allocated temp entis
static C_BaseTempEntity *GetDynamicList();
// Called at startup to allow temp entities to precache any models/sounds that they need
static void PrecacheTempEnts( void );
static void ClearDynamicTempEnts( void );
static void CheckDynamicTempEnts( void );
private:
// Next in chain
C_BaseTempEntity *m_pNext;
C_BaseTempEntity *m_pNextDynamic;
// TEs add themselves to this list for the executable.
static C_BaseTempEntity *s_pTempEntities;
static C_BaseTempEntity *s_pDynamicEntities;
};
#endif // C_BASETEMPENTITY_H

411
cl_dll/c_baseviewmodel.cpp Normal file
View File

@ -0,0 +1,411 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side view model implementation. Responsible for drawing
// the view model.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseviewmodel.h"
#include "model_types.h"
#include "hud.h"
#include "view_shared.h"
#include "iviewrender.h"
#include "view.h"
#include "vmatrix.h"
#include "cl_animevent.h"
#include "eventlist.h"
#include "tools/bonelist.h"
#include <KeyValues.h>
#include "hltvcamera.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef CSTRIKE_DLL
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
#endif
void PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg );
void FormatViewModelAttachment( Vector &vOrigin, bool bInverse )
{
// Presumably, SetUpView has been called so we know our FOV and render origin.
const CViewSetup *pViewSetup = view->GetPlayerViewSetup();
float worldx = tan( pViewSetup->fov * M_PI/360.0 );
float viewx = tan( pViewSetup->fovViewmodel * M_PI/360.0 );
// aspect ratio cancels out, so only need one factor
// the difference between the screen coordinates of the 2 systems is the ratio
// of the coefficients of the projection matrices (tan (fov/2) is that coefficient)
float factorX = worldx / viewx;
float factorY = factorX;
// Get the coordinates in the viewer's space.
Vector tmp = vOrigin - pViewSetup->origin;
Vector vTransformed( MainViewRight().Dot( tmp ), MainViewUp().Dot( tmp ), MainViewForward().Dot( tmp ) );
// Now squash X and Y.
if ( bInverse )
{
if ( factorX != 0 && factorY != 0 )
{
vTransformed.x /= factorX;
vTransformed.y /= factorY;
}
else
{
vTransformed.x = 0.0f;
vTransformed.y = 0.0f;
}
}
else
{
vTransformed.x *= factorX;
vTransformed.y *= factorY;
}
// Transform back to world space.
Vector vOut = (MainViewRight() * vTransformed.x) + (MainViewUp() * vTransformed.y) + (MainViewForward() * vTransformed.z);
vOrigin = pViewSetup->origin + vOut;
}
void C_BaseViewModel::FormatViewModelAttachment( int nAttachment, Vector &vecOrigin, QAngle &angle )
{
::FormatViewModelAttachment( vecOrigin, false );
}
bool C_BaseViewModel::IsViewModel() const
{
return true;
}
void C_BaseViewModel::UncorrectViewModelAttachment( Vector &vOrigin )
{
// Unformat the attachment.
::FormatViewModelAttachment( vOrigin, true );
}
//-----------------------------------------------------------------------------
// Purpose
//-----------------------------------------------------------------------------
void C_BaseViewModel::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
// We override sound requests so that we can play them locally on the owning player
if ( ( event == AE_CL_PLAYSOUND ) || ( event == CL_EVENT_SOUND ) )
{
// Only do this if we're owned by someone
if ( GetOwner() != NULL )
{
CLocalPlayerFilter filter;
EmitSound( filter, GetOwner()->GetSoundSourceIndex(), options, &GetAbsOrigin() );
return;
}
}
// Otherwise pass the event to our associated weapon
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
if ( pWeapon )
{
bool bResult = pWeapon->OnFireEvent( this, origin, angles, event, options );
if ( !bResult )
{
BaseClass::FireEvent( origin, angles, event, options );
}
}
}
bool C_BaseViewModel::Interpolate( float currentTime )
{
CStudioHdr *pStudioHdr = GetModelPtr();
// Make sure we reset our animation information if we've switch sequences
UpdateAnimationParity();
bool bret = BaseClass::Interpolate( currentTime );
// Hack to extrapolate cycle counter for view model
float elapsed_time = currentTime - m_flAnimTime;
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
// Predicted viewmodels have fixed up interval
if ( GetPredictable() || IsClientCreated() )
{
Assert( pPlayer );
float curtime = pPlayer ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime;
elapsed_time = curtime - m_flAnimTime;
// Adjust for interpolated partial frame
elapsed_time += ( gpGlobals->interpolation_amount * TICK_INTERVAL );
}
// Prediction errors?
if ( elapsed_time < 0 )
{
elapsed_time = 0;
}
float dt = elapsed_time * GetSequenceCycleRate( pStudioHdr, GetSequence() );
if ( dt >= 1.0f )
{
if ( !IsSequenceLooping( GetSequence() ) )
{
dt = 0.999f;
}
else
{
dt = fmod( dt, 1.0f );
}
}
SetCycle( dt );
return bret;
}
inline bool C_BaseViewModel::ShouldFlipViewModel()
{
#ifdef CSTRIKE_DLL
// If cl_righthand is set, then we want them all right-handed.
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
if ( pWeapon )
{
const FileWeaponInfo_t *pInfo = &pWeapon->GetWpnData();
return pInfo->m_bAllowFlipping && pInfo->m_bBuiltRightHanded != cl_righthand.GetBool();
}
#endif
return false;
}
void C_BaseViewModel::ApplyBoneMatrixTransform( matrix3x4_t& transform )
{
if ( ShouldFlipViewModel() )
{
matrix3x4_t viewMatrix, viewMatrixInverse;
// We could get MATERIAL_VIEW here, but this is called sometimes before the renderer
// has set that matrix. Luckily, this is called AFTER the CViewSetup has been initialized.
const CViewSetup *pSetup = view->GetPlayerViewSetup();
AngleMatrix( pSetup->angles, pSetup->origin, viewMatrixInverse );
MatrixInvert( viewMatrixInverse, viewMatrix );
// Transform into view space.
matrix3x4_t temp, temp2;
ConcatTransforms( viewMatrix, transform, temp );
// Flip it along X.
// (This is the slower way to do it, and it equates to negating the top row).
//matrix3x4_t mScale;
//SetIdentityMatrix( mScale );
//mScale[0][0] = 1;
//mScale[1][1] = -1;
//mScale[2][2] = 1;
//ConcatTransforms( mScale, temp, temp2 );
temp[1][0] = -temp[1][0];
temp[1][1] = -temp[1][1];
temp[1][2] = -temp[1][2];
temp[1][3] = -temp[1][3];
// Transform back out of view space.
ConcatTransforms( viewMatrixInverse, temp, transform );
}
}
//-----------------------------------------------------------------------------
// Purpose: check if weapon viewmodel should be drawn
//-----------------------------------------------------------------------------
bool C_BaseViewModel::ShouldDraw()
{
if ( engine->IsHLTV() )
{
return ( HLTVCamera()->GetMode() == OBS_MODE_IN_EYE &&
HLTVCamera()->GetPrimaryTarget() == GetOwner() );
}
else
{
return BaseClass::ShouldDraw();
}
}
//-----------------------------------------------------------------------------
// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried
// by this player, otherwise draw the worldmodel.
//-----------------------------------------------------------------------------
int C_BaseViewModel::DrawModel( int flags )
{
if ( !m_bReadyToDraw )
return 0;
if ( flags & STUDIO_RENDER )
{
// Determine blending amount and tell engine
float blend = (float)( GetFxBlend() / 255.0f );
// Totally gone
if ( blend <= 0.0f )
return 0;
// Tell engine
render->SetBlend( blend );
float color[3];
GetColorModulation( color );
render->SetColorModulation( color );
}
if ( ShouldFlipViewModel() )
materials->CullMode( MATERIAL_CULLMODE_CW );
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
int ret;
// If the local player's overriding the viewmodel rendering, let him do it
if ( pPlayer && pPlayer->IsOverridingViewmodel() )
{
ret = pPlayer->DrawOverriddenViewmodel( this, flags );
}
else
{
ret = BaseClass::DrawModel( flags );
}
materials->CullMode( MATERIAL_CULLMODE_CCW );
// Now that we've rendered, reset the animation restart flag
if ( flags & STUDIO_RENDER )
{
if ( m_nOldAnimationParity != m_nAnimationParity )
{
m_nOldAnimationParity = m_nAnimationParity;
}
// Tell the weapon itself that we've rendered, in case it wants to do something
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
if ( pWeapon )
{
pWeapon->ViewModelDrawn( this );
}
}
return ret;
}
//-----------------------------------------------------------------------------
// Purpose: Called by the player when the player's overriding the viewmodel drawing. Avoids infinite recursion.
//-----------------------------------------------------------------------------
int C_BaseViewModel::DrawOverriddenViewmodel( int flags )
{
return BaseClass::DrawModel( flags );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int C_BaseViewModel::GetFxBlend( void )
{
// See if the local player wants to override the viewmodel's rendering
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer && pPlayer->IsOverridingViewmodel() )
{
return pPlayer->GetFxBlend();
}
return BaseClass::GetFxBlend();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseViewModel::IsTransparent( void )
{
// See if the local player wants to override the viewmodel's rendering
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer && pPlayer->IsOverridingViewmodel() )
{
return pPlayer->ViewModel_IsTransparent();
}
return BaseClass::IsTransparent();
}
//-----------------------------------------------------------------------------
// Purpose: If the animation parity of the weapon has changed, we reset cycle to avoid popping
//-----------------------------------------------------------------------------
void C_BaseViewModel::UpdateAnimationParity( void )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
// If we're predicting, then we don't use animation parity because we change the animations on the clientside
// while predicting. When not predicting, only the server changes the animations, so a parity mismatch
// tells us if we need to reset the animation.
if ( m_nOldAnimationParity != m_nAnimationParity && !GetPredictable() )
{
float curtime = (pPlayer && IsIntermediateDataAllocated()) ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime;
// FIXME: this is bad
// Simulate a networked m_flAnimTime and m_flCycle
// FIXME: Do we need the magic 0.1?
SetCycle( 0.0f ); // GetSequenceCycleRate( GetSequence() ) * 0.1;
m_flAnimTime = curtime;
}
}
//-----------------------------------------------------------------------------
// Purpose: Update global map state based on data received
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_BaseViewModel::OnDataChanged( DataUpdateType_t updateType )
{
SetPredictionEligible( true );
BaseClass::OnDataChanged(updateType);
}
void C_BaseViewModel::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate(updateType);
OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR );
}
//-----------------------------------------------------------------------------
// Purpose: Add entity to visible view models list
//-----------------------------------------------------------------------------
void C_BaseViewModel::AddEntity( void )
{
// Server says don't interpolate this frame, so set previous info to new info.
if ( IsEffectActive(EF_NOINTERP) )
{
ResetLatched();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseViewModel::GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS])
{
BaseClass::GetBoneControllers( controllers );
// Tell the weapon itself that we've rendered, in case it wants to do something
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
if ( pWeapon )
{
pWeapon->GetViewmodelBoneControllers( this, controllers );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : RenderGroup_t
//-----------------------------------------------------------------------------
RenderGroup_t C_BaseViewModel::GetRenderGroup()
{
return RENDER_GROUP_VIEW_MODEL_OPAQUE;
}

19
cl_dll/c_baseviewmodel.h Normal file
View File

@ -0,0 +1,19 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side view model implementation. Responsible for drawing
// the view model.
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASEVIEWMODEL_H
#define C_BASEVIEWMODEL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseanimating.h"
#include "UtlVector.h"
#include "baseviewmodel_shared.h"
#endif // C_BASEVIEWMODEL_H

View File

@ -0,0 +1,46 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "model_types.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "solidsetdefaults.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
#include "physics.h"
#include "c_breakableprop.h"
#include "view.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT(C_BreakableProp, DT_BreakableProp, CBreakableProp)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BreakableProp::C_BreakableProp( void )
{
m_takedamage = DAMAGE_YES;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BreakableProp::SetFadeMinMax( float fademin, float fademax )
{
m_fadeMinDist = fademin;
m_fadeMaxDist = fademax;
}
//-----------------------------------------------------------------------------
// Copy fade from another breakable prop
//-----------------------------------------------------------------------------
void C_BreakableProp::CopyFadeFrom( C_BreakableProp *pSource )
{
m_flFadeScale = pSource->m_flFadeScale;
}

30
cl_dll/c_breakableprop.h Normal file
View File

@ -0,0 +1,30 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_BREAKABLEPROP_H
#define C_BREAKABLEPROP_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BreakableProp : public C_BaseAnimating
{
typedef C_BaseAnimating BaseClass;
public:
DECLARE_CLIENTCLASS();
C_BreakableProp();
virtual void SetFadeMinMax( float fademin, float fademax );
// Copy fade from another breakable prop
void CopyFadeFrom( C_BreakableProp *pSource );
};
#endif // C_BREAKABLEPROP_H

View File

@ -0,0 +1,143 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Color correction entity with simple radial falloff
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "cbase.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "materialsystem/materialsystemutil.h"
#include "materialsystem/icolorcorrection.h"
#include "utlvector.h"
#include "generichash.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink();
private:
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_maxWeight;
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled;
ColorCorrectionHandle_t m_CCHandle;
};
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrection, DT_ColorCorrection, CColorCorrection)
RecvPropVector( RECVINFO(m_vecOrigin) ),
RecvPropFloat( RECVINFO(m_minFalloff) ),
RecvPropFloat( RECVINFO(m_maxFalloff) ),
RecvPropFloat( RECVINFO(m_maxWeight) ),
RecvPropString( RECVINFO(m_netLookupFilename) ),
RecvPropBool( RECVINFO(m_bEnabled) ),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_ColorCorrection::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged( updateType );
// We're releasing the CS:S client before the engine with this interface, so we need to fail gracefully
if ( !colorcorrection )
{
return;
}
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
char filename[MAX_PATH];
Q_strncpy( filename, m_netLookupFilename, MAX_PATH );
m_CCHandle = colorcorrection->AddLookup( filename );
colorcorrection->LockLookup( m_CCHandle );
colorcorrection->LoadLookup( m_CCHandle, filename );
colorcorrection->UnlockLookup( m_CCHandle );
}
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_ColorCorrection::ShouldDraw()
{
return false;
}
void C_ColorCorrection::ClientThink()
{
// We're releasing the CS:S client before the engine with this interface, so we need to fail gracefully
if ( !colorcorrection )
{
return;
}
if( !m_bEnabled )
{
colorcorrection->SetLookupWeight( m_CCHandle, 0.0f );
return;
}
CBaseEntity *pPlayer = UTIL_PlayerByIndex(1);
if( !pPlayer )
{
return;
}
Vector playerOrigin = pPlayer->GetAbsOrigin();
float dist = (playerOrigin - m_vecOrigin).Length();
float weight = (dist-m_minFalloff) / (m_maxFalloff-m_minFalloff);
if( weight<0.0f ) weight = 0.0f;
if( weight>1.0f ) weight = 1.0f;
colorcorrection->SetLookupWeight( m_CCHandle, m_maxWeight * (1.0f - weight) );
BaseClass::ClientThink();
}

View File

@ -0,0 +1,126 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Color correction entity.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "cbase.h"
#include "filesystem.h"
//#include "triggers.h"
#include "cdll_client_int.h"
#include "materialsystem/materialsystemutil.h"
#include "materialsystem/icolorcorrection.h"
#include "utlvector.h"
#include "generichash.h"
//#include "engine/conprint.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Purpose : Shadow control entity
//------------------------------------------------------------------------------
class C_ColorCorrectionVolume : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrectionVolume, C_BaseEntity );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink();
private:
float m_Weight;
char m_lookupFilename[MAX_PATH];
ColorCorrectionHandle_t m_CCHandle;
};
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrectionVolume, DT_ColorCorrectionVolume, CColorCorrectionVolume)
RecvPropFloat( RECVINFO(m_Weight) ),
RecvPropString( RECVINFO(m_lookupFilename) ),
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_ColorCorrectionVolume )
DEFINE_PRED_FIELD( m_Weight, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_ColorCorrectionVolume::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged( updateType );
// We're releasing the CS:S client before the engine with this interface, so we need to fail gracefully
if ( !colorcorrection )
{
return;
}
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
char filename[MAX_PATH];
Q_strncpy( filename, m_lookupFilename, MAX_PATH );
m_CCHandle = colorcorrection->AddLookup( filename );
colorcorrection->LockLookup( m_CCHandle );
colorcorrection->LoadLookup( m_CCHandle, filename );
colorcorrection->UnlockLookup( m_CCHandle );
}
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_ColorCorrectionVolume::ShouldDraw()
{
return false;
}
void C_ColorCorrectionVolume::ClientThink()
{
// We're releasing the CS:S client before the engine with this interface, so we need to fail gracefully
if ( !colorcorrection )
{
return;
}
Vector entityPosition = GetAbsOrigin();
colorcorrection->SetLookupWeight( m_CCHandle, m_Weight );
}

189
cl_dll/c_dynamiclight.cpp Normal file
View File

@ -0,0 +1,189 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Dynamic light
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "dlight.h"
#include "iefx.h"
#include "IViewRender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// A dynamic light, with the goofy hack needed for spotlights
//-----------------------------------------------------------------------------
class C_DynamicLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_DynamicLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_DynamicLight();
public:
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink( void );
unsigned char m_Flags;
unsigned char m_LightStyle;
float m_Radius;
int m_Exponent;
float m_InnerAngle;
float m_OuterAngle;
float m_SpotRadius;
private:
dlight_t* m_pDynamicLight;
dlight_t* m_pSpotlightEnd;
};
IMPLEMENT_CLIENTCLASS_DT(C_DynamicLight, DT_DynamicLight, CDynamicLight)
RecvPropInt (RECVINFO(m_Flags)),
RecvPropInt (RECVINFO(m_LightStyle)),
RecvPropFloat (RECVINFO(m_Radius)),
RecvPropInt (RECVINFO(m_Exponent)),
RecvPropFloat (RECVINFO(m_InnerAngle)),
RecvPropFloat (RECVINFO(m_OuterAngle)),
RecvPropFloat (RECVINFO(m_SpotRadius)),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
C_DynamicLight::C_DynamicLight(void) : m_pSpotlightEnd(0), m_pDynamicLight(0)
{
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void C_DynamicLight::OnDataChanged(DataUpdateType_t updateType)
{
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink(gpGlobals->curtime + 0.05);
}
BaseClass::OnDataChanged( updateType );
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
bool C_DynamicLight::ShouldDraw()
{
return false;
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void C_DynamicLight::ClientThink(void)
{
Vector forward;
AngleVectors( GetAbsAngles(), &forward );
if ( (m_Flags & DLIGHT_NO_MODEL_ILLUMINATION) == 0 )
{
// Deal with the model light
if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
{
m_pDynamicLight = effects->CL_AllocDlight( index );
Assert (m_pDynamicLight);
}
m_pDynamicLight->style = m_LightStyle;
m_pDynamicLight->radius = m_Radius;
m_pDynamicLight->flags = m_Flags;
if ( m_OuterAngle > 0 )
m_pDynamicLight->flags |= DLIGHT_NO_WORLD_ILLUMINATION;
m_pDynamicLight->color.r = m_clrRender->r;
m_pDynamicLight->color.g = m_clrRender->g;
m_pDynamicLight->color.b = m_clrRender->b;
m_pDynamicLight->color.exponent = m_Exponent; // this makes it match the world
m_pDynamicLight->origin = GetAbsOrigin();
m_pDynamicLight->m_InnerAngle = m_InnerAngle;
m_pDynamicLight->m_OuterAngle = m_OuterAngle;
m_pDynamicLight->die = gpGlobals->curtime + 1e6;
m_pDynamicLight->m_Direction = forward;
}
else
{
// In this case, the m_Flags could have changed; which is how we turn the light off
if (m_pDynamicLight)
{
m_pDynamicLight->die = gpGlobals->curtime;
m_pDynamicLight = 0;
}
}
if (( m_OuterAngle > 0 ) && ((m_Flags & DLIGHT_NO_WORLD_ILLUMINATION) == 0) )
{
// Raycast to where the endpoint goes
// Deal with the environment light
if ( !m_pSpotlightEnd || (m_pSpotlightEnd->key != -index) )
{
m_pSpotlightEnd = effects->CL_AllocDlight( -index );
Assert (m_pSpotlightEnd);
}
// Trace a line outward, don't use hitboxes (too slow)
Vector end;
VectorMA( GetAbsOrigin(), m_Radius, forward, end );
trace_t pm;
C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace
UTIL_TraceLine( GetAbsOrigin(), end, MASK_NPCWORLDSTATIC, NULL, COLLISION_GROUP_NONE, &pm );
C_BaseEntity::PopEnableAbsRecomputations();
VectorCopy( pm.endpos, m_pSpotlightEnd->origin );
if (pm.fraction == 1.0f)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
else
{
float falloff = 1.0 - pm.fraction;
falloff *= falloff;
m_pSpotlightEnd->style = m_LightStyle;
m_pSpotlightEnd->flags = DLIGHT_NO_MODEL_ILLUMINATION | (m_Flags & DLIGHT_DISPLACEMENT_MASK);
m_pSpotlightEnd->radius = m_SpotRadius; // * falloff;
m_pSpotlightEnd->die = gpGlobals->curtime + 1e6;
m_pSpotlightEnd->color.r = m_clrRender->r * falloff;
m_pSpotlightEnd->color.g = m_clrRender->g * falloff;
m_pSpotlightEnd->color.b = m_clrRender->b * falloff;
m_pSpotlightEnd->color.exponent = m_Exponent;
// For bumped lighting
m_pSpotlightEnd->m_Direction = forward;
// Update list of surfaces we influence
render->TouchLight( m_pSpotlightEnd );
}
}
else
{
// In this case, the m_Flags could have changed; which is how we turn the light off
if (m_pSpotlightEnd)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
}
SetNextClientThink(gpGlobals->curtime + 0.001);
}

2220
cl_dll/c_effects.cpp Normal file

File diff suppressed because it is too large Load Diff

18
cl_dll/c_effects.h Normal file
View File

@ -0,0 +1,18 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_EFFECTS_H
#define C_EFFECTS_H
#ifdef _WIN32
#pragma once
#endif
// Draw rain effects.
void DrawPrecipitation();
#endif // C_EFFECTS_H

773
cl_dll/c_entitydissolve.cpp Normal file
View File

@ -0,0 +1,773 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "IViewRender.h"
#include "view.h"
#include "studio.h"
#include "bone_setup.h"
#include "model_types.h"
#include "beamdraw.h"
#include "engine/ivdebugoverlay.h"
#include "iviewrender_beams.h"
#include "fx.h"
#include "IEffects.h"
#include "c_entitydissolve.h"
#include "movevars_shared.h"
#include "ClientEffectPrecacheSystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectBuild )
CLIENTEFFECT_MATERIAL( "effects/tesla_glow_noz" )
CLIENTEFFECT_MATERIAL( "effects/spark" )
CLIENTEFFECT_MATERIAL( "effects/combinemuzzle2" )
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityDissolve, DT_EntityDissolve, CEntityDissolve )
RecvPropTime(RECVINFO(m_flStartTime)),
RecvPropFloat(RECVINFO(m_flFadeOutStart)),
RecvPropFloat(RECVINFO(m_flFadeOutLength)),
RecvPropFloat(RECVINFO(m_flFadeOutModelStart)),
RecvPropFloat(RECVINFO(m_flFadeOutModelLength)),
RecvPropFloat(RECVINFO(m_flFadeInStart)),
RecvPropFloat(RECVINFO(m_flFadeInLength)),
RecvPropInt(RECVINFO(m_nDissolveType)),
RecvPropVector( RECVINFO( m_vDissolverOrigin) ),
RecvPropInt( RECVINFO( m_nMagnitude ) ),
END_RECV_TABLE()
extern PMaterialHandle g_Material_Spark;
PMaterialHandle g_Material_AR2Glow = NULL;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityDissolve::C_EntityDissolve( void )
{
m_bLinkedToServerEnt = true;
m_pController = false;
m_bCoreExplode = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
if ( GetMoveParent() )
{
GetMoveParent()->GetRenderBounds( theMins, theMaxs );
}
else
{
theMins = GetAbsOrigin();
theMaxs = theMaxs;
}
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityDissolve::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
m_flNextSparkTime = m_flStartTime;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Cleanup
//-----------------------------------------------------------------------------
void C_EntityDissolve::UpdateOnRemove( void )
{
if ( m_pController )
{
physenv->DestroyMotionController( m_pController );
m_pController = NULL;
}
BaseClass::UpdateOnRemove();
}
//------------------------------------------------------------------------------
// Apply the forces to the entity
//------------------------------------------------------------------------------
IMotionEvent::simresult_e C_EntityDissolve::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
{
linear.Init();
angular.Init();
// Make it zero g
linear.z -= -1.02 * sv_gravity.GetFloat();
Vector vel;
AngularImpulse angVel;
pObject->GetVelocity( &vel, &angVel );
vel += linear * deltaTime; // account for gravity scale
Vector unitVel = vel;
Vector unitAngVel = angVel;
float speed = VectorNormalize( unitVel );
// float angSpeed = VectorNormalize( unitAngVel );
// float speedScale = 0.0;
// float angSpeedScale = 0.0;
float flLinearLimit = 50;
float flLinearLimitDelta = 40;
if ( speed > flLinearLimit )
{
float flDeltaVel = (flLinearLimit - speed) / deltaTime;
if ( flLinearLimitDelta != 0.0f )
{
float flMaxDeltaVel = -flLinearLimitDelta / deltaTime;
if ( flDeltaVel < flMaxDeltaVel )
{
flDeltaVel = flMaxDeltaVel;
}
}
VectorMA( linear, flDeltaVel, unitVel, linear );
}
return SIM_GLOBAL_ACCELERATION;
}
//-----------------------------------------------------------------------------
// Tesla effect
//-----------------------------------------------------------------------------
static void FX_BuildTesla( C_BaseEntity *pEntity, Vector &vecOrigin, Vector &vecEnd )
{
BeamInfo_t beamInfo;
beamInfo.m_pStartEnt = pEntity;
beamInfo.m_nStartAttachment = 0;
beamInfo.m_pEndEnt = NULL;
beamInfo.m_nEndAttachment = 0;
beamInfo.m_nType = TE_BEAMTESLA;
beamInfo.m_vecStart = vecOrigin;
beamInfo.m_vecEnd = vecEnd;
beamInfo.m_pszModelName = "sprites/lgtning.vmt";
beamInfo.m_flHaloScale = 0.0;
beamInfo.m_flLife = random->RandomFloat( 0.25f, 1.0f );
beamInfo.m_flWidth = random->RandomFloat( 8.0f, 14.0f );
beamInfo.m_flEndWidth = 1.0f;
beamInfo.m_flFadeLength = 0.5f;
beamInfo.m_flAmplitude = 24;
beamInfo.m_flBrightness = 255.0;
beamInfo.m_flSpeed = 150.0f;
beamInfo.m_nStartFrame = 0.0;
beamInfo.m_flFrameRate = 30.0;
beamInfo.m_flRed = 255.0;
beamInfo.m_flGreen = 255.0;
beamInfo.m_flBlue = 255.0;
beamInfo.m_nSegments = 18;
beamInfo.m_bRenderable = true;
beamInfo.m_nFlags = 0; //FBEAM_ONLYNOISEONCE;
beams->CreateBeamEntPoint( beamInfo );
}
//-----------------------------------------------------------------------------
// Purpose: Tesla effect
//-----------------------------------------------------------------------------
void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset )
{
Vector vecOrigin;
QAngle vecAngles;
MatrixGetColumn( hitboxToWorld, 3, vecOrigin );
MatrixAngles( hitboxToWorld, vecAngles.Base() );
C_BaseEntity *pEntity = GetMoveParent();
// Make a couple of tries at it
int iTries = -1;
Vector vecForward;
trace_t tr;
do
{
iTries++;
// Some beams are deliberatly aimed around the point, the rest are random.
if ( !bRandom )
{
QAngle vecTemp = vecAngles;
vecTemp[YAW] += flYawOffset;
AngleVectors( vecTemp, &vecForward );
// Randomly angle it up or down
vecForward.z = RandomFloat( -1, 1 );
}
else
{
vecForward = RandomVector( -1, 1 );
}
UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr );
} while ( tr.fraction >= 1.0 && iTries < 3 );
Vector vecEnd = tr.endpos - (vecForward * 8);
// Only spark & glow if we hit something
if ( tr.fraction < 1.0 )
{
if ( !EffectOccluded( tr.endpos ) )
{
// Move it towards the camera
Vector vecFlash = tr.endpos;
Vector vecForward;
AngleVectors( MainViewAngles(), &vecForward );
vecFlash -= (vecForward * 8);
g_pEffects->EnergySplash( vecFlash, -vecForward, false );
// End glow
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
pSimple->SetSortOrigin( vecFlash );
SimpleParticle *pParticle;
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash );
if ( pParticle != NULL )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = RandomFloat( 0.5, 1 );
pParticle->m_vecVelocity = vec3_origin;
Vector color( 1,1,1 );
float colorRamp = RandomFloat( 0.75f, 1.25f );
pParticle->m_uchColor[0] = min( 1.0f, color[0] * colorRamp ) * 255.0f;
pParticle->m_uchColor[1] = min( 1.0f, color[1] * colorRamp ) * 255.0f;
pParticle->m_uchColor[2] = min( 1.0f, color[2] * colorRamp ) * 255.0f;
pParticle->m_uchStartSize = RandomFloat( 6,13 );
pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 10;
pParticle->m_flRoll = RandomFloat( 0,360 );
pParticle->m_flRollDelta = 0;
}
}
}
// Build the tesla
FX_BuildTesla( pEntity, vecOrigin, tr.endpos );
}
//-----------------------------------------------------------------------------
// Sorts the components of a vector
//-----------------------------------------------------------------------------
static inline void SortAbsVectorComponents( const Vector& src, int* pVecIdx )
{
Vector absVec( fabs(src[0]), fabs(src[1]), fabs(src[2]) );
int maxIdx = (absVec[0] > absVec[1]) ? 0 : 1;
if (absVec[2] > absVec[maxIdx])
{
maxIdx = 2;
}
// always choose something right-handed....
switch( maxIdx )
{
case 0:
pVecIdx[0] = 1;
pVecIdx[1] = 2;
pVecIdx[2] = 0;
break;
case 1:
pVecIdx[0] = 2;
pVecIdx[1] = 0;
pVecIdx[2] = 1;
break;
case 2:
pVecIdx[0] = 0;
pVecIdx[1] = 1;
pVecIdx[2] = 2;
break;
}
}
//-----------------------------------------------------------------------------
// Compute the bounding box's center, size, and basis
//-----------------------------------------------------------------------------
void C_EntityDissolve::ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec )
{
// Compute the center of the hitbox in worldspace
Vector vecHitboxCenter;
VectorAdd( pHitBox->bbmin, pHitBox->bbmax, vecHitboxCenter );
vecHitboxCenter *= 0.5f;
VectorTransform( vecHitboxCenter, hitboxToWorld, *pVecAbsOrigin );
// Get the object's basis
Vector vec[3];
MatrixGetColumn( hitboxToWorld, 0, vec[0] );
MatrixGetColumn( hitboxToWorld, 1, vec[1] );
MatrixGetColumn( hitboxToWorld, 2, vec[2] );
// vec[1] *= -1.0f;
Vector vecViewDir;
VectorSubtract( CurrentViewOrigin(), *pVecAbsOrigin, vecViewDir );
VectorNormalize( vecViewDir );
// Project the shadow casting direction into the space of the hitbox
Vector localViewDir;
localViewDir[0] = DotProduct( vec[0], vecViewDir );
localViewDir[1] = DotProduct( vec[1], vecViewDir );
localViewDir[2] = DotProduct( vec[2], vecViewDir );
// Figure out which vector has the largest component perpendicular
// to the view direction...
// Sort by how perpendicular it is
int vecIdx[3];
SortAbsVectorComponents( localViewDir, vecIdx );
// Here's our hitbox basis vectors; namely the ones that are
// most perpendicular to the view direction
*pXVec = vec[vecIdx[0]];
*pYVec = vec[vecIdx[1]];
// Project them into a plane perpendicular to the view direction
*pXVec -= vecViewDir * DotProduct( vecViewDir, *pXVec );
*pYVec -= vecViewDir * DotProduct( vecViewDir, *pYVec );
VectorNormalize( *pXVec );
VectorNormalize( *pYVec );
// Compute the hitbox size
Vector boxSize;
VectorSubtract( pHitBox->bbmax, pHitBox->bbmin, boxSize );
// We project the two longest sides into the vectors perpendicular
// to the projection direction, then add in the projection of the perp direction
Vector2D size( boxSize[vecIdx[0]], boxSize[vecIdx[1]] );
size.x *= fabs( DotProduct( vec[vecIdx[0]], *pXVec ) );
size.y *= fabs( DotProduct( vec[vecIdx[1]], *pYVec ) );
// Add the third component into x and y
size.x += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pXVec ) );
size.y += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pYVec ) );
// Bloat a bit, since the shadow wants to extend outside the model a bit
size *= 2.0f;
// Clamp the minimum size
Vector2DMax( size, Vector2D(10.0f, 10.0f), size );
// Factor the size into the xvec + yvec
(*pXVec) *= size.x * 0.5f;
(*pYVec) *= size.y * 0.5f;
}
//-----------------------------------------------------------------------------
// Sparks!
//-----------------------------------------------------------------------------
void C_EntityDissolve::DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] )
{
if ( m_flNextSparkTime > gpGlobals->curtime )
return;
float dt = m_flStartTime + m_flFadeOutStart - gpGlobals->curtime;
dt = clamp( dt, 0.0f, m_flFadeOutStart );
float flNextTime;
if (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL)
{
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 2.0f * TICK_INTERVAL, 0.4f );
}
else
{
// m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT);
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 0.3f, 1.0f );
}
m_flNextSparkTime = gpGlobals->curtime + flNextTime;
// Send out beams around us
int iNumBeamsAround = 2;
int iNumRandomBeams = 1;
int iTotalBeams = iNumBeamsAround + iNumRandomBeams;
float flYawOffset = RandomFloat(0,360);
for ( int i = 0; i < iTotalBeams; i++ )
{
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
float flActualYawOffset = 0;
bool bRandom = ( i >= iNumBeamsAround );
if ( !bRandom )
{
flActualYawOffset = anglemod( flYawOffset + ((360 / iTotalBeams) * i) );
}
BuildTeslaEffect( pBox, *hitboxbones[pBox->bone], bRandom, flActualYawOffset );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::SetupEmitter( void )
{
if ( !m_pEmitter )
{
m_pEmitter = CSimpleEmitter::Create( "C_EntityDissolve" );
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetFadeInPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt > m_flFadeOutStart )
return 1.0f;
if ( dt < m_flFadeInStart )
return 0.0f;
if ( (dt > m_flFadeInStart) && (dt < m_flFadeInStart + m_flFadeInLength) )
{
dt -= m_flFadeInStart;
return ( dt / m_flFadeInLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetFadeOutPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt < m_flFadeInStart )
return 1.0f;
if ( dt > m_flFadeOutStart )
{
dt -= m_flFadeOutStart;
if ( dt > m_flFadeOutLength )
return 0.0f;
return 1.0f - ( dt / m_flFadeOutLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetModelFadeOutPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt < m_flFadeOutModelStart )
return 1.0f;
if ( dt > m_flFadeOutModelStart )
{
dt -= m_flFadeOutModelStart;
if ( dt > m_flFadeOutModelLength )
return 0.0f;
return 1.0f - ( dt / m_flFadeOutModelLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::ClientThink( void )
{
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if (!pAnimating)
return;
// NOTE: IsRagdoll means *client-side* ragdoll. We shouldn't be trying to fight
// the server ragdoll (or any server physics) on the client
if (( !m_pController ) && ( m_nDissolveType == ENTITY_DISSOLVE_NORMAL ) && pAnimating->IsRagdoll())
{
IPhysicsObject *ppList[32];
int nCount = pAnimating->VPhysicsGetObjectList( ppList, 32 );
if ( nCount > 0 )
{
m_pController = physenv->CreateMotionController( this );
for ( int i = 0; i < nCount; ++i )
{
m_pController->AttachObject( ppList[i], true );
}
}
}
color32 color;
color.r = color.g = color.b = ( 1.0f - GetFadeInPercentage() ) * 255.0f;
color.a = GetModelFadeOutPercentage() * 255.0f;
// Setup the entity fade
pAnimating->SetRenderMode( kRenderTransColor );
pAnimating->SetRenderColor( color.r, color.g, color.b, color.a );
if ( GetModelFadeOutPercentage() <= 0.2f )
{
m_bCoreExplode = true;
}
// If we're dead, fade out
if ( GetFadeOutPercentage() <= 0.0f )
{
// Do NOT remove from the client entity list. It'll confuse the local network backdoor, and the entity will never get destroyed
// because when the server says to destroy it, the client won't be able to find it.
// ClientEntityList().RemoveEntity( GetClientHandle() );
partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
RemoveFromLeafSystem();
//FIXME: Ick!
//Adrian: I'll assume we don't need the ragdoll either so I'll remove that too.
if ( m_bLinkedToServerEnt == false )
{
Release();
C_ClientRagdoll *pRagdoll = dynamic_cast <C_ClientRagdoll *> ( pAnimating );
if ( pRagdoll )
{
pRagdoll->ReleaseRagdoll();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_EntityDissolve::DrawModel( int flags )
{
// See if we should draw
if ( gpGlobals->frametime == 0 || m_bReadyToDraw == false )
return 0;
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if ( pAnimating == NULL )
return 0;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) == false )
return 0;
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if ( pStudioHdr == NULL )
return false;
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
if ( set == NULL )
return false;
// Make sure the emitter is setup properly
SetupEmitter();
// Get fade percentages for the effect
float fadeInPerc = GetFadeInPercentage();
float fadeOutPerc = GetFadeOutPercentage();
float fadePerc = ( fadeInPerc >= 1.0f ) ? fadeOutPerc : fadeInPerc;
Vector vecSkew = vec3_origin;
// Do extra effects under certain circumstances
if ( ( fadePerc < 0.99f ) && ( (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) )
{
DoSparks( set, hitboxbones );
}
// Skew the particles in front or in back of their targets
vecSkew = CurrentViewForward() * ( 8.0f - ( ( 1.0f - fadePerc ) * 32.0f ) );
float spriteScale = ( ( gpGlobals->curtime - m_flStartTime ) / m_flFadeOutLength );
spriteScale = clamp( spriteScale, 0.75f, 1.0f );
// Cache off this material reference
if ( g_Material_Spark == NULL )
{
g_Material_Spark = ParticleMgr()->GetPMaterial( "effects/spark" );
}
if ( g_Material_AR2Glow == NULL )
{
g_Material_AR2Glow = ParticleMgr()->GetPMaterial( "effects/combinemuzzle2" );
}
SimpleParticle *sParticle;
for ( int i = 0; i < set->numhitboxes; ++i )
{
Vector vecAbsOrigin, xvec, yvec;
mstudiobbox_t *pBox = set->pHitbox(i);
ComputeRenderInfo( pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec );
Vector offset;
Vector xDir, yDir;
xDir = xvec;
float xScale = VectorNormalize( xDir ) * 0.75f;
yDir = yvec;
float yScale = VectorNormalize( yDir ) * 0.75f;
int numParticles = clamp( 3.0f * fadePerc, 0, 3 );
int iTempParts = 2;
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
numParticles = 15;
iTempParts = 20;
}
}
for ( int j = 0; j < iTempParts; j++ )
{
// Skew the origin
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
offset += vecSkew;
if ( random->RandomInt( 0, 2 ) != 0 )
continue;
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), g_Material_Spark, vecAbsOrigin + offset );
if ( sParticle == NULL )
return 1;
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 16.0f, 64.0f ) );
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
Vector vDirection = (vecAbsOrigin + offset) - m_vDissolverOrigin;
VectorNormalize( vDirection );
sParticle->m_vecVelocity = vDirection * m_nMagnitude;
}
}
if ( sParticle->m_vecVelocity.z > 0 )
{
sParticle->m_uchStartSize = random->RandomFloat( 4, 6 ) * spriteScale;
}
else
{
sParticle->m_uchStartSize = 2 * spriteScale;
}
sParticle->m_flDieTime = random->RandomFloat( 0.4f, 0.5f );
// If we're the last particles, last longer
if ( numParticles == 0 )
{
sParticle->m_flDieTime *= 2.0f;
sParticle->m_uchStartSize = 2 * spriteScale;
sParticle->m_flRollDelta = Helper_RandomFloat( -4.0f, 4.0f );
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
sParticle->m_flDieTime *= 2.0f;
sParticle->m_flRollDelta = Helper_RandomFloat( -1.0f, 1.0f );
}
}
}
else
{
sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f, 8.0f );
}
sParticle->m_flLifetime = 0.0f;
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
float alpha = 255;
sParticle->m_uchColor[0] = alpha;
sParticle->m_uchColor[1] = alpha;
sParticle->m_uchColor[2] = alpha;
sParticle->m_uchStartAlpha = alpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
}
for ( int j = 0; j < numParticles; j++ )
{
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
offset += vecSkew;
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), g_Material_AR2Glow, vecAbsOrigin + offset );
if ( sParticle == NULL )
return 1;
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -64.0f, 128.0f ) );
sParticle->m_uchStartSize = random->RandomFloat( 8, 12 ) * spriteScale;
sParticle->m_flDieTime = 0.1f;
sParticle->m_flLifetime = 0.0f;
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
sParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
float alpha = 255;
sParticle->m_uchColor[0] = alpha;
sParticle->m_uchColor[1] = alpha;
sParticle->m_uchColor[2] = alpha;
sParticle->m_uchStartAlpha = alpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
Vector vDirection = (vecAbsOrigin + offset) - m_vDissolverOrigin;
VectorNormalize( vDirection );
sParticle->m_vecVelocity = vDirection * m_nMagnitude;
sParticle->m_flDieTime = 0.5f;
}
}
}
}
return 1;
}

77
cl_dll/c_entitydissolve.h Normal file
View File

@ -0,0 +1,77 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENTITY_DISSOLVE_H
#define C_ENTITY_DISSOLVE_H
#include "cbase.h"
//-----------------------------------------------------------------------------
// Entity Dissolve, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityDissolve : public C_BaseEntity, public IMotionEvent
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityDissolve, C_BaseEntity );
C_EntityDissolve( void );
// Inherited from C_BaseEntity
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual int DrawModel( int flags );
virtual bool ShouldDraw() { return true; }
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void UpdateOnRemove( void );
// Inherited from IMotionEvent
virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular );
void SetupEmitter( void );
void ClientThink( void );
void SetServerLinkState( bool state ) { m_bLinkedToServerEnt = state; }
float m_flStartTime;
float m_flFadeOutStart;
float m_flFadeOutLength;
float m_flFadeOutModelStart;
float m_flFadeOutModelLength;
float m_flFadeInStart;
float m_flFadeInLength;
int m_nDissolveType;
float m_flNextSparkTime;
Vector m_vDissolverOrigin;
int m_nMagnitude;
bool m_bCoreExplode;
protected:
float GetFadeInPercentage( void ); // Fade in amount (entity fading to black)
float GetFadeOutPercentage( void ); // Fade out amount (particles fading away)
float GetModelFadeOutPercentage( void );// Mode fade out amount
// Compute the bounding box's center, size, and basis
void ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec );
void BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset );
void DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] );
private:
CSmartPtr<CSimpleEmitter> m_pEmitter;
bool m_bLinkedToServerEnt;
IPhysicsMotionController *m_pController;
};
#endif // C_ENTITY_DISSOLVE_H

View File

@ -0,0 +1,250 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseparticleentity.h"
#include "entityparticletrail_shared.h"
#include "particlemgr.h"
#include "particle_util.h"
#include "particles_simple.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Entity particle trail, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityParticleTrail : public C_BaseParticleEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityParticleTrail, C_BaseParticleEntity );
C_EntityParticleTrail( );
~C_EntityParticleTrail( );
// C_BaseEntity
virtual void OnDataChanged( DataUpdateType_t updateType );
// IParticleEffect
void Update( float fTimeDelta );
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
private:
C_EntityParticleTrail( const C_EntityParticleTrail & ); // not defined, not accessible
void Start( );
void AddParticle( float flInitialDeltaTime, const Vector &vecMins, const Vector &vecMaxs, const matrix3x4_t &boxToWorld );
int m_iMaterialName;
EntityParticleTrailInfo_t m_Info;
EHANDLE m_hConstraintEntity;
PMaterialHandle m_hMaterial;
TimedEvent m_teParticleSpawn;
};
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityParticleTrail, DT_EntityParticleTrail, CEntityParticleTrail )
RecvPropInt(RECVINFO(m_iMaterialName)),
RecvPropDataTable( RECVINFO_DT( m_Info ), 0, &REFERENCE_RECV_TABLE(DT_EntityParticleTrailInfo) ),
RecvPropEHandle(RECVINFO(m_hConstraintEntity)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityParticleTrail::C_EntityParticleTrail( void )
{
}
C_EntityParticleTrail::~C_EntityParticleTrail()
{
ParticleMgr()->RemoveEffect( &m_ParticleEffect );
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
Start( );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::Start( )
{
if( ParticleMgr()->AddEffect( &m_ParticleEffect, this ) == false )
return;
const char *pMaterialName = GetMaterialNameFromIndex( m_iMaterialName );
if ( !pMaterialName )
return;
m_hMaterial = ParticleMgr()->GetPMaterial( pMaterialName );
m_teParticleSpawn.Init( 150 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::AddParticle( float flInitialDeltaTime, const Vector &vecMins, const Vector &vecMaxs, const matrix3x4_t &boxToWorld )
{
// Select a random point somewhere in the hitboxes of the entity.
Vector vecLocalPosition, vecWorldPosition;
vecLocalPosition.x = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.x, vecMaxs.x );
vecLocalPosition.y = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.y, vecMaxs.y );
vecLocalPosition.z = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.z, vecMaxs.z );
VectorTransform( vecLocalPosition, boxToWorld, vecWorldPosition );
// Don't emit the particle unless it's inside the model
if ( m_hConstraintEntity.Get() )
{
Ray_t ray;
trace_t tr;
ray.Init( vecWorldPosition, vecWorldPosition );
enginetrace->ClipRayToEntity( ray, MASK_ALL, m_hConstraintEntity, &tr );
if ( !tr.startsolid )
return;
}
// Make a new particle
SimpleParticle *pParticle = (SimpleParticle *)m_ParticleEffect.AddParticle( sizeof(SimpleParticle), m_hMaterial );
if ( pParticle == NULL )
return;
pParticle->m_Pos = vecWorldPosition;
pParticle->m_flRoll = Helper_RandomInt( 0, 360 );
pParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
pParticle->m_flLifetime = flInitialDeltaTime;
pParticle->m_flDieTime = m_Info.m_flLifetime;
pParticle->m_uchColor[0] = 64;
pParticle->m_uchColor[1] = 140;
pParticle->m_uchColor[2] = 225;
pParticle->m_uchStartAlpha = Helper_RandomInt( 64, 64 );
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = m_Info.m_flStartSize;
pParticle->m_uchEndSize = m_Info.m_flEndSize;
pParticle->m_vecVelocity = vec3_origin;
VectorMA( pParticle->m_Pos, flInitialDeltaTime, pParticle->m_vecVelocity, pParticle->m_Pos );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::Update( float fTimeDelta )
{
float tempDelta = fTimeDelta;
studiohdr_t *pStudioHdr;
mstudiohitboxset_t *set;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
C_BaseEntity *pMoveParent = GetMoveParent();
if ( !pMoveParent )
return;
C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
if (!pAnimating)
goto trailNoHitboxes;
if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) )
goto trailNoHitboxes;
pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if (!pStudioHdr)
goto trailNoHitboxes;
set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
if ( !set )
goto trailNoHitboxes;
//Add new particles
while ( m_teParticleSpawn.NextEvent( tempDelta ) )
{
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
AddParticle( tempDelta, pBox->bbmin, pBox->bbmax, *hitboxbones[pBox->bone] );
}
return;
trailNoHitboxes:
while ( m_teParticleSpawn.NextEvent( tempDelta ) )
{
AddParticle( tempDelta, pMoveParent->CollisionProp()->OBBMins(), pMoveParent->CollisionProp()->OBBMaxs(), pMoveParent->EntityToWorldTransform() );
}
}
inline void C_EntityParticleTrail::RenderParticles( CParticleRenderIterator *pIterator )
{
const SimpleParticle *pParticle = (const SimpleParticle*)pIterator->GetFirst();
while ( pParticle )
{
float t = pParticle->m_flLifetime / pParticle->m_flDieTime;
// Render
Vector tPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
float sortKey = tPos.z;
Vector color = Vector( pParticle->m_uchColor[0] / 255.0f, pParticle->m_uchColor[1] / 255.0f, pParticle->m_uchColor[2] / 255.0f );
float alpha = Lerp( t, pParticle->m_uchStartAlpha / 255.0f, pParticle->m_uchEndAlpha / 255.0f );
float flSize = Lerp( t, pParticle->m_uchStartSize, pParticle->m_uchEndSize );
// Render it
RenderParticle_ColorSize( pIterator->GetParticleDraw(), tPos, color, alpha, flSize );
pParticle = (const SimpleParticle*)pIterator->GetNext( sortKey );
}
}
inline void C_EntityParticleTrail::SimulateParticles( CParticleSimulateIterator *pIterator )
{
SimpleParticle *pParticle = (SimpleParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Update position
float flTimeDelta = pIterator->GetTimeDelta();
pParticle->m_Pos += pParticle->m_vecVelocity * flTimeDelta;
// NOTE: I'm overloading "die time" to be the actual start time.
pParticle->m_flLifetime += flTimeDelta;
if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
pIterator->RemoveParticle( pParticle );
pParticle = (SimpleParticle*)pIterator->GetNext();
}
}

View File

@ -0,0 +1,304 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_baseanimating.h"
#include "particlemgr.h"
#include "materialsystem/imaterialvar.h"
#include "cl_animevent.h"
#include "particle_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// An entity which emits other entities at points
//-----------------------------------------------------------------------------
class C_EnvParticleScript : public C_BaseAnimating, public IParticleEffect
{
public:
DECLARE_CLASS( C_EnvParticleScript, C_BaseAnimating );
DECLARE_CLIENTCLASS();
C_EnvParticleScript();
// IParticleEffect overrides.
public:
virtual bool ShouldSimulate() const { return m_bSimulate; }
virtual void SetShouldSimulate( bool bSim ) { m_bSimulate = bSim; }
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
virtual const Vector &GetSortOrigin();
// C_BaseAnimating overrides
public:
// NOTE: Ths enclosed particle effect binding will do all the drawing
// But we have to return true, unlike other particle systems, for the animation events to work
virtual bool ShouldDraw() { return true; }
virtual int DrawModel( int flags ) { return 0; }
virtual int GetFxBlend( void ) { return 0; }
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
// Creates, destroys particles attached to an attachment
void CreateParticle( const char *pAttachmentName, const char *pSpriteName );
void DestroyAllParticles( const char *pAttachmentName );
void DestroyAllParticles( );
private:
struct ParticleScriptParticle_t : public Particle
{
int m_nAttachment;
float m_flSize;
};
CParticleEffectBinding m_ParticleEffect;
float m_flMaxParticleSize;
int m_nOldSequence;
float m_flSequenceScale;
bool m_bSimulate;
};
REGISTER_EFFECT( C_EnvParticleScript );
//-----------------------------------------------------------------------------
// Datatable
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EnvParticleScript, DT_EnvParticleScript, CEnvParticleScript )
RecvPropFloat( RECVINFO(m_flSequenceScale) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
C_EnvParticleScript::C_EnvParticleScript()
{
m_flMaxParticleSize = 0.0f;
m_bSimulate = true;
}
//-----------------------------------------------------------------------------
// Check for changed sequence numbers
//-----------------------------------------------------------------------------
void C_EnvParticleScript::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_nOldSequence = GetSequence();
}
//-----------------------------------------------------------------------------
// Starts up the particle system
//-----------------------------------------------------------------------------
void C_EnvParticleScript::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if(updateType == DATA_UPDATE_CREATED)
{
ParticleMgr()->AddEffect( &m_ParticleEffect, this );
}
if ( m_nOldSequence != GetSequence() )
{
DestroyAllParticles();
}
}
//-----------------------------------------------------------------------------
// Creates, destroys particles attached to an attachment
//-----------------------------------------------------------------------------
void C_EnvParticleScript::CreateParticle( const char *pAttachmentName, const char *pSpriteName )
{
// Find the attachment
int nAttachment = LookupAttachment( pAttachmentName );
if ( nAttachment <= 0 )
return;
// Get the sprite materials
PMaterialHandle hMat = m_ParticleEffect.FindOrAddMaterial( pSpriteName );
ParticleScriptParticle_t *pParticle =
(ParticleScriptParticle_t*)m_ParticleEffect.AddParticle(sizeof(ParticleScriptParticle_t), hMat);
if ( pParticle == NULL )
return;
// Get the sprite size from the material's materialvars
bool bFound = false;
IMaterialVar *pMaterialVar = NULL;
IMaterial *pMaterial = ParticleMgr()->PMaterialToIMaterial( hMat );
if ( pMaterial )
{
pMaterialVar = pMaterial->FindVar( "$spritesize", &bFound, false );
}
if ( bFound )
{
pParticle->m_flSize = pMaterialVar->GetFloatValue();
}
else
{
pParticle->m_flSize = 100.0f;
}
// Make sure the particle cull size reflects our particles
if ( pParticle->m_flSize > m_flMaxParticleSize )
{
m_flMaxParticleSize = pParticle->m_flSize;
m_ParticleEffect.SetParticleCullRadius( m_flMaxParticleSize );
}
// Place the particle on the attachment specified
pParticle->m_nAttachment = nAttachment;
QAngle vecAngles;
GetAttachment( nAttachment, pParticle->m_Pos, vecAngles );
if ( m_flSequenceScale != 1.0f )
{
pParticle->m_Pos -= GetAbsOrigin();
pParticle->m_Pos *= m_flSequenceScale;
pParticle->m_Pos += GetAbsOrigin();
}
}
void C_EnvParticleScript::DestroyAllParticles( const char *pAttachmentName )
{
int nAttachment = LookupAttachment( pAttachmentName );
if ( nAttachment <= 0 )
return;
int nCount = m_ParticleEffect.GetNumActiveParticles();
Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) );
int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles );
Assert( nActualCount == nCount );
for ( int i = 0; i < nActualCount; ++i )
{
ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i];
if ( pParticle->m_nAttachment == nAttachment )
{
// Mark for deletion
pParticle->m_nAttachment = -1;
}
}
}
void C_EnvParticleScript::DestroyAllParticles( )
{
int nCount = m_ParticleEffect.GetNumActiveParticles();
Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) );
int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles );
Assert( nActualCount == nCount );
for ( int i = 0; i < nActualCount; ++i )
{
ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i];
// Mark for deletion
pParticle->m_nAttachment = -1;
}
}
//-----------------------------------------------------------------------------
// The animation events will create particles on the attachment points
//-----------------------------------------------------------------------------
void C_EnvParticleScript::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
// Handle events to create + destroy particles
switch( event )
{
case CL_EVENT_SPRITEGROUP_CREATE:
{
char pAttachmentName[256];
char pSpriteName[256];
int nArgs = sscanf( options, "%255s %255s", pAttachmentName, pSpriteName );
if ( nArgs == 2 )
{
CreateParticle( pAttachmentName, pSpriteName );
}
}
return;
case CL_EVENT_SPRITEGROUP_DESTROY:
{
char pAttachmentName[256];
int nArgs = sscanf( options, "%255s", pAttachmentName );
if ( nArgs == 1 )
{
DestroyAllParticles( pAttachmentName );
}
}
return;
}
// Fall back
BaseClass::FireEvent( origin, angles, event, options );
}
//-----------------------------------------------------------------------------
// Simulate the particles
//-----------------------------------------------------------------------------
void C_EnvParticleScript::RenderParticles( CParticleRenderIterator *pIterator )
{
const ParticleScriptParticle_t* pParticle = (const ParticleScriptParticle_t*)pIterator->GetFirst();
while ( pParticle )
{
Vector vecRenderPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, vecRenderPos );
float sortKey = vecRenderPos.z;
Vector color( 1, 1, 1 );
RenderParticle_ColorSize( pIterator->GetParticleDraw(), vecRenderPos, color, 1.0f, pParticle->m_flSize );
pParticle = (const ParticleScriptParticle_t*)pIterator->GetNext( sortKey );
}
}
void C_EnvParticleScript::SimulateParticles( CParticleSimulateIterator *pIterator )
{
ParticleScriptParticle_t* pParticle = (ParticleScriptParticle_t*)pIterator->GetFirst();
while ( pParticle )
{
// Here's how we retire particles
if ( pParticle->m_nAttachment == -1 )
{
pIterator->RemoveParticle( pParticle );
}
else
{
// Move the particle to the attachment point
QAngle vecAngles;
GetAttachment( pParticle->m_nAttachment, pParticle->m_Pos, vecAngles );
if ( m_flSequenceScale != 1.0f )
{
pParticle->m_Pos -= GetAbsOrigin();
pParticle->m_Pos *= m_flSequenceScale;
pParticle->m_Pos += GetAbsOrigin();
}
}
pParticle = (ParticleScriptParticle_t*)pIterator->GetNext();
}
}
const Vector &C_EnvParticleScript::GetSortOrigin()
{
return GetAbsOrigin();
}

View File

@ -0,0 +1,197 @@
//====== Copyright © 1996-2003, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "shareddefs.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "view.h"
#include "iviewrender.h"
#include "view_shared.h"
#include "texture_group_names.h"
#include "vstdlib/icommandline.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvProjectedTexture : public C_BaseEntity
{
DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
virtual void OnDataChanged( DataUpdateType_t updateType );
void ShutDownLightHandle( void );
virtual void Simulate();
void UpdateLight( bool bForceUpdate );
C_EnvProjectedTexture();
~C_EnvProjectedTexture();
private:
ClientShadowHandle_t m_LightHandle;
EHANDLE m_hTargetEntity;
bool m_bState;
float m_flLightFOV;
bool m_bEnableShadows;
bool m_bLightOnlyTarget;
bool m_bLightWorld;
bool m_bCameraSpace;
color32 m_cLightColor;
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
RecvPropBool( RECVINFO( m_bState ) ),
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
RecvPropBool( RECVINFO( m_bLightWorld ) ),
RecvPropBool( RECVINFO( m_bCameraSpace ) ),
RecvPropInt( RECVINFO( m_cLightColor ) ),
END_RECV_TABLE()
C_EnvProjectedTexture::C_EnvProjectedTexture( void )
{
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
C_EnvProjectedTexture::~C_EnvProjectedTexture( void )
{
ShutDownLightHandle();
}
void C_EnvProjectedTexture::ShutDownLightHandle( void )
{
// Clear out the light
if( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
g_pClientShadowMgr->DestroyFlashlight( m_LightHandle );
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
{
UpdateLight( true );
BaseClass::OnDataChanged( updateType );
}
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
{
if ( m_bState == false )
{
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
ShutDownLightHandle();
}
return;
}
Vector vPos = GetAbsOrigin();
Vector vForward;
FlashlightState_t state;
if ( m_hTargetEntity != NULL )
{
if ( m_bCameraSpace )
{
const QAngle &angles = GetLocalAngles();
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if( pPlayer )
{
const QAngle playerAngles = pPlayer->GetAbsAngles();
Vector vPlayerForward;
AngleVectors( playerAngles, &vPlayerForward );
matrix3x4_t mRotMatrix;
AngleMatrix( angles, mRotMatrix );
VectorTransform( vPlayerForward, mRotMatrix, vForward );
float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;
VectorNormalize( vForward );
}
}
else
{
vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
VectorNormalize( vForward );
}
}
else
{
AngleVectors( GetAbsAngles(), &vForward );
}
state.m_fHorizontalFOVDegrees = m_flLightFOV;
state.m_fVerticalFOVDegrees = m_flLightFOV;
state.m_vecLightOrigin = vPos;
state.m_vecLightDirection = vForward;
state.m_fQuadraticAtten = 0.0;
state.m_fLinearAtten = 100;
state.m_fConstantAtten = 0.0f;
state.m_Color.Init( (float)m_cLightColor.r/255.0f, (float)m_cLightColor.g/255.0f, (float)m_cLightColor.b/255.0f );
state.m_NearZ = 1.0f;
state.m_FarZ = 750;
state.m_bEnableShadows = m_bEnableShadows;
if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
{
m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
}
else
{
if ( m_hTargetEntity != NULL || bForceUpdate == true )
{
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
}
}
if( m_bLightOnlyTarget )
{
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
}
else
{
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
}
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
if ( bForceUpdate == false )
{
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
}
}
void C_EnvProjectedTexture::Simulate( void )
{
UpdateLight( false );
BaseClass::Simulate();
}

View File

@ -0,0 +1,297 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "shareddefs.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "view.h"
#include "iviewrender.h"
#include "view_shared.h"
#include "texture_group_names.h"
#include "vstdlib/icommandline.h"
#include "keyvalues.h"
#include "ScreenSpaceEffects.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvScreenOverlay : public C_BaseEntity
{
DECLARE_CLASS( C_EnvScreenOverlay, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
void PreDataUpdate( DataUpdateType_t updateType );
void PostDataUpdate( DataUpdateType_t updateType );
void HandleOverlaySwitch( void );
void StartOverlays( void );
void StopOverlays( void );
void StartCurrentOverlay( void );
void ClientThink( void );
protected:
char m_iszOverlayNames[ MAX_SCREEN_OVERLAYS ][255];
float m_flOverlayTimes[ MAX_SCREEN_OVERLAYS ];
float m_flStartTime;
int m_iDesiredOverlay;
bool m_bIsActive;
bool m_bWasActive;
int m_iCachedDesiredOverlay;
int m_iCurrentOverlay;
float m_flCurrentOverlayTime;
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOverlay )
RecvPropArray( RecvPropString( RECVINFO( m_iszOverlayNames[0]) ), m_iszOverlayNames ),
RecvPropArray( RecvPropFloat( RECVINFO( m_flOverlayTimes[0] ) ), m_flOverlayTimes ),
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropInt( RECVINFO( m_iDesiredOverlay ) ),
RecvPropBool( RECVINFO( m_bIsActive ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::PreDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PreDataUpdate( updateType );
m_bWasActive = m_bIsActive;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
// If we have a start time now, start the overlays going
if ( m_bIsActive && m_flStartTime > 0 && view->GetScreenOverlayMaterial() == NULL )
{
StartOverlays();
}
if ( m_flStartTime == -1 )
{
StopOverlays();
}
HandleOverlaySwitch();
if ( updateType == DATA_UPDATE_CREATED &&
CommandLine()->FindParm( "-makereslists" ) )
{
for ( int i = 0; i < MAX_SCREEN_OVERLAYS; ++i )
{
if ( m_iszOverlayNames[ i ] && m_iszOverlayNames[ i ][ 0 ] )
{
materials->FindMaterial( m_iszOverlayNames[ i ], TEXTURE_GROUP_CLIENT_EFFECTS, false );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::StopOverlays( void )
{
SetNextClientThink( CLIENT_THINK_NEVER );
if ( m_bWasActive && !m_bIsActive )
{
view->SetScreenOverlayMaterial( NULL );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::StartOverlays( void )
{
m_iCurrentOverlay = 0;
m_flCurrentOverlayTime = 0;
m_iCachedDesiredOverlay = 0;
SetNextClientThink( CLIENT_THINK_ALWAYS );
StartCurrentOverlay();
HandleOverlaySwitch();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::HandleOverlaySwitch( void )
{
if( m_iCachedDesiredOverlay != m_iDesiredOverlay )
{
m_iCurrentOverlay = m_iDesiredOverlay;
m_iCachedDesiredOverlay = m_iDesiredOverlay;
StartCurrentOverlay();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::StartCurrentOverlay( void )
{
if ( m_iCurrentOverlay == MAX_SCREEN_OVERLAYS || !m_iszOverlayNames[m_iCurrentOverlay] || !m_iszOverlayNames[m_iCurrentOverlay][0] )
{
// Hit the end of our overlays, so stop.
m_flStartTime = 0;
StopOverlays();
return;
}
if ( m_flOverlayTimes[m_iCurrentOverlay] == -1 )
m_flCurrentOverlayTime = -1;
else
m_flCurrentOverlayTime = gpGlobals->curtime + m_flOverlayTimes[m_iCurrentOverlay];
// Bring up the current overlay
IMaterial *pMaterial = materials->FindMaterial( m_iszOverlayNames[m_iCurrentOverlay], TEXTURE_GROUP_CLIENT_EFFECTS, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetScreenOverlayMaterial( pMaterial );
}
else
{
Warning("env_screenoverlay couldn't find overlay %s.\n", m_iszOverlayNames[m_iCurrentOverlay] );
StopOverlays();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::ClientThink( void )
{
// If the current overlay's run out, go to the next one
if ( m_flCurrentOverlayTime != -1 && m_flCurrentOverlayTime < gpGlobals->curtime )
{
m_iCurrentOverlay++;
StartCurrentOverlay();
}
}
// Effect types
enum
{
SCREENEFFECT_EP2_ADVISOR_STUN,
SCREENEFFECT_EP1_INTRO,
};
// ============================================================================
// Screenspace effect
// ============================================================================
class C_EnvScreenEffect : public C_BaseEntity
{
DECLARE_CLASS( C_EnvScreenEffect, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
virtual void ReceiveMessage( int classID, bf_read &msg );
private:
float m_flDuration;
int m_nType;
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenEffect, DT_EnvScreenEffect, CEnvScreenEffect )
RecvPropFloat( RECVINFO( m_flDuration ) ),
RecvPropInt( RECVINFO( m_nType ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
// Input : classID -
// &msg -
//-----------------------------------------------------------------------------
void C_EnvScreenEffect::ReceiveMessage( int classID, bf_read &msg )
{
// Make sure our IDs match
if ( classID != GetClientClass()->m_ClassID )
{
// Message is for subclass
BaseClass::ReceiveMessage( classID, msg );
return;
}
int messageType = msg.ReadByte();
switch( messageType )
{
// Effect turning on
case 0: // FIXME: Declare
{
// Create a keyvalue block to set these params
KeyValues *pKeys = new KeyValues( "keys" );
if ( pKeys == NULL )
return;
if ( m_nType == SCREENEFFECT_EP1_INTRO )
{
if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
{
return;
}
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 0 );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "episodic_intro", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "episodic_intro" );
}
else if ( m_nType == SCREENEFFECT_EP2_ADVISOR_STUN )
{
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "episodic_stun", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "episodic_stun" );
}
pKeys->deleteThis();
}
break;
// Effect turning off
case 1: // FIXME: Declare
if ( m_nType == SCREENEFFECT_EP1_INTRO )
{
if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
{
return;
}
// Create a keyvalue block to set these params
KeyValues *pKeys = new KeyValues( "keys" );
if ( pKeys == NULL )
return;
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 1 );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "episodic_intro", pKeys );
}
else if ( m_nType == SCREENEFFECT_EP2_ADVISOR_STUN )
{
g_pScreenSpaceEffects->DisableScreenSpaceEffect( "episodic_stun" );
}
break;
}
}

View File

@ -0,0 +1,90 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
extern bool g_bUseCustomAutoExposureMin;
extern bool g_bUseCustomAutoExposureMax;
extern bool g_bUseCustomBloomScale;
extern float g_flCustomAutoExposureMin;
extern float g_flCustomAutoExposureMax;
extern float g_flCustomBloomScale;
extern float g_flCustomBloomScaleMinimum;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvTonemapController : public C_BaseEntity
{
DECLARE_CLASS( C_EnvTonemapController, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_EnvTonemapController();
~C_EnvTonemapController();
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
bool m_bUseCustomAutoExposureMin;
bool m_bUseCustomAutoExposureMax;
bool m_bUseCustomBloomScale;
float m_flCustomAutoExposureMin;
float m_flCustomAutoExposureMax;
float m_flCustomBloomScale;
float m_flCustomBloomScaleMinimum;
private:
C_EnvTonemapController( const C_EnvTonemapController & );
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvTonemapController, DT_EnvTonemapController, CEnvTonemapController )
RecvPropInt( RECVINFO(m_bUseCustomAutoExposureMin) ),
RecvPropInt( RECVINFO(m_bUseCustomAutoExposureMax) ),
RecvPropInt( RECVINFO(m_bUseCustomBloomScale) ),
RecvPropFloat( RECVINFO(m_flCustomAutoExposureMin) ),
RecvPropFloat( RECVINFO(m_flCustomAutoExposureMax) ),
RecvPropFloat( RECVINFO(m_flCustomBloomScale) ),
RecvPropFloat( RECVINFO(m_flCustomBloomScaleMinimum) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvTonemapController::C_EnvTonemapController( void )
{
m_bUseCustomAutoExposureMin = false;
m_bUseCustomAutoExposureMax = false;
m_bUseCustomBloomScale = false;
m_flCustomAutoExposureMin = 0;
m_flCustomAutoExposureMax = 0;
m_flCustomBloomScale = 0.0f;
m_flCustomBloomScaleMinimum = 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvTonemapController::~C_EnvTonemapController( void )
{
g_bUseCustomAutoExposureMin = false;
g_bUseCustomAutoExposureMax = false;
g_bUseCustomBloomScale = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvTonemapController::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged(updateType);
g_bUseCustomAutoExposureMin = m_bUseCustomAutoExposureMin;
g_bUseCustomAutoExposureMax = m_bUseCustomAutoExposureMax;
g_bUseCustomBloomScale = m_bUseCustomBloomScale;
g_flCustomAutoExposureMin = m_flCustomAutoExposureMin;
g_flCustomAutoExposureMax = m_flCustomAutoExposureMax;
g_flCustomBloomScale = m_flCustomBloomScale;
g_flCustomBloomScaleMinimum = m_flCustomBloomScaleMinimum;
}

1470
cl_dll/c_fire_smoke.cpp Normal file

File diff suppressed because it is too large Load Diff

322
cl_dll/c_fire_smoke.h Normal file
View File

@ -0,0 +1,322 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef C_FIRE_SMOKE_H
#define C_FIRE_SMOKE_H
#include "particles_simple.h"
#include "tempent.h"
#include "glow_overlay.h"
#include "view.h"
#include "particle_litsmokeemitter.h"
class CFireOverlay;
class C_FireSprite : public C_Sprite
{
DECLARE_CLASS( C_FireSprite, C_Sprite );
private:
virtual int DrawModel( int flags )
{
if ( m_bFadeFromAbove )
{
// The sprites become less visible the more you look down or up at them
Vector vToPos = GetLocalOrigin() - CurrentViewOrigin();
VectorNormalize( vToPos );
float fUpAmount = vToPos.z;
int iAlpha = 255;
if ( fUpAmount < -0.75f )
iAlpha = 0;
else if ( fUpAmount < -0.65f )
iAlpha = 255 - (int)( ( fUpAmount + 0.65f ) * 10.0f * -255.0f );
else if ( fUpAmount > 0.85f )
iAlpha = 0;
else if ( fUpAmount > 0.75f )
iAlpha = 255 - (int)( ( fUpAmount - 0.75f ) * 10.0f * 255.0f );
SetColor( iAlpha, iAlpha, iAlpha );
}
return BaseClass::DrawModel( flags );
}
public:
Vector m_vecMoveDir;
bool m_bFadeFromAbove;
};
class C_FireFromAboveSprite : public C_Sprite
{
DECLARE_CLASS( C_FireFromAboveSprite, C_Sprite );
virtual int DrawModel( int flags )
{
// The sprites become more visible the more you look down or up at them
Vector vToPos = GetLocalOrigin() - CurrentViewOrigin();
VectorNormalize( vToPos );
float fUpAmount = vToPos.z;
int iAlpha = 0;
if ( fUpAmount < -0.85f )
iAlpha = 255;
else if ( fUpAmount < -0.65f )
iAlpha = (int)( ( fUpAmount + 0.65f ) * 5.0f * -255.0f );
else if ( fUpAmount > 0.75f )
iAlpha = 255;
else if ( fUpAmount > 0.55f )
iAlpha = (int)( ( fUpAmount - 0.55f ) * 5.0f * 255.0f );
SetColor( iAlpha, iAlpha, iAlpha );
return BaseClass::DrawModel( flags );
}
};
#ifdef _XBOX
// XBox reduces the flame count
#define NUM_CHILD_FLAMES 1
#else
#define NUM_CHILD_FLAMES 4
#endif
#define SMOKE_RISE_RATE 92.0f
#define SMOKE_LIFETIME 2.0f
#define EMBER_LIFETIME 2.0f
#define FLAME_CHILD_SPREAD 64.0f
#define FLAME_SOURCE_HEIGHT 128.0f
#define FLAME_FROM_ABOVE_SOURCE_HEIGHT 32.0f
//==================================================
// C_FireSmoke
//==================================================
//NOTENOTE: Mirrored in dlls/fire_smoke.h
#define bitsFIRESMOKE_NONE 0x00000000
#define bitsFIRESMOKE_ACTIVE 0x00000001
#define bitsFIRESMOKE_SMOKE 0x00000002
#define bitsFIRESMOKE_SMOKE_COLLISION 0x00000004
#define bitsFIRESMOKE_GLOW 0x00000008
#define bitsFIRESMOKE_VISIBLE_FROM_ABOVE 0x00000010
#define OVERLAY_MAX_VISIBLE_RANGE 512.0f
class C_FireSmoke : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_FireSmoke, C_BaseEntity );
C_FireSmoke();
~C_FireSmoke();
void Start( void );
void Simulate( void );
void StartClientOnly( void );
void RemoveClientOnly( void );
protected:
void Update( void );
void UpdateAnimation( void );
void UpdateScale( void );
void UpdateFlames( void );
void AddFlames( void );
void SpawnSmoke( void );
void FindClipPlane( void );
//C_BaseEntity
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool ShouldDraw();
float GetScale( void ) const { return m_flScaleRegister; }
//From the server
public:
float m_flStartScale;
float m_flScale;
float m_flScaleTime;
int m_nFlags;
int m_nFlameModelIndex;
int m_nFlameFromAboveModelIndex;
//Client-side only
public:
float m_flScaleRegister;
float m_flScaleStart;
float m_flScaleEnd;
float m_flScaleTimeStart;
float m_flScaleTimeEnd;
float m_flChildFlameSpread;
VPlane m_planeClip;
float m_flClipPerc;
bool m_bClipTested;
bool m_bFadingOut;
protected:
void UpdateEffects( void );
//CSmartPtr<CEmberEffect> m_pEmberEmitter;
CSmartPtr<CLitSmokeEmitter> m_pSmokeEmitter;
C_FireSprite m_entFlames[NUM_CHILD_FLAMES];
C_FireFromAboveSprite m_entFlamesFromAbove[NUM_CHILD_FLAMES];
float m_entFlameScales[NUM_CHILD_FLAMES];
TimedEvent m_tParticleSpawn;
CFireOverlay *m_pFireOverlay;
private:
C_FireSmoke( const C_FireSmoke & );
};
//Fire overlay
class CFireOverlay : public CGlowOverlay
{
public:
//Constructor
CFireOverlay( C_FireSmoke *owner )
{
m_pOwner = owner;
m_flScale = 0.0f;
m_nGUID = random->RandomInt( -999999, 999999 );
}
//-----------------------------------------------------------------------------
// Purpose: Generate a flicker value
// Output : scalar value
//-----------------------------------------------------------------------------
float GetFlickerScale( void )
{
float result = 0.0f;
float time = Helper_GetTime() + m_nGUID;
result = sin( time * 1000.0f );
result += 0.5f * sin( time * 2000.0f );
result -= 0.5f * cos( time * 8000.0f );
return result;
}
//-----------------------------------------------------------------------------
// Purpose: Update the overlay
//-----------------------------------------------------------------------------
virtual bool Update( void )
{
if ( m_pOwner == NULL )
return false;
float scale = m_pOwner->GetScale();
float dscale = scale - m_flScale;
m_vPos[2] += dscale * FLAME_SOURCE_HEIGHT;
m_flScale = scale;
scale *= 0.75f;
float flickerScale = GetFlickerScale();
float newScale = scale + ( scale * flickerScale * 0.1f );
m_Sprites[0].m_flHorzSize = ( newScale * 0.2f ) + ( m_Sprites[0].m_flHorzSize * 0.8f );
m_Sprites[0].m_flVertSize = m_Sprites[0].m_flHorzSize * 1.5f;
float cameraDistance = ( CurrentViewOrigin() - (m_pOwner->GetAbsOrigin())).Length();
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
if ( local )
{
cameraDistance *= local->GetFOVDistanceAdjustFactor();
}
if ( cameraDistance > OVERLAY_MAX_VISIBLE_RANGE )
cameraDistance = OVERLAY_MAX_VISIBLE_RANGE;
float alpha = 1.0f - ( cameraDistance / OVERLAY_MAX_VISIBLE_RANGE );
Vector newColor = m_vBaseColors[0] + ( m_vBaseColors[0] * flickerScale * 0.5f );
m_Sprites[0].m_vColor = ( newColor * 0.1f ) + ( m_Sprites[0].m_vColor * 0.9f ) * alpha;
return true;
}
public:
C_FireSmoke *m_pOwner;
Vector m_vBaseColors[MAX_SUN_LAYERS];
float m_flScale;
int m_nGUID;
};
//
// Entity flame, client-side implementation
//
#define NUM_FLAMELETS 5
class C_EntityFlame : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityFlame, C_BaseEntity );
C_EntityFlame( void );
~C_EntityFlame( void );
void UpdateOnRemove( void );
void CleanUpRagdollOnRemove( void );
void OnDataChanged( DataUpdateType_t updateType );
RenderGroup_t GetRenderGroup();
void Simulate( void );
EHANDLE m_hEntAttached; // The entity that we are burning (attached to).
bool m_bUseHitboxes;
bool m_bCreatedClientside;
virtual void ClientThink( void );
C_FireSmoke *m_pFireSmoke[NUM_HITBOX_FIRES];
protected:
void AttachToHitBoxes( void );
void UpdateHitBoxFlames( void );
void DeleteHitBoxFlames( void );
float m_flSize;
CSmartPtr<CEmberEffect> m_pEmitter;
TimedEvent m_ParticleSpawn;
bool m_bAttachedToHitboxes;
float m_flLifetime;
bool m_bStartedFading;
const model_t *m_pCachedModel; // Holds the model pointer to detect when it changes
Vector m_vecLastPosition;
PMaterialHandle m_MaterialHandle[NUM_FLAMELETS];
// For attaching to the hitboxes of an animating model.
Vector m_vecFireOrigin[NUM_HITBOX_FIRES];
int m_nHitbox[NUM_HITBOX_FIRES];
};
#endif //C_FIRE_SMOKE_H

352
cl_dll/c_fish.cpp Normal file
View File

@ -0,0 +1,352 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// c_fish.cpp
// Simple fish client-side logic
// Author: Michael S. Booth, April 2005
#include "cbase.h"
#include <bitbuf.h>
#include "engine/IVDebugOverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
ConVar FishDebug( "fish_debug", "0", FCVAR_CHEAT, "Show debug info for fish" );
//-----------------------------------------------------------------------------
/**
* Client-side fish entity
*/
class C_Fish : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_Fish, C_BaseAnimating );
DECLARE_CLIENTCLASS();
virtual void Spawn( void );
virtual void ClientThink();
virtual void OnDataChanged( DataUpdateType_t type );
private:
friend void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut );
friend void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut );
Vector m_pos; ///< local position
Vector m_vel; ///< local velocity
QAngle m_angles; ///< local angles
int m_localLifeState; ///< our version of m_lifeState
float m_deathDepth; ///< water depth when we died
float m_deathAngle; ///< angle to float at when dead
float m_buoyancy; ///< so each fish floats at a different rate when dead
CountdownTimer m_wiggleTimer; ///< for simulating swimming motions
float m_wigglePhase; ///< where in the wiggle sinusoid we are
float m_wiggleRate; ///< the speed of our wiggling
Vector m_actualPos; ///< position from server
QAngle m_actualAngles; ///< angles from server
Vector m_poolOrigin;
float m_waterLevel; ///< Z coordinate of water surface
bool m_gotUpdate; ///< true after we have received a network update
enum { MAX_ERROR_HISTORY = 20 };
float m_errorHistory[ MAX_ERROR_HISTORY ]; ///< error history samples
int m_errorHistoryIndex;
int m_errorHistoryCount;
float m_averageError;
};
//-----------------------------------------------------------------------------
void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_Fish *fish = (C_Fish *)pStruct;
float *out = (float *)pOut;
*out = pData->m_Value.m_Float + fish->m_poolOrigin.x;
}
void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_Fish *fish = (C_Fish *)pStruct;
float *out = (float *)pOut;
*out = pData->m_Value.m_Float + fish->m_poolOrigin.y;
}
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_Fish, DT_CFish, CFish )
RecvPropVector( RECVINFO(m_poolOrigin) ),
RecvPropFloat( RECVINFO_NAME( m_actualPos.x, m_x ), 0, RecvProxy_FishOriginX ),
RecvPropFloat( RECVINFO_NAME( m_actualPos.y, m_y ), 0, RecvProxy_FishOriginY ),
RecvPropFloat( RECVINFO_NAME( m_actualPos.z, m_z ) ),
RecvPropFloat( RECVINFO_NAME( m_actualAngles.y, m_angle ) ),
RecvPropInt( RECVINFO(m_nModelIndex) ),
RecvPropInt( RECVINFO(m_lifeState) ),
RecvPropFloat( RECVINFO(m_waterLevel) ), ///< get this from the server in case we die when slightly out of the water due to error correction
END_RECV_TABLE()
//-----------------------------------------------------------------------------
void C_Fish::Spawn( void )
{
BaseClass::Spawn();
m_angles = QAngle( 0, 0, 0 );
m_actualAngles = m_angles;
m_vel = Vector( 0, 0, 0 );
m_gotUpdate = false;
m_localLifeState = LIFE_ALIVE;
m_buoyancy = RandomFloat( 0.4f, 1.0f );
m_errorHistoryIndex = 0;
m_errorHistoryCount = 0;
m_averageError = 0.0f;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
void C_Fish::ClientThink()
{
if (FishDebug.GetBool())
{
debugoverlay->AddLineOverlay( m_pos, m_actualPos, 255, 0, 0, true, 0.1f );
switch( m_localLifeState )
{
case LIFE_DYING:
debugoverlay->AddTextOverlay( m_pos, 0.1f, "DYING" );
break;
case LIFE_DEAD:
debugoverlay->AddTextOverlay( m_pos, 0.1f, "DEAD" );
break;
}
}
float deltaT = gpGlobals->frametime;
// check if we just died
if (m_localLifeState == LIFE_ALIVE && m_lifeState != LIFE_ALIVE)
{
// we have died
m_localLifeState = LIFE_DYING;
m_deathDepth = m_pos.z;
// determine surface float angle
m_deathAngle = RandomFloat( 87.0f, 93.0f ) * ((RandomInt( 0, 100 ) < 50) ? 1.0f : -1.0f);
}
switch( m_localLifeState )
{
case LIFE_DYING:
{
// depth parameter
float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth);
t *= t;
// roll onto side
m_angles.z = m_deathAngle * t;
// float to surface
const float fudge = 2.0f;
if (m_pos.z < m_waterLevel - fudge)
{
m_vel.z += (1.0f - t) * m_buoyancy * deltaT;
}
else
{
m_localLifeState = LIFE_DEAD;
}
break;
}
case LIFE_DEAD:
{
// depth parameter
float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth);
t *= t;
// roll onto side
m_angles.z = m_deathAngle * t;
// keep near water surface
const float sub = 0.5f;
m_vel.z += 10.0f * (m_waterLevel - m_pos.z - sub) * deltaT;
// bob on surface
const float rollAmp = 5.0f;
const float rollFreq = 2.33f;
m_angles.z += rollAmp * sin( rollFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
const float rollAmp2 = 7.0f;
const float rollFreq2 = 4.0f;
m_angles.x += rollAmp2 * sin( rollFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
const float bobAmp = 0.75f;
const float bobFreq = 4.0f;
m_vel.z += bobAmp * sin( bobFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
const float bobAmp2 = 0.75f;
const float bobFreq2 = 3.333f;
m_vel.z += bobAmp2 * sin( bobFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
// decay movement speed to zero
const float drag = 1.0f;
m_vel.z -= drag * m_vel.z * deltaT;
break;
}
case LIFE_ALIVE:
{
// use server-side Z coordinate directly
m_pos.z = m_actualPos.z;
// use server-side angles
m_angles = m_actualAngles;
// fishy wiggle based on movement
if (!m_wiggleTimer.IsElapsed())
{
float swimPower = 1.0f - (m_wiggleTimer.GetElapsedTime() / m_wiggleTimer.GetCountdownDuration());
const float amp = 6.0f * swimPower;
float wiggle = amp * sin( m_wigglePhase );
m_wigglePhase += m_wiggleRate * deltaT;
// wiggle decay
const float wiggleDecay = 5.0f;
m_wiggleRate -= wiggleDecay * deltaT;
m_angles.y += wiggle;
}
break;
}
}
// compute error between our local position and actual server position
Vector error = m_actualPos - m_pos;
error.z = 0.0f;
float errorLen = error.Length();
if (m_localLifeState == LIFE_ALIVE)
{
// if error is far above average, start swimming
const float wiggleThreshold = 2.0f;
if (errorLen - m_averageError > wiggleThreshold)
{
// if error is large, we must have started swimming
const float swimTime = 5.0f;
m_wiggleTimer.Start( swimTime );
m_wiggleRate = 2.0f * errorLen;
const float maxWiggleRate = 30.0f;
if (m_wiggleRate > maxWiggleRate)
{
m_wiggleRate = maxWiggleRate;
}
}
// update average error
m_errorHistory[ m_errorHistoryIndex++ ] = errorLen;
if (m_errorHistoryIndex >= MAX_ERROR_HISTORY)
{
m_errorHistoryIndex = 0;
m_errorHistoryCount = MAX_ERROR_HISTORY;
}
else if (m_errorHistoryCount < MAX_ERROR_HISTORY)
{
++m_errorHistoryCount;
}
m_averageError = 0.0f;
if (m_errorHistoryCount)
{
for( int r=0; r<m_errorHistoryCount; ++r )
{
m_averageError += m_errorHistory[r];
}
m_averageError /= (float)m_errorHistoryCount;
}
}
// keep fish motion smooth by correcting towards actual server position
// NOTE: This only tracks XY motion
const float maxError = 20.0f;
float errorT = errorLen / maxError;
if (errorT > 1.0f)
{
errorT = 1.0f;
}
// we want a nonlinear spring force for tracking
errorT *= errorT;
// as fish move faster, their error increases - use a stiffer spring when fast, and a weak one when slow
const float trackRate = 0.0f + errorT * 115.0f;
m_vel.x += trackRate * error.x * deltaT;
m_vel.y += trackRate * error.y * deltaT;
const float trackDrag = 2.0f + errorT * 6.0f;
m_vel.x -= trackDrag * m_vel.x * deltaT;
m_vel.y -= trackDrag * m_vel.y * deltaT;
// euler integration
m_pos += m_vel * deltaT;
SetNetworkOrigin( m_pos );
SetAbsOrigin( m_pos );
SetNetworkAngles( m_angles );
SetAbsAngles( m_angles );
}
//-----------------------------------------------------------------------------
void C_Fish::OnDataChanged( DataUpdateType_t type )
{
//if (!m_gotUpdate)
if (type == DATA_UPDATE_CREATED)
{
// initial update
m_gotUpdate = true;
m_pos = m_actualPos;
m_vel = Vector( 0, 0, 0 );
return;
}
}

301
cl_dll/c_forcefeedback.cpp Normal file
View File

@ -0,0 +1,301 @@
#include "cbase.h"
#include "forcefeedback.h"
#include "hud_macros.h"
#include "input.h"
#define FF_CLIENT_FLAG 0x8000
class FFParams
{
public:
FORCEFEEDBACK_t m_nEffectType;
FFBaseParams_t m_BaseParams;
};
struct FFEffectInfo_t
{
FORCEFEEDBACK_t effectType;
char const *name;
};
#define DECLARE_FFEFFECT( name ) { name, #name }
static FFEffectInfo_t g_EffectTypes[] =
{
DECLARE_FFEFFECT( FORCE_FEEDBACK_SHOT_SINGLE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_SHOT_DOUBLE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_TAKEDAMAGE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_SCREENSHAKE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_SKIDDING ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_BREAKING )
};
//-----------------------------------------------------------------------------
// Purpose:
// Input : effect -
// Output : char const
//-----------------------------------------------------------------------------
char const *NameForForceFeedbackEffect( FORCEFEEDBACK_t effect )
{
int c = ARRAYSIZE( g_EffectTypes );
if ( (int)effect < 0 || (int)effect >= c )
return "???";
const FFEffectInfo_t& info = g_EffectTypes[ (int)effect ];
Assert( info.effectType == effect );
return info.name;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *name -
// Output : FORCEFEEDBACK_t
//-----------------------------------------------------------------------------
FORCEFEEDBACK_t ForceFeedbackEffectForName( const char *name )
{
int c = ARRAYSIZE( g_EffectTypes );
for ( int i = 0 ; i < c; ++i )
{
const FFEffectInfo_t& info = g_EffectTypes[ i ];
if ( !Q_stricmp( info.name, name ) )
return info.effectType;
}
return ( FORCEFEEDBACK_t )-1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CForceFeedback : public IForceFeedback, public CAutoGameSystem
{
public:
virtual bool Init();
virtual void Shutdown();
// API
virtual void StopAllEffects( CBasePlayer *player );
virtual void StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect );
virtual void StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params );
virtual void PauseAll( CBasePlayer *player );
virtual void ResumeAll( CBasePlayer *player );
void MsgFunc_ForceFeedback( bf_read &msg );
private:
void Internal_StopAllEffects();
void Internal_StopEffect( FORCEFEEDBACK_t effect );
void Internal_StartEffect( FORCEFEEDBACK_t, const FFBaseParams_t& params );
void Internal_PauseAll();
void Internal_ResumeAll();
};
static CForceFeedback g_ForceFeedbackSingleton;
IForceFeedback *forcefeedback = &g_ForceFeedbackSingleton;
//-----------------------------------------------------------------------------
// Purpose:
// Input : &msg -
//-----------------------------------------------------------------------------
void __MsgFunc_ForceFeedback( bf_read &msg )
{
g_ForceFeedbackSingleton.MsgFunc_ForceFeedback( msg );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CForceFeedback::Init()
{
HOOK_MESSAGE( ForceFeedback );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Shutdown()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
//-----------------------------------------------------------------------------
void CForceFeedback::StopAllEffects( CBasePlayer *player )
{
if ( !player )
return;
Internal_StopAllEffects();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
// effect -
//-----------------------------------------------------------------------------
void CForceFeedback::StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect )
{
if ( !player )
return;
Internal_StopEffect( effect );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
// effect -
// params -
//-----------------------------------------------------------------------------
void CForceFeedback::StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params )
{
if ( !player )
{
return;
}
Internal_StartEffect( effect, params );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
//-----------------------------------------------------------------------------
void CForceFeedback::PauseAll( CBasePlayer *player )
{
if ( !player )
return;
Internal_PauseAll();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
//-----------------------------------------------------------------------------
void CForceFeedback::ResumeAll( CBasePlayer *player )
{
if ( !player )
return;
Internal_ResumeAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_StopAllEffects()
{
input->ForceFeedback_StopAll();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : heffect -
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_StopEffect( FORCEFEEDBACK_t effect )
{
input->ForceFeedback_Stop( effect );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : effect -
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_StartEffect( FORCEFEEDBACK_t effect, const FFBaseParams_t& params)
{
char const *name = NameForForceFeedbackEffect( effect );
Msg( "Starting FF effect '%s'\n", name );
FFParams p;
p.m_nEffectType = effect;
p.m_BaseParams = params;
input->ForceFeedback_Start( effect, params );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_PauseAll()
{
input->ForceFeedback_Pause();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_ResumeAll()
{
input->ForceFeedback_Resume();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszName -
// iSize -
// *pbuf -
//-----------------------------------------------------------------------------
void CForceFeedback::MsgFunc_ForceFeedback( bf_read &msg )
{
byte msgType = msg.ReadByte();
switch ( msgType )
{
default:
{
Warning( "Bad parse in MsgFunc_ForceFeedback!\n" );
}
break;
case FFMSG_STOPALL:
{
Internal_StopAllEffects();
}
break;
case FFMSG_START:
{
FORCEFEEDBACK_t effectType = (FORCEFEEDBACK_t)msg.ReadByte();
FFBaseParams_t params;
params.m_flDirection = 360.0f * ( (byte)msg.ReadByte() / 255.0f );
params.m_flDuration = (float)msg.ReadLong() / 1000.0f;
params.m_flGain = ( (byte)msg.ReadByte() / 255.0f );
params.m_nPriority = msg.ReadByte();
params.m_bSolo = msg.ReadByte() == 0 ? false : true;
if ( effectType >= 0 && effectType < NUM_FORCE_FEEDBACK_PRESETS )
{
Internal_StartEffect( effectType, params );
}
else
{
Warning( "Bad parse in MsgFunc_ForceFeedback, FFMSG_START (%i)!\n", effectType );
}
}
break;
case FFMSG_STOP:
{
FORCEFEEDBACK_t effectType = (FORCEFEEDBACK_t)msg.ReadByte();
Internal_StopEffect( effectType );
}
break;
case FFMSG_PAUSE:
{
Internal_PauseAll();
}
break;
case FFMSG_RESUME:
{
Internal_ResumeAll();
}
break;
}
}

View File

@ -0,0 +1,139 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "view.h"
#include "model_types.h"
#include "IVRenderView.h"
#include "engine/ivmodelinfo.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_FuncAreaPortalWindow : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_FuncAreaPortalWindow, C_BaseEntity );
// Overrides.
public:
virtual void ComputeFxBlend();
virtual bool IsTransparent();
virtual int DrawModel( int flags );
virtual bool ShouldReceiveProjectedTextures( int flags );
private:
float GetDistanceBlend();
public:
float m_flFadeStartDist; // Distance at which it starts fading (when <= this, alpha=m_flTranslucencyLimit).
float m_flFadeDist; // Distance at which it becomes solid.
// 0-1 value - minimum translucency it's allowed to get to.
float m_flTranslucencyLimit;
int m_iBackgroundModelIndex;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncAreaPortalWindow, DT_FuncAreaPortalWindow, CFuncAreaPortalWindow )
RecvPropFloat( RECVINFO( m_flFadeStartDist ) ),
RecvPropFloat( RECVINFO( m_flFadeDist ) ),
RecvPropFloat( RECVINFO( m_flTranslucencyLimit ) ),
RecvPropInt( RECVINFO( m_iBackgroundModelIndex ) )
END_RECV_TABLE()
void C_FuncAreaPortalWindow::ComputeFxBlend()
{
// We reset our blend down below so pass anything except 0 to the renderer.
m_nRenderFXBlend = 255;
#ifdef _DEBUG
m_nFXComputeFrame = gpGlobals->framecount;
#endif
}
bool C_FuncAreaPortalWindow::IsTransparent()
{
return true;
}
int C_FuncAreaPortalWindow::DrawModel( int flags )
{
if ( !m_bReadyToDraw )
return 0;
if( !GetModel() )
return 0;
// Make sure we're a brush model.
int modelType = modelinfo->GetModelType( GetModel() );
if( modelType != mod_brush )
return 0;
// Draw the fading version.
render->SetBlend( GetDistanceBlend() );
render->DrawBrushModel(
this,
(model_t *)GetModel(),
GetAbsOrigin(),
GetAbsAngles(),
!!(flags & STUDIO_TRANSPARENCY) );
// Draw the optional foreground model next.
// Only use the alpha in the texture from the thing in the front.
if (m_iBackgroundModelIndex >= 0)
{
render->SetBlend( 1 );
model_t *pBackground = ( model_t * )modelinfo->GetModel( m_iBackgroundModelIndex );
if( pBackground && modelinfo->GetModelType( pBackground ) == mod_brush )
{
render->DrawBrushModel(
this,
pBackground,
GetAbsOrigin(),
GetAbsAngles(),
!!(flags & STUDIO_TRANSPARENCY) );
}
}
return 1;
}
float C_FuncAreaPortalWindow::GetDistanceBlend()
{
// Get the viewer's distance to us.
float flDist = CollisionProp()->CalcDistanceFromPoint( CurrentViewOrigin() );
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
if ( local )
{
flDist *= local->GetFOVDistanceAdjustFactor();
}
float flAlpha = RemapVal( flDist, m_flFadeStartDist, m_flFadeDist, m_flTranslucencyLimit, 1 );
flAlpha = clamp( flAlpha, m_flTranslucencyLimit, 1 );
return flAlpha;
}
bool C_FuncAreaPortalWindow::ShouldReceiveProjectedTextures( int flags )
{
return false;
}

File diff suppressed because it is too large Load Diff

144
cl_dll/c_func_conveyor.cpp Normal file
View File

@ -0,0 +1,144 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "FunctionProxy.h"
#include <KeyValues.h>
#include "VMatrix.h"
#include "FunctionProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_FuncConveyor : public C_BaseEntity
{
public:
DECLARE_CLASS( C_FuncConveyor, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_FuncConveyor();
float GetConveyorSpeed() { return m_flConveyorSpeed; }
private:
float m_flConveyorSpeed;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncConveyor, DT_FuncConveyor, CFuncConveyor )
RecvPropFloat( RECVINFO( m_flConveyorSpeed ) ),
END_RECV_TABLE()
C_FuncConveyor::C_FuncConveyor()
{
m_flConveyorSpeed = 0.0;
}
class CConveyorMaterialProxy : public IMaterialProxy
{
public:
CConveyorMaterialProxy();
virtual ~CConveyorMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
private:
C_BaseEntity *BindArgToEntity( void *pArg );
IMaterialVar *m_pTextureScrollVar;
};
CConveyorMaterialProxy::CConveyorMaterialProxy()
{
m_pTextureScrollVar = NULL;
}
CConveyorMaterialProxy::~CConveyorMaterialProxy()
{
}
bool CConveyorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pScrollVarName = pKeyValues->GetString( "textureScrollVar" );
if( !pScrollVarName )
return false;
bool foundVar;
m_pTextureScrollVar = pMaterial->FindVar( pScrollVarName, &foundVar, false );
if( !foundVar )
return false;
return true;
}
C_BaseEntity *CConveyorMaterialProxy::BindArgToEntity( void *pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
return pRend->GetIClientUnknown()->GetBaseEntity();
}
void CConveyorMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !pC_BaseEntity )
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
if ( !pEntity )
return;
C_FuncConveyor *pConveyor = dynamic_cast<C_FuncConveyor*>(pEntity);
if ( !pConveyor )
return;
if ( !m_pTextureScrollVar )
{
return;
}
float flConveyorSpeed = pConveyor->GetConveyorSpeed();
float flRate = abs( flConveyorSpeed ) / 128.0;
float flAngle = (flConveyorSpeed >= 0) ? 180 : 0;
float sOffset = gpGlobals->curtime * cos( flAngle * ( M_PI / 180.0f ) ) * flRate;
float tOffset = gpGlobals->curtime * sin( flAngle * ( M_PI / 180.0f ) ) * flRate;
// make sure that we are positive
if( sOffset < 0.0f )
{
sOffset += 1.0f + -( int )sOffset;
}
if( tOffset < 0.0f )
{
tOffset += 1.0f + -( int )tOffset;
}
// make sure that we are in a [0,1] range
sOffset = sOffset - ( int )sOffset;
tOffset = tOffset - ( int )tOffset;
if (m_pTextureScrollVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)
{
VMatrix mat;
MatrixBuildTranslation( mat, sOffset, tOffset, 0.0f );
m_pTextureScrollVar->SetMatrixValue( mat );
}
else
{
m_pTextureScrollVar->SetVecValue( sOffset, tOffset, 0.0f );
}
}
EXPOSE_INTERFACE( CConveyorMaterialProxy, IMaterialProxy, "ConveyorScroll" IMATERIAL_PROXY_INTERFACE_VERSION );

455
cl_dll/c_func_dust.cpp Normal file
View File

@ -0,0 +1,455 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_func_dust.h"
#include "func_dust_shared.h"
#include "c_te_particlesystem.h"
#include "env_wind_shared.h"
#include "engine/IEngineTrace.h"
#include "tier0/vprof.h"
#include "ClientEffectPrecacheSystem.h"
#ifdef _XBOX
#include "particles_ez.h"
#endif // XBOX
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_Func_Dust, DT_Func_Dust, CFunc_Dust )
RecvPropInt( RECVINFO(m_Color) ),
RecvPropInt( RECVINFO(m_SpawnRate) ),
RecvPropFloat( RECVINFO(m_flSizeMin) ),
RecvPropFloat( RECVINFO(m_flSizeMax) ),
RecvPropInt( RECVINFO(m_LifetimeMin) ),
RecvPropInt( RECVINFO(m_LifetimeMax) ),
RecvPropInt( RECVINFO(m_DustFlags) ),
RecvPropInt( RECVINFO(m_SpeedMax) ),
RecvPropInt( RECVINFO(m_DistMax) ),
RecvPropInt( RECVINFO( m_nModelIndex ) ),
RecvPropFloat( RECVINFO( m_FallSpeed ) ),
RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
END_RECV_TABLE()
// ------------------------------------------------------------------------------------ //
// CDustEffect implementation.
// ------------------------------------------------------------------------------------ //
#define DUST_ACCEL 50
void CDustEffect::RenderParticles( CParticleRenderIterator *pIterator )
{
const CFuncDustParticle *pParticle = (const CFuncDustParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Velocity.
float flAlpha;
if( m_pDust->m_DustFlags & DUSTFLAGS_FROZEN )
{
flAlpha = 1;
}
else
{
// Alpha.
float flAngle = (pParticle->m_flLifetime / pParticle->m_flDieTime) * M_PI * 2;
flAlpha = sin( flAngle - (M_PI * 0.5f) ) * 0.5f + 0.5f;
}
Vector tPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
float sortKey = (int) tPos.z;
if( -tPos.z <= m_pDust->m_DistMax )
{
flAlpha *= 1 + (tPos.z / m_pDust->m_DistMax);
// Draw it.
float flSize = pParticle->m_flSize;
if( m_pDust->m_DustFlags & DUSTFLAGS_SCALEMOTES )
flSize *= -tPos.z;
RenderParticle_Color255Size(
pIterator->GetParticleDraw(),
tPos,
Vector( m_pDust->m_Color.r, m_pDust->m_Color.g, m_pDust->m_Color.b ),
flAlpha * m_pDust->m_Color.a,
flSize
);
}
pParticle = (const CFuncDustParticle*)pIterator->GetNext( sortKey );
}
}
void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
{
Vector vecWind;
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
CFuncDustParticle *pParticle = (CFuncDustParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Velocity.
if( !(m_pDust->m_DustFlags & DUSTFLAGS_FROZEN) )
{
// Kill the particle?
pParticle->m_flLifetime += pIterator->GetTimeDelta();
if( pParticle->m_flLifetime >= pParticle->m_flDieTime )
{
pIterator->RemoveParticle( pParticle );
}
else
{
for ( int i = 0 ; i < 2 ; i++ )
{
if ( pParticle->m_vVelocity[i] < vecWind[i] )
{
pParticle->m_vVelocity[i] += ( gpGlobals->frametime * DUST_ACCEL );
// clamp
if ( pParticle->m_vVelocity[i] > vecWind[i] )
pParticle->m_vVelocity[i] = vecWind[i];
}
else if (pParticle->m_vVelocity[i] > vecWind[i] )
{
pParticle->m_vVelocity[i] -= ( gpGlobals->frametime * DUST_ACCEL );
// clamp.
if ( pParticle->m_vVelocity[i] < vecWind[i] )
pParticle->m_vVelocity[i] = vecWind[i];
}
}
// Apply velocity.
pParticle->m_Pos.MulAdd( pParticle->m_Pos, pParticle->m_vVelocity, pIterator->GetTimeDelta() );
}
}
pParticle = (CFuncDustParticle*)pIterator->GetNext();
}
}
// ------------------------------------------------------------------------------------ //
// C_Func_Dust implementation.
// ------------------------------------------------------------------------------------ //
C_Func_Dust::C_Func_Dust() : m_Effect( "C_Func_Dust" )
{
m_Effect.m_pDust = this;
m_Effect.SetDynamicallyAllocated( false ); // So it doesn't try to delete itself.
}
C_Func_Dust::~C_Func_Dust()
{
}
CLIENTEFFECT_REGISTER_BEGIN( PrecacheFuncDust )
CLIENTEFFECT_MATERIAL( "particle/sparkles" )
CLIENTEFFECT_REGISTER_END()
void C_Func_Dust::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if( updateType == DATA_UPDATE_CREATED )
{
m_hMaterial = m_Effect.GetPMaterial( "particle/sparkles" );
m_Effect.SetSortOrigin( WorldSpaceCenter( ) );
// Let us think each frame.
SetNextClientThink( CLIENT_THINK_ALWAYS );
// If we're setup to be frozen, just make a bunch of particles initially.
if( m_DustFlags & DUSTFLAGS_FROZEN )
{
for( int i=0; i < m_SpawnRate; i++ )
{
AttemptSpawnNewParticle();
}
}
}
m_Spawner.Init( m_SpawnRate ); // N particles per second
}
void C_Func_Dust::ClientThink()
{
// If frozen, don't make new particles.
if( m_DustFlags & DUSTFLAGS_FROZEN )
return;
// Spawn particles?
if( m_DustFlags & DUSTFLAGS_ON )
{
float flDelta = min( gpGlobals->frametime, 0.1f );
while( m_Spawner.NextEvent( flDelta ) )
{
AttemptSpawnNewParticle();
}
}
// Tell the particle manager our bbox.
Vector vWorldMins, vWorldMaxs;
CollisionProp()->WorldSpaceAABB( &vWorldMins, &vWorldMaxs );
vWorldMins -= Vector( m_flSizeMax, m_flSizeMax, m_flSizeMax );
vWorldMaxs += Vector( m_flSizeMax, m_flSizeMax, m_flSizeMax );
m_Effect.GetBinding().SetBBox( vWorldMins, vWorldMaxs );
}
bool C_Func_Dust::ShouldDraw()
{
return false;
}
void C_Func_Dust::AttemptSpawnNewParticle()
{
// Find a random spot inside our bmodel.
static int nTests=10;
for( int iTest=0; iTest < nTests; iTest++ )
{
Vector vPercent = RandomVector( 0, 1 );
Vector vTest = WorldAlignMins() + (WorldAlignMaxs() - WorldAlignMins()) * vPercent;
int contents = enginetrace->GetPointContents_Collideable( GetCollideable(), vTest );
if( contents & CONTENTS_SOLID )
{
CFuncDustParticle *pParticle = (CFuncDustParticle*)m_Effect.AddParticle( 10, m_hMaterial, vTest );
if( pParticle )
{
pParticle->m_vVelocity = RandomVector( -m_SpeedMax, m_SpeedMax );
pParticle->m_vVelocity.z -= m_FallSpeed;
pParticle->m_flLifetime = 0;
pParticle->m_flDieTime = RemapVal( rand(), 0, RAND_MAX, m_LifetimeMin, m_LifetimeMax );
if( m_DustFlags & DUSTFLAGS_SCALEMOTES )
pParticle->m_flSize = RemapVal( rand(), 0, RAND_MAX, m_flSizeMin/10000.0f, m_flSizeMax/10000.0f );
else
pParticle->m_flSize = RemapVal( rand(), 0, RAND_MAX, m_flSizeMin, m_flSizeMax );
pParticle->m_Color = m_Color;
}
break;
}
}
}
//
// Dust
//
//-----------------------------------------------------------------------------
// Spew out dust!
//-----------------------------------------------------------------------------
void FX_Dust( const Vector &vecOrigin, const Vector &vecDirection, float flSize, float flSpeed )
{
#ifdef _XBOX
//
// XBox Version
//
VPROF_BUDGET( "FX_Dust", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
int numPuffs = (flSize*0.5f);
if ( numPuffs < 1 )
numPuffs = 1;
if ( numPuffs > 32 )
numPuffs = 32;
float speed = flSpeed * 0.1f;
if ( speed < 0 )
speed = 1.0f;
if (speed > 48.0f )
speed = 48.0f;
//FIXME: Better sampling area
Vector offset = vecOrigin + ( vecDirection * flSize );
//Find area ambient light color and use it to tint smoke
Vector worldLight = WorldGetLightForPoint( offset, true );
// FIXME: Reduce
PMaterialHandle hMaterial[2];
hMaterial[0] = ParticleMgr()->GetPMaterial("particle/particle_smokegrenade");
hMaterial[1] = ParticleMgr()->GetPMaterial("particle/particle_noisesphere");
// Throw puffs
SimpleParticle particle;
for ( int i = 0; i < numPuffs; i++ )
{
offset.Random( -(flSize*0.25f), flSize*0.25f );
offset += vecOrigin + ( vecDirection * flSize );
particle.m_Pos = offset;
particle.m_flLifetime = 0.0f;
particle.m_flDieTime = random->RandomFloat( 0.4f, 1.0f );
particle.m_vecVelocity = vecDirection * random->RandomFloat( speed*0.5f, speed ) * i;
particle.m_vecVelocity[2] = 0.0f;
int color = random->RandomInt( 48, 64 );
particle.m_uchColor[0] = (color+16) + ( worldLight[0] * (float) color );
particle.m_uchColor[1] = (color+8) + ( worldLight[1] * (float) color );
particle.m_uchColor[2] = color + ( worldLight[2] * (float) color );
particle.m_uchStartAlpha= random->RandomInt( 64, 128 );
particle.m_uchEndAlpha = 0;
particle.m_uchStartSize = random->RandomInt( 2, 8 );
particle.m_uchEndSize = random->RandomInt( 24, 48 );
particle.m_flRoll = random->RandomInt( 0, 360 );
particle.m_flRollDelta = random->RandomFloat( -0.5f, 0.5f );
AddSimpleParticle( &particle, hMaterial[random->RandomInt(0,1)] );
}
#else
//
// PC Version
//
VPROF_BUDGET( "FX_Dust", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
pSimple->SetSortOrigin( vecOrigin );
pSimple->SetNearClip( 32, 64 );
SimpleParticle *pParticle;
Vector offset;
int numPuffs = (flSize*0.5f);
if ( numPuffs < 1 )
numPuffs = 1;
if ( numPuffs > 32 )
numPuffs = 32;
float speed = flSpeed * 0.1f;
if ( speed < 0 )
speed = 1.0f;
if (speed > 48.0f )
speed = 48.0f;
//FIXME: Better sampling area
offset = vecOrigin + ( vecDirection * flSize );
//Find area ambient light color and use it to tint smoke
Vector worldLight = WorldGetLightForPoint( offset, true );
PMaterialHandle hMaterial[2];
hMaterial[0] = pSimple->GetPMaterial("particle/particle_smokegrenade");
hMaterial[1] = pSimple->GetPMaterial("particle/particle_noisesphere");
//Throw puffs
for ( int i = 0; i < numPuffs; i++ )
{
offset.Random( -(flSize*0.25f), flSize*0.25f );
offset += vecOrigin + ( vecDirection * flSize );
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), hMaterial[random->RandomInt(0,1)], offset );
if ( pParticle != NULL )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 0.4f, 1.5f );
pParticle->m_vecVelocity = vecDirection * random->RandomFloat( speed*0.5f, speed ) * i;
pParticle->m_vecVelocity[2] = 0.0f;
int color = random->RandomInt( 48, 64 );
pParticle->m_uchColor[0] = (color+16) + ( worldLight[0] * (float) color );
pParticle->m_uchColor[1] = (color+8) + ( worldLight[1] * (float) color );
pParticle->m_uchColor[2] = color + ( worldLight[2] * (float) color );
pParticle->m_uchStartAlpha = random->RandomInt( 32, 128 );
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = random->RandomInt( 2, 8 );
pParticle->m_uchEndSize = random->RandomInt( 24, 48 );
pParticle->m_flRoll = random->RandomInt( 0, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
}
}
#endif // _XBOX
}
class C_TEDust: public C_TEParticleSystem
{
public:
DECLARE_CLASS( C_TEDust, C_TEParticleSystem );
DECLARE_CLIENTCLASS();
C_TEDust();
virtual ~C_TEDust();
public:
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual bool ShouldDraw() { return true; }
public:
float m_flSize;
float m_flSpeed;
Vector m_vecDirection;
protected:
void GetDustColor( Vector &color );
};
IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEDust, DT_TEDust, CTEDust )
RecvPropFloat(RECVINFO(m_flSize)),
RecvPropFloat(RECVINFO(m_flSpeed)),
RecvPropVector(RECVINFO(m_vecDirection)),
END_RECV_TABLE()
//==================================================
// C_TEDust
//==================================================
C_TEDust::C_TEDust()
{
}
C_TEDust::~C_TEDust()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bNewEntity - whether or not to start a new entity
//-----------------------------------------------------------------------------
void C_TEDust::PostDataUpdate( DataUpdateType_t updateType )
{
FX_Dust( m_vecOrigin, m_vecDirection, m_flSize, m_flSpeed );
}
void TE_Dust( IRecipientFilter& filter, float delay,
const Vector &pos, const Vector &dir, float size, float speed )
{
FX_Dust( pos, dir, size, speed );
}

112
cl_dll/c_func_dust.h Normal file
View File

@ -0,0 +1,112 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_FUNC_DUST_H
#define C_FUNC_DUST_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "particles_simple.h"
#include "particle_util.h"
#include "bspflags.h"
// ------------------------------------------------------------------------------------ //
// CDustEffect particle renderer.
// ------------------------------------------------------------------------------------ //
class C_Func_Dust;
class CFuncDustParticle : public Particle
{
public:
Vector m_vVelocity;
float m_flLifetime;
float m_flDieTime;
float m_flSize;
color32 m_Color;
};
class CDustEffect : public CParticleEffect
{
public:
CDustEffect( const char *pDebugName ) : CParticleEffect( pDebugName ) {}
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
C_Func_Dust *m_pDust;
private:
CDustEffect( const CDustEffect & ); // not defined, not accessible
};
// ------------------------------------------------------------------------------------ //
// C_Func_Dust class.
// ------------------------------------------------------------------------------------ //
class C_Func_Dust : public C_BaseEntity
{
public:
DECLARE_CLASS( C_Func_Dust, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_Func_Dust();
virtual ~C_Func_Dust();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink();
virtual bool ShouldDraw();
private:
void AttemptSpawnNewParticle();
// Vars from server.
public:
color32 m_Color;
int m_SpawnRate;
float m_flSizeMin;
float m_flSizeMax;
int m_SpeedMax;
int m_LifetimeMin;
int m_LifetimeMax;
int m_DistMax;
float m_FallSpeed; // extra 'gravity'
public:
int m_DustFlags; // Combination of DUSTFLAGS_
public:
CDustEffect m_Effect;
PMaterialHandle m_hMaterial;
TimedEvent m_Spawner;
private:
C_Func_Dust( const C_Func_Dust & ); // not defined, not accessible
};
#endif // C_FUNC_DUST_H

72
cl_dll/c_func_lod.cpp Normal file
View File

@ -0,0 +1,72 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "view.h"
#include "iviewrender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Vector g_vecRenderOrigin;
extern ConVar r_DoCovertTransitions;
class C_Func_LOD : public C_BaseEntity
{
public:
DECLARE_CLASS( C_Func_LOD, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_Func_LOD();
// C_BaseEntity overrides.
public:
unsigned char GetClientSideFade();
public:
// Replicated vars from the server.
// These are documented in the server-side entity.
public:
float m_fDisappearDist;
};
ConVar lod_TransitionDist("lod_TransitionDist", "800");
ConVar lod_Enable("lod_Enable", "0");
// ------------------------------------------------------------------------- //
// Tables.
// ------------------------------------------------------------------------- //
// Datatable..
IMPLEMENT_CLIENTCLASS_DT(C_Func_LOD, DT_Func_LOD, CFunc_LOD)
RecvPropFloat(RECVINFO(m_fDisappearDist)),
END_RECV_TABLE()
// ------------------------------------------------------------------------- //
// C_Func_LOD implementation.
// ------------------------------------------------------------------------- //
C_Func_LOD::C_Func_LOD()
{
m_fDisappearDist = 5000.0f;
}
//-----------------------------------------------------------------------------
// Purpose: Calculate a fade.
//-----------------------------------------------------------------------------
unsigned char C_Func_LOD::GetClientSideFade()
{
return UTIL_ComputeEntityFade( this, m_fDisappearDist, m_fDisappearDist + lod_TransitionDist.GetFloat(), 1.0f );
}

View File

@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_FuncOccluder : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_FuncOccluder, C_BaseEntity );
// Overrides.
public:
virtual bool ShouldDraw();
virtual int DrawModel( int flags );
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
int m_nOccluderIndex;
bool m_bActive;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncOccluder, DT_FuncOccluder, CFuncOccluder )
RecvPropBool( RECVINFO( m_bActive ) ),
RecvPropInt( RECVINFO(m_nOccluderIndex) ),
END_RECV_TABLE()
void C_FuncOccluder::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
engine->ActivateOccluder( m_nOccluderIndex, m_bActive );
}
bool C_FuncOccluder::ShouldDraw()
{
return false;
}
int C_FuncOccluder::DrawModel( int flags )
{
Assert(0);
return 0;
}

View File

@ -0,0 +1,626 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_smoke_trail.h"
#include "smoke_fog_overlay.h"
#include "engine/IEngineTrace.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SF_EMISSIVE 0x00000001
// ------------------------------------------------------------------------- //
// Definitions
// ------------------------------------------------------------------------- //
static Vector s_FadePlaneDirections[] =
{
Vector( 1,0,0),
Vector(-1,0,0),
Vector(0, 1,0),
Vector(0,-1,0),
Vector(0,0, 1),
Vector(0,0,-1)
};
#define NUM_FADE_PLANES (sizeof(s_FadePlaneDirections)/sizeof(s_FadePlaneDirections[0]))
// ------------------------------------------------------------------------- //
// Classes
// ------------------------------------------------------------------------- //
class C_FuncSmokeVolume : public C_BaseParticleEntity, public IPrototypeAppEffect
{
public:
DECLARE_CLASS( C_FuncSmokeVolume, C_BaseParticleEntity );
DECLARE_CLIENTCLASS();
C_FuncSmokeVolume();
~C_FuncSmokeVolume();
int IsEmissive( void ) { return ( m_spawnflags & SF_EMISSIVE ); }
private:
class SmokeGrenadeParticle : public Particle
{
public:
float m_RotationFactor;
float m_CurRotation;
float m_FadeAlpha; // Set as it moves around.
unsigned char m_ColorInterp; // Amount between min and max colors.
unsigned char m_Color[4];
};
// C_BaseEntity.
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
// IPrototypeAppEffect.
public:
virtual void Start( CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs );
// IParticleEffect.
public:
virtual void Update(float fTimeDelta);
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
virtual void NotifyRemove();
private:
// The SmokeEmitter represents a grid in 3D space.
class SmokeParticleInfo
{
public:
SmokeGrenadeParticle *m_pParticle;
int m_TradeIndex; // -1 if not exchanging yet.
float m_TradeClock; // How long since they started trading.
float m_TradeDuration; // How long the trade will take to finish.
float m_FadeAlpha; // Calculated from nearby world geometry.
unsigned char m_Color[4];
};
inline int GetSmokeParticleIndex(int x, int y, int z)
{
Assert( IsValidXYZCoords( x, y, z ) );
return z*m_xCount*m_yCount+y*m_xCount+x;
}
inline SmokeParticleInfo *GetSmokeParticleInfo(int x, int y, int z)
{
Assert( IsValidXYZCoords( x, y, z ) );
return &m_pSmokeParticleInfos[GetSmokeParticleIndex(x,y,z)];
}
inline void GetParticleInfoXYZ(int index, int &x, int &y, int &z)
{
Assert( index >= 0 && index < m_xCount * m_yCount * m_zCount );
z = index / (m_xCount*m_yCount);
int zIndex = z*m_xCount*m_yCount;
y = (index - zIndex) / m_xCount;
int yIndex = y*m_xCount;
x = index - zIndex - yIndex;
Assert( IsValidXYZCoords( x, y, z ) );
}
inline bool IsValidXYZCoords(int x, int y, int z)
{
return x >= 0 && y >= 0 && z >= 0 && x < m_xCount && y < m_yCount && z < m_zCount;
}
inline Vector GetSmokeParticlePos(int x, int y, int z )
{
return WorldAlignMins() +
Vector( x * m_SpacingRadius * 2 + m_SpacingRadius,
y * m_SpacingRadius * 2 + m_SpacingRadius,
z * m_SpacingRadius * 2 + m_SpacingRadius );
}
inline Vector GetSmokeParticlePosIndex(int index)
{
int x, y, z;
GetParticleInfoXYZ(index, x, y, z);
return GetSmokeParticlePos(x, y, z);
}
// Start filling the smoke volume
void FillVolume();
private:
// State variables from server.
color32 m_Color1;
color32 m_Color2;
char m_MaterialName[255];
float m_ParticleDrawWidth;
float m_ParticleSpacingDistance;
float m_DensityRampSpeed;
float m_RotationSpeed;
float m_MovementSpeed;
float m_Density;
int m_spawnflags;
private:
C_FuncSmokeVolume( const C_FuncSmokeVolume & );
float m_CurrentDensity;
float m_ParticleRadius;
bool m_bStarted;
PMaterialHandle m_MaterialHandle;
SmokeParticleInfo *m_pSmokeParticleInfos;
int m_xCount, m_yCount, m_zCount;
float m_SpacingRadius;
Vector m_MinColor;
Vector m_MaxColor;
Vector m_vLastOrigin;
QAngle m_vLastAngles;
bool m_bFirstUpdate;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncSmokeVolume, DT_FuncSmokeVolume, CFuncSmokeVolume )
RecvPropInt( RECVINFO( m_Color1 ), 0, RecvProxy_IntToColor32 ),
RecvPropInt( RECVINFO( m_Color2 ), 0, RecvProxy_IntToColor32 ),
RecvPropString( RECVINFO( m_MaterialName ) ),
RecvPropFloat( RECVINFO( m_ParticleDrawWidth ) ),
RecvPropFloat( RECVINFO( m_ParticleSpacingDistance ) ),
RecvPropFloat( RECVINFO( m_DensityRampSpeed ) ),
RecvPropFloat( RECVINFO( m_RotationSpeed ) ),
RecvPropFloat( RECVINFO( m_MovementSpeed ) ),
RecvPropFloat( RECVINFO( m_Density ) ),
RecvPropInt( RECVINFO( m_spawnflags ) ),
RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
END_RECV_TABLE()
// Helpers.
// ------------------------------------------------------------------------- //
static inline void InterpColor(unsigned char dest[4], unsigned char src1[4], unsigned char src2[4], float percent)
{
dest[0] = (unsigned char)(src1[0] + (src2[0] - src1[0]) * percent);
dest[1] = (unsigned char)(src1[1] + (src2[1] - src1[1]) * percent);
dest[2] = (unsigned char)(src1[2] + (src2[2] - src1[2]) * percent);
}
static inline int GetWorldPointContents(const Vector &vPos)
{
#if defined(PARTICLEPROTOTYPE_APP)
return 0;
#else
return enginetrace->GetPointContents( vPos );
#endif
}
static inline void WorldTraceLine( const Vector &start, const Vector &end, int contentsMask, trace_t *trace )
{
#if defined(PARTICLEPROTOTYPE_APP)
trace->fraction = 1;
#else
UTIL_TraceLine(start, end, contentsMask, NULL, COLLISION_GROUP_NONE, trace);
#endif
}
static inline Vector EngineGetLightForPoint(const Vector &vPos)
{
#if defined(PARTICLEPROTOTYPE_APP)
return Vector(1,1,1);
#else
return engine->GetLightForPoint(vPos, true);
#endif
}
static inline Vector& EngineGetVecRenderOrigin()
{
#if defined(PARTICLEPROTOTYPE_APP)
static Vector dummy(0,0,0);
return dummy;
#else
extern Vector g_vecRenderOrigin;
return g_vecRenderOrigin;
#endif
}
static inline float& EngineGetSmokeFogOverlayAlpha()
{
#if defined(PARTICLEPROTOTYPE_APP)
static float dummy;
return dummy;
#else
return g_SmokeFogOverlayAlpha;
#endif
}
static inline C_BaseEntity* ParticleGetEntity( int index )
{
#if defined(PARTICLEPROTOTYPE_APP)
return NULL;
#else
return cl_entitylist->GetEnt( index );
#endif
}
// ------------------------------------------------------------------------- //
// C_FuncSmokeVolume
// ------------------------------------------------------------------------- //
C_FuncSmokeVolume::C_FuncSmokeVolume()
{
m_bFirstUpdate = true;
m_vLastOrigin.Init();
m_vLastAngles.Init();
m_pSmokeParticleInfos = NULL;
m_SpacingRadius = 0.0f;;
m_ParticleRadius = 0.0f;
m_MinColor.Init( 1.0, 1.0, 1.0 );
m_MaxColor.Init( 1.0, 1.0, 1.0 );
}
C_FuncSmokeVolume::~C_FuncSmokeVolume()
{
delete [] m_pSmokeParticleInfos;
}
void C_FuncSmokeVolume::OnDataChanged( DataUpdateType_t updateType )
{
m_MinColor[0] = ( 1.0f / 255.0f ) * m_Color1.r;
m_MinColor[1] = ( 1.0f / 255.0f ) * m_Color1.g;
m_MinColor[2] = ( 1.0f / 255.0f ) * m_Color1.b;
m_MaxColor[0] = ( 1.0f / 255.0f ) * m_Color2.r;
m_MaxColor[1] = ( 1.0f / 255.0f ) * m_Color2.g;
m_MaxColor[2] = ( 1.0f / 255.0f ) * m_Color2.b;
m_ParticleRadius = m_ParticleDrawWidth * 0.5f;
m_SpacingRadius = m_ParticleSpacingDistance * 0.5f;
m_ParticleEffect.SetParticleCullRadius( m_ParticleRadius );
// Warning( "m_Density: %f\n", m_Density );
// Warning( "m_MovementSpeed: %f\n", m_MovementSpeed );
if(updateType == DATA_UPDATE_CREATED)
{
Vector size = WorldAlignMaxs() - WorldAlignMins();
m_xCount = 0.5f + ( size.x / ( m_SpacingRadius * 2.0f ) );
m_yCount = 0.5f + ( size.y / ( m_SpacingRadius * 2.0f ) );
m_zCount = 0.5f + ( size.z / ( m_SpacingRadius * 2.0f ) );
m_CurrentDensity = m_Density;
delete [] m_pSmokeParticleInfos;
m_pSmokeParticleInfos = new SmokeParticleInfo[m_xCount * m_yCount * m_zCount];
Start( ParticleMgr(), NULL );
}
BaseClass::OnDataChanged( updateType );
}
void C_FuncSmokeVolume::Start( CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs )
{
if( !pParticleMgr->AddEffect( &m_ParticleEffect, this ) )
return;
m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial( m_MaterialName );
FillVolume();
m_bStarted = true;
}
void C_FuncSmokeVolume::Update( float fTimeDelta )
{
// Update our world space bbox if we've moved at all.
// We do this manually because sometimes people make HUGE bboxes, and if they're constantly changing because their
// particles wander outside the current bounds sometimes, it'll be linking them into all the leaves repeatedly.
const Vector &curOrigin = GetAbsOrigin();
const QAngle &curAngles = GetAbsAngles();
if ( !VectorsAreEqual( curOrigin, m_vLastOrigin, 0.1 ) ||
fabs( curAngles.x - m_vLastAngles.x ) > 0.1 ||
fabs( curAngles.y - m_vLastAngles.y ) > 0.1 ||
fabs( curAngles.z - m_vLastAngles.z ) > 0.1 ||
m_bFirstUpdate )
{
m_bFirstUpdate = false;
m_vLastAngles = curAngles;
m_vLastOrigin = curOrigin;
Vector vWorldMins, vWorldMaxs;
CollisionProp()->WorldSpaceAABB( &vWorldMins, &vWorldMaxs );
vWorldMins -= Vector( m_ParticleRadius, m_ParticleRadius, m_ParticleRadius );
vWorldMaxs += Vector( m_ParticleRadius, m_ParticleRadius, m_ParticleRadius );
m_ParticleEffect.SetBBox( vWorldMins, vWorldMaxs );
}
// lerp m_CurrentDensity towards m_Density at a rate of m_DensityRampSpeed
if( m_CurrentDensity < m_Density )
{
m_CurrentDensity += m_DensityRampSpeed * fTimeDelta;
if( m_CurrentDensity > m_Density )
{
m_CurrentDensity = m_Density;
}
}
else if( m_CurrentDensity > m_Density )
{
m_CurrentDensity -= m_DensityRampSpeed * fTimeDelta;
if( m_CurrentDensity < m_Density )
{
m_CurrentDensity = m_Density;
}
}
if( m_CurrentDensity == 0.0f )
{
return;
}
// This is used to randomize the direction it chooses to move a particle in.
int offsetLookup[3] = {-1,0,1};
float tradeDurationMax = m_ParticleSpacingDistance / ( m_MovementSpeed + 0.1f );
float tradeDurationMin = tradeDurationMax * 0.5f;
if ( IS_NAN( tradeDurationMax ) || IS_NAN( tradeDurationMin ) )
return;
// Warning( "tradeDuration: [%f,%f]\n", tradeDurationMin, tradeDurationMax );
// Update all the moving traders and establish new ones.
int nTotal = m_xCount * m_yCount * m_zCount;
for( int i=0; i < nTotal; i++ )
{
SmokeParticleInfo *pInfo = &m_pSmokeParticleInfos[i];
if(!pInfo->m_pParticle)
continue;
if(pInfo->m_TradeIndex == -1)
{
pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha;
pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0];
pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1];
pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2];
// Is there an adjacent one that's not trading?
int x, y, z;
GetParticleInfoXYZ(i, x, y, z);
int xCountOffset = rand();
int yCountOffset = rand();
int zCountOffset = rand();
bool bFound = false;
for(int xCount=0; xCount < 3 && !bFound; xCount++)
{
for(int yCount=0; yCount < 3 && !bFound; yCount++)
{
for(int zCount=0; zCount < 3; zCount++)
{
int testX = x + offsetLookup[(xCount+xCountOffset) % 3];
int testY = y + offsetLookup[(yCount+yCountOffset) % 3];
int testZ = z + offsetLookup[(zCount+zCountOffset) % 3];
if(testX == x && testY == y && testZ == z)
continue;
if(IsValidXYZCoords(testX, testY, testZ))
{
SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ);
if(pOther->m_pParticle && pOther->m_TradeIndex == -1)
{
// Ok, this one is looking to trade also.
pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ);
pOther->m_TradeIndex = i;
pInfo->m_TradeClock = pOther->m_TradeClock = 0;
pOther->m_TradeDuration = pInfo->m_TradeDuration = FRand( tradeDurationMin, tradeDurationMax );
bFound = true;
break;
}
}
}
}
}
}
else
{
SmokeParticleInfo *pOther = &m_pSmokeParticleInfos[pInfo->m_TradeIndex];
assert(pOther->m_TradeIndex == i);
// This makes sure the trade only gets updated once per frame.
if(pInfo < pOther)
{
// Increment the trade clock..
pInfo->m_TradeClock = (pOther->m_TradeClock += fTimeDelta);
int x, y, z;
GetParticleInfoXYZ(i, x, y, z);
Vector myPos = GetSmokeParticlePos(x, y, z);
int otherX, otherY, otherZ;
GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ);
Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ);
// Is the trade finished?
if(pInfo->m_TradeClock >= pInfo->m_TradeDuration)
{
pInfo->m_TradeIndex = pOther->m_TradeIndex = -1;
pInfo->m_pParticle->m_Pos = otherPos;
pOther->m_pParticle->m_Pos = myPos;
SmokeGrenadeParticle *temp = pInfo->m_pParticle;
pInfo->m_pParticle = pOther->m_pParticle;
pOther->m_pParticle = temp;
}
else
{
// Ok, move them closer.
float percent = (float)cos(pInfo->m_TradeClock * 2 * 1.57079632f / pInfo->m_TradeDuration);
percent = percent * 0.5 + 0.5;
pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * (1 - percent);
pOther->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * percent;
InterpColor(pInfo->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, 1-percent);
InterpColor(pOther->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, percent);
pInfo->m_pParticle->m_Pos = myPos + (otherPos - myPos) * (1 - percent);
pOther->m_pParticle->m_Pos = myPos + (otherPos - myPos) * percent;
}
}
}
}
}
void C_FuncSmokeVolume::RenderParticles( CParticleRenderIterator *pIterator )
{
if ( m_CurrentDensity == 0 )
return;
const SmokeGrenadeParticle *pParticle = (const SmokeGrenadeParticle*)pIterator->GetFirst();
while ( pParticle )
{
Vector renderPos = pParticle->m_Pos;
// Fade out globally.
float alpha = m_CurrentDensity;
// Apply the precalculated fade alpha from world geometry.
alpha *= pParticle->m_FadeAlpha;
// TODO: optimize this whole routine!
Vector color = m_MinColor + (m_MaxColor - m_MinColor) * (pParticle->m_ColorInterp / 255.1f);
if ( IsEmissive() )
{
color.x += pParticle->m_Color[0] / 255.0f;
color.y += pParticle->m_Color[1] / 255.0f;
color.z += pParticle->m_Color[2] / 255.0f;
color.x = clamp( color.x, 0.0f, 1.0f );
color.y = clamp( color.y, 0.0f, 1.0f );
color.z = clamp( color.z, 0.0f, 1.0f );
}
else
{
color.x *= pParticle->m_Color[0] / 255.0f;
color.y *= pParticle->m_Color[1] / 255.0f;
color.z *= pParticle->m_Color[2] / 255.0f;
}
Vector tRenderPos;
TransformParticle( ParticleMgr()->GetModelView(), renderPos, tRenderPos );
float sortKey = 1;//tRenderPos.z;
RenderParticle_ColorSizeAngle(
pIterator->GetParticleDraw(),
tRenderPos,
color,
alpha * GetAlphaDistanceFade(tRenderPos, 10, 30), // Alpha
m_ParticleRadius,
pParticle->m_CurRotation
);
pParticle = (const SmokeGrenadeParticle*)pIterator->GetNext( sortKey );
}
}
void C_FuncSmokeVolume::SimulateParticles( CParticleSimulateIterator *pIterator )
{
if ( m_CurrentDensity == 0 )
return;
SmokeGrenadeParticle *pParticle = (SmokeGrenadeParticle*)pIterator->GetFirst();
while ( pParticle )
{
pParticle->m_CurRotation += pParticle->m_RotationFactor * ( M_PI / 180.0f ) * m_RotationSpeed * pIterator->GetTimeDelta();
pParticle = (SmokeGrenadeParticle*)pIterator->GetNext();
}
}
void C_FuncSmokeVolume::NotifyRemove()
{
m_xCount = m_yCount = m_zCount = 0;
}
void C_FuncSmokeVolume::FillVolume()
{
Vector vPos;
for(int x=0; x < m_xCount; x++)
{
for(int y=0; y < m_yCount; y++)
{
for(int z=0; z < m_zCount; z++)
{
vPos = GetSmokeParticlePos( x, y, z );
if(SmokeParticleInfo *pInfo = GetSmokeParticleInfo(x,y,z))
{
int contents = GetWorldPointContents(vPos);
if(contents & CONTENTS_SOLID)
{
pInfo->m_pParticle = NULL;
}
else
{
SmokeGrenadeParticle *pParticle =
(SmokeGrenadeParticle*)m_ParticleEffect.AddParticle(sizeof(SmokeGrenadeParticle), m_MaterialHandle);
if(pParticle)
{
pParticle->m_Pos = vPos;
pParticle->m_ColorInterp = (unsigned char)((rand() * 255) / RAND_MAX);
pParticle->m_RotationFactor = FRand( -1.0f, 1.0f ); // Rotation factor.
pParticle->m_CurRotation = FRand( -m_RotationSpeed, m_RotationSpeed );
}
#ifdef _DEBUG
int testX, testY, testZ;
int index = GetSmokeParticleIndex(x,y,z);
GetParticleInfoXYZ(index, testX, testY, testZ);
assert(testX == x && testY == y && testZ == z);
#endif
Vector vColor = EngineGetLightForPoint(vPos);
pInfo->m_Color[0] = LinearToTexture( vColor.x );
pInfo->m_Color[1] = LinearToTexture( vColor.y );
pInfo->m_Color[2] = LinearToTexture( vColor.z );
// Cast some rays and if it's too close to anything, fade its alpha down.
pInfo->m_FadeAlpha = 1;
for(int i=0; i < NUM_FADE_PLANES; i++)
{
trace_t trace;
WorldTraceLine(vPos, vPos + s_FadePlaneDirections[i] * 100, MASK_SOLID_BRUSHONLY, &trace);
if(trace.fraction < 1.0f)
{
float dist = DotProduct(trace.plane.normal, vPos) - trace.plane.dist;
if(dist < 0)
{
pInfo->m_FadeAlpha = 0;
}
else if(dist < m_ParticleRadius)
{
float alphaScale = dist / m_ParticleRadius;
alphaScale *= alphaScale * alphaScale;
pInfo->m_FadeAlpha *= alphaScale;
}
}
}
pInfo->m_pParticle = pParticle;
pInfo->m_TradeIndex = -1;
}
}
}
}
}
}

View File

@ -0,0 +1,119 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseentity.h"
#include "soundinfo.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// An entity which emits other entities at points
//-----------------------------------------------------------------------------
class C_FuncTrackTrain : public C_BaseEntity
{
public:
DECLARE_CLASS( C_FuncTrackTrain, C_BaseEntity );
DECLARE_CLIENTCLASS();
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
private:
int m_nLongAxis;
float m_flRadius;
float m_flLineLength;
};
//-----------------------------------------------------------------------------
// Datatable
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_FuncTrackTrain, DT_FuncTrackTrain, CFuncTrackTrain )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Sound spatialization
//-----------------------------------------------------------------------------
void C_FuncTrackTrain::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if (updateType == DATA_UPDATE_CREATED)
{
// Compute the cross-sectional area and dimension and length of the line segment
int nIndex1, nIndex2;
const Vector &vecOBBSize = CollisionProp()->OBBSize();
if ( ( vecOBBSize.x > vecOBBSize.y ) && ( vecOBBSize.x > vecOBBSize.z ) )
{
m_nLongAxis = 0;
nIndex1 = 1; nIndex2 = 2;
}
else if ( vecOBBSize.y > vecOBBSize.z )
{
m_nLongAxis = 1;
nIndex1 = 0; nIndex2 = 2;
}
else
{
m_nLongAxis = 2;
nIndex1 = 0; nIndex2 = 1;
}
m_flRadius = sqrt( vecOBBSize[nIndex1] * vecOBBSize[nIndex1] + vecOBBSize[nIndex2] * vecOBBSize[nIndex2] ) * 0.5f;
m_flLineLength = vecOBBSize[m_nLongAxis];
}
}
//-----------------------------------------------------------------------------
// Sound spatialization
//-----------------------------------------------------------------------------
bool C_FuncTrackTrain::GetSoundSpatialization( SpatializationInfo_t& info )
{
// Out of PVS
if ( IsDormant() )
return false;
if ( info.pflRadius )
{
*info.pflRadius = m_flRadius;
}
if ( info.pOrigin )
{
Vector vecStart, vecEnd, vecWorldDir;
Vector vecDir = vec3_origin;
vecDir[m_nLongAxis] = 1.0f;
VectorRotate( vecDir, EntityToWorldTransform(), vecWorldDir );
VectorMA( WorldSpaceCenter(), -0.5f * m_flLineLength, vecWorldDir, vecStart );
VectorMA( vecStart, m_flLineLength, vecWorldDir, vecEnd );
float t;
CalcClosestPointOnLine( info.info.vListenerOrigin, vecStart, vecEnd, *info.pOrigin, &t );
if ( t < 0.0f )
{
*info.pOrigin = vecStart;
}
else if ( t > 1.0f )
{
*info.pOrigin = vecEnd;
}
}
if ( info.pAngles )
{
VectorCopy( CollisionProp()->GetCollisionAngles(), *info.pAngles );
}
return true;
}

133
cl_dll/c_gib.cpp Normal file
View File

@ -0,0 +1,133 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "vcollide_parse.h"
#include "c_gib.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//NOTENOTE: This is not yet coupled with the server-side implementation of CGib
// This is only a client-side version of gibs at the moment
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_Gib::~C_Gib( void )
{
VPhysicsDestroyObject();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszModelName -
// vecOrigin -
// vecForceDir -
// vecAngularImp -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
C_Gib *C_Gib::CreateClientsideGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float flLifetime )
{
C_Gib *pGib = new C_Gib;
if ( pGib == NULL )
return NULL;
if ( pGib->InitializeGib( pszModelName, vecOrigin, vecForceDir, vecAngularImp, flLifetime ) == false )
return NULL;
return pGib;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszModelName -
// vecOrigin -
// vecForceDir -
// vecAngularImp -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_Gib::InitializeGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float flLifetime )
{
if ( InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
Release();
return false;
}
SetAbsOrigin( vecOrigin );
SetCollisionGroup( COLLISION_GROUP_DEBRIS );
solid_t tmpSolid;
PhysModelParseSolid( tmpSolid, this, GetModelIndex() );
m_pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &tmpSolid );
if ( m_pPhysicsObject )
{
float flForce = m_pPhysicsObject->GetMass();
vecForceDir *= flForce;
m_pPhysicsObject->ApplyForceOffset( vecForceDir, GetAbsOrigin() );
m_pPhysicsObject->SetCallbackFlags( m_pPhysicsObject->GetCallbackFlags() | CALLBACK_GLOBAL_TOUCH | CALLBACK_GLOBAL_TOUCH_STATIC );
}
else
{
// failed to create a physics object
Release();
return false;
}
SetNextClientThink( gpGlobals->curtime + flLifetime );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_Gib::ClientThink( void )
{
SetRenderMode( kRenderTransAlpha );
m_nRenderFX = kRenderFxFadeFast;
if ( m_clrRender->a == 0 )
{
#ifdef HL2_CLIENT_DLL
s_AntlionGibManager.RemoveGib( this );
#endif
Release();
return;
}
SetNextClientThink( gpGlobals->curtime + 1.0f );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOther -
//-----------------------------------------------------------------------------
void C_Gib::StartTouch( C_BaseEntity *pOther )
{
// Limit the amount of times we can bounce
if ( m_flTouchDelta < gpGlobals->curtime )
{
HitSurface( pOther );
m_flTouchDelta = gpGlobals->curtime + 0.1f;
}
BaseClass::StartTouch( pOther );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOther -
//-----------------------------------------------------------------------------
void C_Gib::HitSurface( C_BaseEntity *pOther )
{
//TODO: Implement splatter or effects in child versions
}

64
cl_dll/c_gib.h Normal file
View File

@ -0,0 +1,64 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_GIB_H
#define C_GIB_H
#ifdef _WIN32
#pragma once
#endif
#define DEFAULT_GIB_LIFETIME 4.0f
// Base client gibs
class C_Gib : public C_BaseAnimating
{
typedef C_BaseAnimating BaseClass;
public:
C_Gib::~C_Gib( void );
static C_Gib *CreateClientsideGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float flLifetime = DEFAULT_GIB_LIFETIME );
bool InitializeGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float flLifetime = DEFAULT_GIB_LIFETIME );
void ClientThink( void );
void StartTouch( C_BaseEntity *pOther );
virtual void HitSurface( C_BaseEntity *pOther );
protected:
float m_flTouchDelta; // Amount of time that must pass before another touch function can be called
};
#ifdef HL2_CLIENT_DLL
class CAntlionGibManager : public CAutoGameSystemPerFrame
{
public:
CAntlionGibManager( char const *name ) : CAutoGameSystemPerFrame( name )
{
}
// Methods of IGameSystem
virtual void Update( float frametime );
virtual void LevelInitPreEntity( void );
void AddGib( C_BaseEntity *pEntity );
void RemoveGib( C_BaseEntity *pEntity );
private:
typedef CHandle<C_BaseEntity> CGibHandle;
CUtlLinkedList< CGibHandle > m_LRU;
};
extern CAntlionGibManager s_AntlionGibManager;
#endif
#endif // C_GIB_H

349
cl_dll/c_hairball.cpp Normal file
View File

@ -0,0 +1,349 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "simple_physics.h"
#include "vmatrix.h"
#include "beamdraw.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_Hairball : public C_BaseEntity
{
DECLARE_CLASS( C_Hairball, C_BaseEntity );
private:
class CHairballDelegate : public CSimplePhysics::IHelper
{
public:
virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
C_Hairball *m_pParent;
};
public:
C_Hairball();
void Init();
// IClientThinkable.
public:
virtual void ClientThink();
// IClientRenderable.
public:
virtual int DrawModel( int flags );
public:
float m_flSphereRadius;
int m_nHairs;
int m_nNodesPerHair;
float m_flSpringDist; // = hair length / (m_nNodesPerHair-1)
CUtlVector<CSimplePhysics::CNode> m_Nodes; // This is m_nHairs * m_nNodesPerHair large.
CUtlVector<Vector> m_HairPositions; // Untransformed base hair positions, distributed on the sphere.
CUtlVector<Vector> m_TransformedHairPositions; // Transformed base hair positions, distributed on the sphere.
CHairballDelegate m_Delegate;
CSimplePhysics m_Physics;
IMaterial *m_pMaterial;
// Super sophisticated AI.
float m_flSitStillTime;
Vector m_vMoveDir;
float m_flSpinDuration;
float m_flCurSpinTime;
float m_flSpinRateX, m_flSpinRateY;
bool m_bFirstThink;
};
void C_Hairball::CHairballDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel )
{
pAccel->Init( 0, 0, -1500 );
}
void C_Hairball::CHairballDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
{
int nSegments = m_pParent->m_nNodesPerHair - 1;
float flSpringDistSqr = m_pParent->m_flSpringDist * m_pParent->m_flSpringDist;
static int nIterations = 1;
for( int iIteration=0; iIteration < nIterations; iIteration++ )
{
for ( int iHair=0; iHair < m_pParent->m_nHairs; iHair++ )
{
CSimplePhysics::CNode *pBase = &pNodes[iHair * m_pParent->m_nNodesPerHair];
for( int i=0; i < nSegments; i++ )
{
Vector &vNode1 = pBase[i].m_vPos;
Vector &vNode2 = pBase[i+1].m_vPos;
Vector vTo = vNode1 - vNode2;
float flDistSqr = vTo.LengthSqr();
if( flDistSqr > flSpringDistSqr )
{
float flDist = (float)sqrt( flDistSqr );
vTo *= 1 - (m_pParent->m_flSpringDist / flDist);
vNode1 -= vTo * 0.5f;
vNode2 += vTo * 0.5f;
}
}
// Lock the base of each hair to the right spot.
pBase->m_vPos = m_pParent->m_TransformedHairPositions[iHair];
}
}
}
C_Hairball::C_Hairball()
{
m_nHairs = 100;
m_nNodesPerHair = 3;
float flHairLength = 20;
m_flSpringDist = flHairLength / (m_nNodesPerHair - 1);
m_Nodes.SetSize( m_nHairs * m_nNodesPerHair );
m_HairPositions.SetSize( m_nHairs );
m_TransformedHairPositions.SetSize( m_nHairs );
m_flSphereRadius = 20;
m_vMoveDir.Init();
m_flSpinDuration = 1;
m_flCurSpinTime = 0;
m_flSpinRateX = m_flSpinRateY = 0;
// Distribute on the sphere (need a better random distribution for the sphere).
for ( int i=0; i < m_HairPositions.Count(); i++ )
{
float theta = RandomFloat( -M_PI, M_PI );
float phi = RandomFloat( -M_PI/2, M_PI/2 );
float cosPhi = cos( phi );
m_HairPositions[i].Init(
cos(theta) * cosPhi * m_flSphereRadius,
sin(theta) * cosPhi * m_flSphereRadius,
sin(phi) * m_flSphereRadius );
}
m_Delegate.m_pParent = this;
m_Physics.Init( 1.0 / 20 ); // NOTE: PLAY WITH THIS FOR EFFICIENCY
m_pMaterial = NULL;
m_bFirstThink = true;
}
void C_Hairball::Init()
{
ClientEntityList().AddNonNetworkableEntity( this );
ClientThinkList()->SetNextClientThink( GetClientHandle(), CLIENT_THINK_ALWAYS );
AddToLeafSystem( RENDER_GROUP_OPAQUE_ENTITY );
m_pMaterial = materials->FindMaterial( "cable/cable", TEXTURE_GROUP_OTHER );
m_flSitStillTime = 5;
}
void C_Hairball::ClientThink()
{
// Do some AI-type stuff.. move the entity around.
//C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
//m_vecAngles = SetAbsAngles( pPlayer->GetAbsAngles() ); // copy player angles.
Assert( !GetMoveParent() );
// Sophisticated AI.
m_flCurSpinTime += gpGlobals->frametime;
if ( m_flCurSpinTime < m_flSpinDuration )
{
float div = m_flCurSpinTime / m_flSpinDuration;
QAngle angles = GetLocalAngles();
angles.x += m_flSpinRateX * SmoothCurve( div );
angles.y += m_flSpinRateY * SmoothCurve( div );
SetLocalAngles( angles );
}
else
{
// Flip between stopped and starting.
if ( fabs( m_flSpinRateX ) > 0.01f )
{
m_flSpinRateX = m_flSpinRateY = 0;
m_flSpinDuration = RandomFloat( 1, 2 );
}
else
{
static float flXSpeed = 3;
static float flYSpeed = flXSpeed * 0.1f;
m_flSpinRateX = RandomFloat( -M_PI*flXSpeed, M_PI*flXSpeed );
m_flSpinRateY = RandomFloat( -M_PI*flYSpeed, M_PI*flYSpeed );
m_flSpinDuration = RandomFloat( 1, 4 );
}
m_flCurSpinTime = 0;
}
if ( m_flSitStillTime > 0 )
{
m_flSitStillTime -= gpGlobals->frametime;
if ( m_flSitStillTime <= 0 )
{
// Shoot out some random lines and find the longest one.
m_vMoveDir.Init( 1, 0, 0 );
float flLongestFraction = 0;
for ( int i=0; i < 15; i++ )
{
Vector vDir( RandomFloat( -1, 1 ), RandomFloat( -1, 1 ), RandomFloat( -1, 1 ) );
VectorNormalize( vDir );
trace_t trace;
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vDir * 10000, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &trace );
if ( trace.fraction != 1.0 )
{
if ( trace.fraction > flLongestFraction )
{
flLongestFraction = trace.fraction;
m_vMoveDir = vDir;
}
}
}
m_vMoveDir *= 650; // set speed.
m_flSitStillTime = -1; // Move in this direction..
}
}
else
{
// Move in the specified direction.
Vector vEnd = GetAbsOrigin() + m_vMoveDir * gpGlobals->frametime;
trace_t trace;
UTIL_TraceLine( GetAbsOrigin(), vEnd, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &trace );
if ( trace.fraction < 1 )
{
// Ok, stop moving.
m_flSitStillTime = RandomFloat( 1, 3 );
}
else
{
SetLocalOrigin( GetLocalOrigin() + m_vMoveDir * gpGlobals->frametime );
}
}
// Transform the base hair positions so we can lock them down.
VMatrix mTransform;
mTransform.SetupMatrixOrgAngles( GetLocalOrigin(), GetLocalAngles() );
for ( int i=0; i < m_HairPositions.Count(); i++ )
{
Vector3DMultiplyPosition( mTransform, m_HairPositions[i], m_TransformedHairPositions[i] );
}
if ( m_bFirstThink )
{
m_bFirstThink = false;
for ( int i=0; i < m_HairPositions.Count(); i++ )
{
for ( int j=0; j < m_nNodesPerHair; j++ )
{
m_Nodes[i*m_nNodesPerHair+j].Init( m_TransformedHairPositions[i] );
}
}
}
// Simulate the physics and apply constraints.
m_Physics.Simulate( m_Nodes.Base(), m_Nodes.Count(), &m_Delegate, gpGlobals->frametime, 0.98 );
}
int C_Hairball::DrawModel( int flags )
{
if ( !m_pMaterial )
return 0;
for ( int iHair=0; iHair < m_nHairs; iHair++ )
{
CSimplePhysics::CNode *pBase = &m_Nodes[iHair * m_nNodesPerHair];
CBeamSegDraw beamDraw;
beamDraw.Start( m_nNodesPerHair-1, m_pMaterial );
for ( int i=0; i < m_nNodesPerHair; i++ )
{
CBeamSeg seg;
seg.m_vPos = pBase[i].m_vPredicted;
seg.m_vColor.Init( 0, 0, 0 );
seg.m_flTexCoord = 0;
static float flHairWidth = 1;
seg.m_flWidth = flHairWidth;
seg.m_flAlpha = 0;
beamDraw.NextSeg( &seg );
}
beamDraw.End();
}
return 1;
}
void CreateHairballCallback()
{
for ( int i=0; i < 20; i++ )
{
C_Hairball *pHairball = new C_Hairball;
pHairball->Init();
// Put it a short distance in front of the player.
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
return;
Vector vForward;
AngleVectors( pPlayer->GetAbsAngles(), &vForward );
pHairball->SetLocalOrigin( pPlayer->GetAbsOrigin() + vForward * 300 + RandomVector( 0, 100 ) );
}
}
ConCommand cc_CreateHairball( "CreateHairball", CreateHairballCallback, 0, FCVAR_CHEAT );

1416
cl_dll/c_impact_effects.cpp Normal file

File diff suppressed because it is too large Load Diff

108
cl_dll/c_impact_effects.h Normal file
View File

@ -0,0 +1,108 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_IMPACT_EFFECTS_H
#define C_IMPACT_EFFECTS_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: DustParticle emitter
//-----------------------------------------------------------------------------
class CDustParticle : public CSimpleEmitter
{
public:
CDustParticle( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
//Create
static CDustParticle *Create( const char *pDebugName="dust" )
{
return new CDustParticle( pDebugName );
}
//Roll
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta )
{
pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta;
pParticle->m_flRollDelta += pParticle->m_flRollDelta * ( timeDelta * -8.0f );
#ifdef _XBOX
//Cap the minimum roll
if ( fabs( pParticle->m_flRollDelta ) < 0.1f )
{
pParticle->m_flRollDelta = ( pParticle->m_flRollDelta > 0.0f ) ? 0.1f : -0.1f;
}
#else
if ( fabs( pParticle->m_flRollDelta ) < 0.5f )
{
pParticle->m_flRollDelta = ( pParticle->m_flRollDelta > 0.0f ) ? 0.5f : -0.5f;
}
#endif // _XBOX
return pParticle->m_flRoll;
}
//Velocity
virtual void UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
{
Vector saveVelocity = pParticle->m_vecVelocity;
//Decellerate
static float dtime;
static float decay;
if ( dtime != timeDelta )
{
dtime = timeDelta;
float expected = 0.5;
decay = exp( log( 0.0001f ) * dtime / expected );
}
pParticle->m_vecVelocity = pParticle->m_vecVelocity * decay;
#ifdef _XBOX
//Cap the minimum speed
if ( pParticle->m_vecVelocity.LengthSqr() < (8.0f*8.0f) )
{
VectorNormalize( saveVelocity );
pParticle->m_vecVelocity = saveVelocity * 8.0f;
}
#else
if ( pParticle->m_vecVelocity.LengthSqr() < (32.0f*32.0f) )
{
VectorNormalize( saveVelocity );
pParticle->m_vecVelocity = saveVelocity * 32.0f;
}
#endif // _XBOX
}
//Alpha
virtual float UpdateAlpha( const SimpleParticle *pParticle )
{
float tLifetime = pParticle->m_flLifetime / pParticle->m_flDieTime;
float ramp = 1.0f - tLifetime;
//Non-linear fade
if ( ramp < 0.75f )
ramp *= ramp;
return ramp;
}
private:
CDustParticle( const CDustParticle & ); // not defined, not accessible
};
void GetColorForSurface( trace_t *trace, Vector *color );
#include "tier0/memdbgoff.h"
#endif // C_IMPACT_EFFECTS_H

214
cl_dll/c_lightglow.cpp Normal file
View File

@ -0,0 +1,214 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "glow_overlay.h"
#include "view.h"
#include "c_pixel_visibility.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_LightGlowOverlay : public CGlowOverlay
{
public:
virtual void CalcSpriteColorAndSize( float flDot, CGlowSprite *pSprite, float *flHorzSize, float *flVertSize, Vector *vColor )
{
*flHorzSize = pSprite->m_flHorzSize;
*flVertSize = pSprite->m_flVertSize;
Vector viewDir = ( CurrentViewOrigin() - m_vecOrigin );
float distToViewer = VectorNormalize( viewDir );
if ( m_bOneSided )
{
if ( DotProduct( viewDir, m_vecDirection ) < 0.0f )
{
*vColor = Vector(0,0,0);
return;
}
}
float fade;
// See if we're in the outer fade distance range
if ( m_nOuterMaxDist > m_nMaxDist && distToViewer > m_nMaxDist )
{
fade = RemapValClamped( distToViewer, m_nMaxDist, m_nOuterMaxDist, 1.0f, 0.0f );
}
else
{
fade = RemapValClamped( distToViewer, m_nMinDist, m_nMaxDist, 0.0f, 1.0f );
}
*vColor = pSprite->m_vColor * fade * m_flGlowObstructionScale;
}
void SetOrigin( const Vector &origin ) { m_vecOrigin = origin; }
void SetFadeDistances( int minDist, int maxDist, int outerMaxDist )
{
m_nMinDist = minDist;
m_nMaxDist = maxDist;
m_nOuterMaxDist = outerMaxDist;
}
void SetOneSided( bool state = true ) { m_bOneSided = state; }
void SetModulateByDot( bool state = true ) { m_bModulateByDot = state; }
void SetDirection( const Vector &dir ) { m_vecDirection = dir; VectorNormalize( m_vecDirection ); }
protected:
Vector m_vecOrigin;
Vector m_vecDirection;
int m_nMinDist;
int m_nMaxDist;
int m_nOuterMaxDist;
bool m_bOneSided;
bool m_bModulateByDot;
};
class C_LightGlow : public C_BaseEntity
{
public:
DECLARE_CLASS( C_LightGlow, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_LightGlow();
// C_BaseEntity overrides.
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual void Simulate( void );
public:
int m_nHorizontalSize;
int m_nVerticalSize;
int m_nMinDist;
int m_nMaxDist;
int m_nOuterMaxDist;
int m_spawnflags;
C_LightGlowOverlay m_Glow;
float m_flGlowProxySize;
};
static void RecvProxy_HDRColorScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_LightGlow *pLightGlow = ( C_LightGlow * )pStruct;
pLightGlow->m_Glow.m_flHDRColorScale = pData->m_Value.m_Float;
}
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_LightGlow, DT_LightGlow, CLightGlow )
RecvPropInt( RECVINFO(m_clrRender), 0, RecvProxy_IntToColor32 ),
RecvPropInt( RECVINFO( m_nHorizontalSize ) ),
RecvPropInt( RECVINFO( m_nVerticalSize ) ),
RecvPropInt( RECVINFO( m_nMinDist ) ),
RecvPropInt( RECVINFO( m_nMaxDist ) ),
RecvPropInt( RECVINFO( m_nOuterMaxDist ) ),
RecvPropInt( RECVINFO( m_spawnflags ) ),
RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ),
RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
RecvPropFloat(RECVINFO(m_flGlowProxySize)),
RecvPropFloat("HDRColorScale", 0, SIZEOF_IGNORE, 0, RecvProxy_HDRColorScale),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
C_LightGlow::C_LightGlow() :
m_nHorizontalSize( 0 ), m_nVerticalSize( 0 ), m_nMinDist( 0 ), m_nMaxDist( 0 )
{
m_Glow.m_bDirectional = false;
m_Glow.m_bInSky = false;
}
void C_LightGlow::Simulate( void )
{
BaseClass::Simulate();
m_Glow.m_vPos = GetAbsOrigin();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_LightGlow::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
m_Glow.m_vPos = GetAbsOrigin();
if ( updateType == DATA_UPDATE_CREATED )
{
// Setup our flare.
Vector vColor(
m_clrRender->r / 255.0f,
m_clrRender->g / 255.0f,
m_clrRender->b / 255.0f );
m_Glow.m_nSprites = 1;
m_Glow.m_Sprites[0].m_flVertSize = (float) m_nVerticalSize;
m_Glow.m_Sprites[0].m_flHorzSize = (float) m_nHorizontalSize;
m_Glow.m_Sprites[0].m_vColor = vColor;
m_Glow.SetOrigin( GetAbsOrigin() );
m_Glow.SetFadeDistances( m_nMinDist, m_nMaxDist, m_nOuterMaxDist );
m_Glow.m_flProxyRadius = m_flGlowProxySize;
if ( m_spawnflags & SF_LIGHTGLOW_DIRECTIONAL )
{
m_Glow.SetOneSided();
}
m_Glow.Activate();
}
else if ( updateType == DATA_UPDATE_DATATABLE_CHANGED ) //Right now only color should change.
{
// Setup our flare.
Vector vColor(
m_clrRender->r / 255.0f,
m_clrRender->g / 255.0f,
m_clrRender->b / 255.0f );
m_Glow.m_Sprites[0].m_vColor = vColor;
}
Vector forward;
AngleVectors( GetAbsAngles(), &forward, NULL, NULL );
m_Glow.SetDirection( forward );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_LightGlow::NotifyShouldTransmit( ShouldTransmitState_t state )
{
BaseClass::NotifyShouldTransmit( state );
// Turn off
if ( state == SHOULDTRANSMIT_END )
{
m_Glow.Deactivate();
}
// Turn on
if ( state == SHOULDTRANSMIT_START )
{
m_Glow.Activate();
}
}

View File

@ -0,0 +1,218 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "particle_prototype.h"
#include "particle_util.h"
#include "baseparticleentity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// ------------------------------------------------------------------------- //
// Definitions
// ------------------------------------------------------------------------- //
#define NUM_MOVIEEXPLOSION_EMITTERS 50
#define EXPLOSION_EMITTER_LIFETIME 3
#define EMITTED_PARTICLE_LIFETIME 1
// ------------------------------------------------------------------------- //
// Classes
// ------------------------------------------------------------------------- //
class MovieExplosionEmitter
{
public:
Vector m_Pos;
Vector m_Velocity;
float m_Lifetime;
TimedEvent m_ParticleSpawn;
};
class C_MovieExplosion : public C_BaseParticleEntity, public IPrototypeAppEffect
{
public:
DECLARE_CLASS( C_MovieExplosion, C_BaseParticleEntity );
DECLARE_CLIENTCLASS();
C_MovieExplosion();
~C_MovieExplosion();
// C_BaseEntity.
public:
virtual void OnDataChanged(DataUpdateType_t updateType);
// IPrototypeAppEffect.
public:
virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
// IParticleEffect.
public:
virtual void Update(float fTimeDelta);
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
public:
MovieExplosionEmitter m_Emitters[NUM_MOVIEEXPLOSION_EMITTERS];
float m_EmitterLifetime;
CParticleMgr *m_pParticleMgr;
PMaterialHandle m_iFireballMaterial;
// Setup for temporary usage in SimulateAndRender.
float m_EmitterAlpha;
private:
C_MovieExplosion( const C_MovieExplosion & );
};
// Expose to the particle app.
EXPOSE_PROTOTYPE_EFFECT(MovieExplosion, C_MovieExplosion);
IMPLEMENT_CLIENTCLASS_DT(C_MovieExplosion, DT_MovieExplosion, MovieExplosion)
END_RECV_TABLE()
// ------------------------------------------------------------------------- //
// C_MovieExplosion
// ------------------------------------------------------------------------- //
C_MovieExplosion::C_MovieExplosion()
{
m_pParticleMgr = NULL;
}
C_MovieExplosion::~C_MovieExplosion()
{
if(m_pParticleMgr)
m_pParticleMgr->RemoveEffect( &m_ParticleEffect );
}
void C_MovieExplosion::OnDataChanged(DataUpdateType_t updateType)
{
C_BaseEntity::OnDataChanged(updateType);
if(updateType == DATA_UPDATE_CREATED)
{
Start( ParticleMgr(), NULL );
}
}
void C_MovieExplosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
{
if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
return;
// Setup our emitters.
for(int iEmitter=0; iEmitter < NUM_MOVIEEXPLOSION_EMITTERS; iEmitter++)
{
MovieExplosionEmitter *pEmitter = &m_Emitters[iEmitter];
pEmitter->m_Velocity = RandomVector(-1, 1) * 200;
pEmitter->m_Pos = GetAbsOrigin();
pEmitter->m_Lifetime = 0;
pEmitter->m_ParticleSpawn.Init(15);
}
m_EmitterLifetime = 0;
// Get our materials.
m_iFireballMaterial = m_ParticleEffect.FindOrAddMaterial("particle/particle_sphere");
m_pParticleMgr = pParticleMgr;
}
void C_MovieExplosion::Update(float fTimeDelta)
{
if(!m_pParticleMgr)
return;
m_EmitterLifetime += fTimeDelta;
if(m_EmitterLifetime > EXPLOSION_EMITTER_LIFETIME)
return;
m_EmitterAlpha = (float)sin(m_EmitterLifetime * 3.14159f / EXPLOSION_EMITTER_LIFETIME);
// Simulate the emitters and have them spit out particles.
for(int iEmitter=0; iEmitter < NUM_MOVIEEXPLOSION_EMITTERS; iEmitter++)
{
MovieExplosionEmitter *pEmitter = &m_Emitters[iEmitter];
pEmitter->m_Pos = pEmitter->m_Pos + pEmitter->m_Velocity * fTimeDelta;
pEmitter->m_Velocity = pEmitter->m_Velocity * 0.9;
float tempDelta = fTimeDelta;
while(pEmitter->m_ParticleSpawn.NextEvent(tempDelta))
{
StandardParticle_t *pParticle =
(StandardParticle_t*)m_ParticleEffect.AddParticle( sizeof(StandardParticle_t), m_iFireballMaterial);
if(pParticle)
{
pParticle->m_Pos = pEmitter->m_Pos;
pParticle->m_Velocity = pEmitter->m_Velocity * 0.2f + RandomVector(-20, 20);
}
}
}
}
void C_MovieExplosion::RenderParticles( CParticleRenderIterator *pIterator )
{
const StandardParticle_t *pParticle = (const StandardParticle_t*)pIterator->GetFirst();
while ( pParticle )
{
// Draw.
Vector tPos;
TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
float sortKey = tPos.z;
float lifetimePercent = pParticle->m_Lifetime / EMITTED_PARTICLE_LIFETIME;
Vector color;
color.x = sin(lifetimePercent * 3.14159);
color.y = color.x * 0.5f;
color.z = 0;
RenderParticle_ColorSize(
pIterator->GetParticleDraw(),
tPos,
color,
m_EmitterAlpha * sin(3.14159 * lifetimePercent),
10);
pParticle = (const StandardParticle_t*)pIterator->GetNext( sortKey );
}
}
void C_MovieExplosion::SimulateParticles( CParticleSimulateIterator *pIterator )
{
StandardParticle_t *pParticle = (StandardParticle_t*)pIterator->GetFirst();
while ( pParticle )
{
// Update its lifetime.
pParticle->m_Lifetime += pIterator->GetTimeDelta();
if(pParticle->m_Lifetime > 1)
{
pIterator->RemoveParticle( pParticle );
}
else
{
// Move it (this comes after rendering to make it clear that moving the particle here won't change
// its rendering for this frame since m_TransformedPos has already been set).
pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * pIterator->GetTimeDelta();
}
pParticle = (StandardParticle_t*)pIterator->GetNext();
}
}

339
cl_dll/c_particle_fire.cpp Normal file
View File

@ -0,0 +1,339 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "particle_prototype.h"
#include "particle_util.h"
#include "baseparticleentity.h"
#include "engine/IEngineTrace.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// ------------------------------------------------------------------------- //
// Defines.
// ------------------------------------------------------------------------- //
#define MAX_FIRE_EMITTERS 128
#define FIRE_PARTICLE_LIFETIME 2
Vector g_FireSpreadDirection(0,0,1);
class FireRamp
{
public:
FireRamp(const Vector &s, const Vector &e)
{
m_Start=s;
m_End=e;
}
Vector m_Start;
Vector m_End;
};
FireRamp g_FireRamps[] =
{
FireRamp(Vector(1,0,0), Vector(1,1,0)),
FireRamp(Vector(0.5,0.5,0), Vector(0,0,0))
};
#define NUM_FIRE_RAMPS (sizeof(g_FireRamps) / sizeof(g_FireRamps[0]))
#define NUM_FIREGRID_OFFSETS 8
Vector g_Offsets[NUM_FIREGRID_OFFSETS] =
{
Vector(-1,-1,-1),
Vector( 1,-1,-1),
Vector(-1, 1,-1),
Vector( 1, 1,-1),
Vector(-1,-1, 1),
Vector( 1,-1, 1),
Vector(-1, 1, 1),
Vector( 1, 1, 1),
};
// If you follow g_Offset[index], you can follow g_Offsets[GetOppositeOffset(index)] to get back.
inline int GetOppositeOffset(int offset)
{
return NUM_FIREGRID_OFFSETS - offset - 1;
}
// ------------------------------------------------------------------------- //
// Classes.
// ------------------------------------------------------------------------- //
class C_ParticleFire : public C_BaseParticleEntity, public IPrototypeAppEffect
{
public:
DECLARE_CLASS( C_ParticleFire, C_BaseParticleEntity );
DECLARE_CLIENTCLASS();
C_ParticleFire();
~C_ParticleFire();
class FireEmitter
{
public:
Vector m_Pos;
TimedEvent m_SpawnEvent;
float m_Lifetime; // How long it's been emitting.
unsigned char m_DirectionsTested; // 1 bit for each of g_Offsets.
};
class FireParticle : public Particle
{
public:
Vector m_StartPos; // The particle moves from m_StartPos to (m_StartPos+m_Direction) over its lifetime.
Vector m_Direction;
float m_Lifetime;
float m_SpinAngle;
unsigned char m_iRamp; // Which fire ramp are we using?
};
// C_BaseEntity.
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
// IPrototypeAppEffect.
public:
virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
// IParticleEffect.
public:
virtual void Update(float fTimeDelta);
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
public:
CParticleMgr *m_pParticleMgr;
PMaterialHandle m_MaterialHandle;
// Controls where the initial fire goes.
Vector m_vOrigin;
Vector m_vDirection;
TimedEvent m_EmitterSpawn;
FireEmitter m_Emitters[MAX_FIRE_EMITTERS];
int m_nEmitters;
private:
C_ParticleFire( const C_ParticleFire & );
};
// ------------------------------------------------------------------------- //
// Tables.
// ------------------------------------------------------------------------- //
// Expose to the particle app.
EXPOSE_PROTOTYPE_EFFECT(ParticleFire, C_ParticleFire);
// Datatable..
IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_ParticleFire, DT_ParticleFire, CParticleFire)
RecvPropVector(RECVINFO(m_vOrigin)),
RecvPropVector(RECVINFO(m_vDirection)),
END_RECV_TABLE()
// ------------------------------------------------------------------------- //
// C_FireSmoke implementation.
// ------------------------------------------------------------------------- //
C_ParticleFire::C_ParticleFire()
{
m_pParticleMgr = NULL;
m_MaterialHandle = INVALID_MATERIAL_HANDLE;
}
C_ParticleFire::~C_ParticleFire()
{
if(m_pParticleMgr)
m_pParticleMgr->RemoveEffect( &m_ParticleEffect );
}
void C_ParticleFire::OnDataChanged(DataUpdateType_t updateType)
{
C_BaseEntity::OnDataChanged(updateType);
if(updateType == DATA_UPDATE_CREATED)
{
Start(ParticleMgr(), NULL);
}
}
void C_ParticleFire::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
{
m_pParticleMgr = pParticleMgr;
m_pParticleMgr->AddEffect( &m_ParticleEffect, this );
m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial("particle/particle_fire");
// Start
m_nEmitters = 0;
m_EmitterSpawn.Init(15);
}
static float fireSpreadDist = 15;
static float size = 20;
void C_ParticleFire::Update(float fTimeDelta)
{
if(!m_pParticleMgr)
{
assert(false);
return;
}
// Add new emitters.
if(m_nEmitters < MAX_FIRE_EMITTERS)
{
float tempDelta = fTimeDelta;
while(m_EmitterSpawn.NextEvent(tempDelta))
{
FireEmitter *pEmitter = NULL;
if(m_nEmitters == 0)
{
// Make the first emitter.
trace_t trace;
UTIL_TraceLine(m_vOrigin, m_vOrigin+m_vDirection*1000, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &trace);
if(trace.fraction < 1)
{
pEmitter = &m_Emitters[m_nEmitters];
pEmitter->m_Pos = trace.endpos + trace.plane.normal * (size - 1);
pEmitter->m_DirectionsTested = 0;
}
}
else
{
static int nTries = 50;
for(int iTry=0; iTry < nTries; iTry++)
{
FireEmitter *pSourceEmitter = &m_Emitters[rand() % m_nEmitters];
int iOffset = rand() % NUM_FIREGRID_OFFSETS;
if(pSourceEmitter->m_DirectionsTested & (1 << iOffset))
continue;
// Test the corners of the new cube. If some points are solid and some are not, then
// we can put fire here.
Vector basePos = pSourceEmitter->m_Pos + g_Offsets[iOffset] * fireSpreadDist;
int nSolidCorners = 0;
for(int iCorner=0; iCorner < NUM_FIREGRID_OFFSETS; iCorner++)
{
Vector vCorner = basePos + g_Offsets[iCorner]*fireSpreadDist;
if ( enginetrace->GetPointContents(vCorner) & CONTENTS_SOLID )
++nSolidCorners;
}
// Don't test this square again.
pSourceEmitter->m_DirectionsTested |= 1 << iOffset;
if(nSolidCorners != 0 && nSolidCorners != NUM_FIREGRID_OFFSETS)
{
pEmitter = &m_Emitters[m_nEmitters];
pEmitter->m_Pos = basePos;
pEmitter->m_DirectionsTested = 1 << GetOppositeOffset(iOffset);
}
}
}
if(pEmitter)
{
pEmitter->m_Lifetime = 0;
pEmitter->m_SpawnEvent.Init(1);
++m_nEmitters;
}
}
}
// Spawn particles out of the emitters.
for(int i=0; i < m_nEmitters; i++)
{
FireEmitter *pEmitter = &m_Emitters[i];
float tempDelta = fTimeDelta;
while(pEmitter->m_SpawnEvent.NextEvent(tempDelta))
{
FireParticle *pParticle = (FireParticle*)m_ParticleEffect.AddParticle(sizeof(FireParticle), m_MaterialHandle);
if(pParticle)
{
static float particleSpeed = 15;
pParticle->m_StartPos = pEmitter->m_Pos;
pParticle->m_Direction = g_FireSpreadDirection * particleSpeed + RandomVector(0, particleSpeed*0.5);
pParticle->m_iRamp = rand() % NUM_FIRE_RAMPS;
pParticle->m_Lifetime = 0;
}
}
}
}
void C_ParticleFire::RenderParticles( CParticleRenderIterator *pIterator )
{
const FireParticle *pParticle = (const FireParticle*)pIterator->GetFirst();
while ( pParticle )
{
float smooth01 = 1 - (cos(pParticle->m_Lifetime * 3.14159 / FIRE_PARTICLE_LIFETIME) * 0.5 + 0.5);
float smooth00 = 1 - (cos(pParticle->m_Lifetime * 3.14159 * 2 / FIRE_PARTICLE_LIFETIME) * 0.5 + 0.5);
FireRamp *pRamp = &g_FireRamps[pParticle->m_iRamp];
Vector curColor = pRamp->m_Start + (pRamp->m_End - pRamp->m_Start) * smooth01;
// Render.
Vector tPos;
TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
float sortKey = (int)tPos.z;
RenderParticle_ColorSize(
pIterator->GetParticleDraw(),
tPos,
curColor,
smooth00,
size);
pParticle = (const FireParticle*)pIterator->GetNext( sortKey );
}
}
void C_ParticleFire::SimulateParticles( CParticleSimulateIterator *pIterator )
{
FireParticle *pParticle = (FireParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Should this particle die?
pParticle->m_Lifetime += pIterator->GetTimeDelta();
if(pParticle->m_Lifetime > FIRE_PARTICLE_LIFETIME)
{
pIterator->RemoveParticle( pParticle );
}
else
{
float smooth01 = 1 - (cos(pParticle->m_Lifetime * 3.14159 / FIRE_PARTICLE_LIFETIME) * 0.5 + 0.5);
pParticle->m_Pos = pParticle->m_StartPos + pParticle->m_Direction * smooth01;
}
pParticle = (FireParticle*)pIterator->GetNext();
}
}

File diff suppressed because it is too large Load Diff

35
cl_dll/c_physbox.cpp Normal file
View File

@ -0,0 +1,35 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_physbox.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT(C_PhysBox, DT_PhysBox, CPhysBox)
RecvPropFloat(RECVINFO(m_mass), 0), // Test..
END_RECV_TABLE()
C_PhysBox::C_PhysBox()
{
}
//-----------------------------------------------------------------------------
// Should this object cast shadows?
//-----------------------------------------------------------------------------
ShadowType_t C_PhysBox::ShadowCastType()
{
if (IsEffectActive(EF_NODRAW | EF_NOSHADOW))
return SHADOWS_NONE;
return SHADOWS_RENDER_TO_TEXTURE;
}
C_PhysBox::~C_PhysBox()
{
}

39
cl_dll/c_physbox.h Normal file
View File

@ -0,0 +1,39 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// Client-side CBasePlayer
#ifndef C_PHYSBOX_H
#define C_PHYSBOX_H
#pragma once
#include "c_baseentity.h"
class C_PhysBox : public C_BaseEntity
{
public:
DECLARE_CLASS( C_PhysBox, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_PhysBox();
virtual ~C_PhysBox();
virtual ShadowType_t ShadowCastType();
public:
float m_mass; // TEST..
};
#endif

158
cl_dll/c_physicsprop.cpp Normal file
View File

@ -0,0 +1,158 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "model_types.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "solidsetdefaults.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
#include "physics.h"
#include "view.h"
#include "clienteffectprecachesystem.h"
#include "c_physicsprop.h"
#include "tier0/vprof.h"
#include "ivrenderview.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT(C_PhysicsProp, DT_PhysicsProp, CPhysicsProp)
RecvPropBool( RECVINFO( m_bAwake ) ),
END_RECV_TABLE()
ConVar r_PhysPropStaticLighting( "r_PhysPropStaticLighting", "1" );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_PhysicsProp::C_PhysicsProp( void )
{
m_pPhysicsObject = NULL;
m_takedamage = DAMAGE_YES;
// default true so static lighting will get recomputed when we go to sleep
m_bAwakeLastTime = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_PhysicsProp::~C_PhysicsProp( void )
{
}
ConVar r_visualizeproplightcaching( "r_visualizeproplightcaching", "0" );
//-----------------------------------------------------------------------------
// Purpose: Draws the object
// Input : flags -
//-----------------------------------------------------------------------------
// FIXME!!!! I hate the fact that InternalDrawModel is always such a huge cut-and-paste job.
int C_PhysicsProp::InternalDrawModel( int flags )
{
VPROF( "C_PhysicsProp::InternalDrawModel" );
//-----------------------------------------------------------------------------
// Overriding C_BaseAnimating::InternalDrawModel so that we can detect when the
// prop is asleep. This allows us to bake the lighting for the model.
//-----------------------------------------------------------------------------
if ( !GetModel() )
{
return 0;
}
if ( IsEffectActive( EF_ITEM_BLINK ) )
{
flags |= STUDIO_ITEM_BLINK;
}
// This should never happen, but if the server class hierarchy has bmodel entities derived from CBaseAnimating or does a
// SetModel with the wrong type of model, this could occur.
if ( modelinfo->GetModelType( GetModel() ) != mod_studio )
{
return BaseClass::DrawModel( flags );
}
// Make sure hdr is valid for drawing
if ( !GetModelPtr() )
{
// inhibit drawing and state setting until all data available
return 0;
}
CreateModelInstance();
if ( r_PhysPropStaticLighting.GetBool() && m_bAwakeLastTime != m_bAwake )
{
if ( m_bAwakeLastTime && !m_bAwake )
{
// transition to sleep, bake lighting now, once
if ( !modelrender->RecomputeStaticLighting( GetModelInstance() ) )
{
// not valid for drawing
return 0;
}
if ( r_visualizeproplightcaching.GetBool() )
{
float color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
render->SetColorModulation( color );
}
}
else if ( r_visualizeproplightcaching.GetBool() )
{
float color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
render->SetColorModulation( color );
}
}
if ( !m_bAwake && r_PhysPropStaticLighting.GetBool() )
{
// going to sleep, have static lighting
flags |= STUDIO_STATIC_LIGHTING;
}
Vector tmpOrigin = GetRenderOrigin();
int drawn = modelrender->DrawModel(
flags,
this,
GetModelInstance(),
index,
GetModel(),
GetRenderOrigin(),
GetRenderAngles(),
m_nSkin,
m_nBody,
m_nHitboxSet );
if ( vcollide_wireframe.GetBool() )
{
if ( IsRagdoll() )
{
m_pRagdoll->DrawWireframe();
}
else
{
vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() );
if ( pCollide && pCollide->solidCount == 1 )
{
static color32 debugColor = {0,255,255,0};
matrix3x4_t matrix;
AngleMatrix( GetAbsAngles(), GetAbsOrigin(), matrix );
engine->DebugDrawPhysCollide( pCollide->solids[0], NULL, matrix, debugColor );
}
}
}
// track state
m_bAwakeLastTime = m_bAwake;
return drawn;
}

34
cl_dll/c_physicsprop.h Normal file
View File

@ -0,0 +1,34 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_PHYSICSPROP_H
#define C_PHYSICSPROP_H
#ifdef _WIN32
#pragma once
#endif
#include "c_breakableprop.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_PhysicsProp : public C_BreakableProp
{
typedef C_BreakableProp BaseClass;
public:
DECLARE_CLIENTCLASS();
C_PhysicsProp();
~C_PhysicsProp();
int InternalDrawModel( int flags );
protected:
// Networked vars.
bool m_bAwake;
bool m_bAwakeLastTime;
};
#endif // C_PHYSICSPROP_H

134
cl_dll/c_physmagnet.cpp Normal file
View File

@ -0,0 +1,134 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_baseentity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_PhysMagnet : public C_BaseAnimating
{
DECLARE_CLASS( C_PhysMagnet, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_PhysMagnet();
virtual ~C_PhysMagnet();
void PostDataUpdate( DataUpdateType_t updateType );
bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const;
public:
// Data received from the server
CUtlVector< int > m_aAttachedObjectsFromServer;
// Private list of entities on the magnet
CUtlVector< EHANDLE > m_aAttachedObjects;
};
//-----------------------------------------------------------------------------
// Purpose: RecvProxy that converts the Magnet's attached object entindexes to handles
//-----------------------------------------------------------------------------
void RecvProxy_MagnetAttachedObjectList( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_PhysMagnet *pMagnet = (C_PhysMagnet*)pOut;
pMagnet->m_aAttachedObjectsFromServer[pData->m_iElement] = pData->m_Value.m_Int;
}
void RecvProxyArrayLength_MagnetAttachedArray( void *pStruct, int objectID, int currentArrayLength )
{
C_PhysMagnet *pMagnet = (C_PhysMagnet*)pStruct;
if ( pMagnet->m_aAttachedObjectsFromServer.Size() != currentArrayLength )
pMagnet->m_aAttachedObjectsFromServer.SetSize( currentArrayLength );
}
IMPLEMENT_CLIENTCLASS_DT(C_PhysMagnet, DT_PhysMagnet, CPhysMagnet)
// ROBIN: Disabled because we don't need it anymore
/*
RecvPropArray2(
RecvProxyArrayLength_MagnetAttachedArray,
RecvPropInt( "magnetattached_array_element", 0, SIZEOF_IGNORE, 0, RecvProxy_MagnetAttachedObjectList ),
128,
0,
"magnetattached_array"
)
*/
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_PhysMagnet::C_PhysMagnet()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_PhysMagnet::~C_PhysMagnet()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_PhysMagnet::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
/*
// First, detect any entities removed from the magnet and restore their shadows
int iCount = m_aAttachedObjects.Count();
int iServerCount = m_aAttachedObjectsFromServer.Count();
for ( int i = 0; i < iCount; i++ )
{
int iEntIndex = m_aAttachedObjects[i]->entindex();
for ( int j = 0; j < iServerCount; j++ )
{
if ( iEntIndex == m_aAttachedObjectsFromServer[j] )
break;
}
if ( j == iServerCount )
{
// Ok, a previously attached object is no longer attached
m_aAttachedObjects[i]->SetShadowUseOtherEntity( NULL );
m_aAttachedObjects.Remove(i);
}
}
// Make sure newly attached entities have vertical shadows too
for ( i = 0; i < iServerCount; i++ )
{
C_BaseEntity *pEntity = cl_entitylist->GetEnt( m_aAttachedObjectsFromServer[i] );
if ( m_aAttachedObjects.Find( pEntity ) == m_aAttachedObjects.InvalidIndex() )
{
pEntity->SetShadowUseOtherEntity( this );
m_aAttachedObjects.AddToTail( pEntity );
}
}
*/
}
//-----------------------------------------------------------------------------
// Purpose: Return a per-entity shadow cast direction
//-----------------------------------------------------------------------------
bool C_PhysMagnet::GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const
{
// Magnets shadow is more vertical than others
//Vector vecDown = g_pClientShadowMgr->GetShadowDirection() - Vector(0,0,1);
//VectorNormalize( vecDown );
//*pDirection = vecDown;
*pDirection = Vector(0,0,-1);
return true;
}

View File

@ -0,0 +1,769 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "c_pixel_visibility.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "ClientEffectPrecacheSystem.h"
#include "view.h"
#include "utlmultilist.h"
static void PixelvisDrawChanged( ConVar *pPixelvisVar, const char *pOld );
ConVar r_pixelvisibility_partial( "r_pixelvisibility_partial", "1" );
ConVar r_dopixelvisibility( "r_dopixelvisibility", "1" );
ConVar r_drawpixelvisibility( "r_drawpixelvisibility", "0", 0, "Show the occlusion proxies", PixelvisDrawChanged );
ConVar r_pixelvisibility_spew( "r_pixelvisibility_spew", "0" );
extern ConVar building_cubemaps;
const float MIN_PROXY_PIXELS = 5.0f;
float PixelVisibility_DrawProxy( OcclusionQueryObjectHandle_t queryHandle, Vector origin, float scale, float proxyAspect, IMaterial *pMaterial, bool screenspace )
{
Vector point;
// don't expand this with distance to fit pixels or the sprite will poke through
// only expand the parts perpendicular to the view
float forwardScale = scale;
// draw a pyramid of points touching a sphere of radius "scale" at origin
float pixelsPerUnit = materials->ComputePixelWidthOfSphere( origin, 1.0f );
pixelsPerUnit = max( pixelsPerUnit, 1e-4f );
if ( screenspace )
{
// Force this to be the size of a sphere of diameter "scale" at some reference distance (1.0 unit)
float pixelsPerUnit2 = materials->ComputePixelWidthOfSphere( CurrentViewOrigin() + CurrentViewForward()*1.0f, scale*0.5f );
// force drawing of "scale" pixels
scale = pixelsPerUnit2 / pixelsPerUnit;
}
else
{
float pixels = scale * pixelsPerUnit;
// make the radius larger to ensure a minimum screen space size of the proxy geometry
if ( pixels < MIN_PROXY_PIXELS )
{
scale = MIN_PROXY_PIXELS / pixelsPerUnit;
}
}
// collapses the pyramid to a plane - so this could be a quad instead
Vector dir = origin - CurrentViewOrigin();
VectorNormalize(dir);
origin -= dir * forwardScale;
forwardScale = 0.0f;
//
Vector verts[5];
const float sqrt2 = 0.707106781f; // sqrt(2) - keeps all vectors the same length from origin
scale *= sqrt2;
float scale45x = scale;
float scale45y = scale / proxyAspect;
verts[0] = origin - CurrentViewForward() * forwardScale; // the apex of the pyramid
verts[1] = origin + CurrentViewUp() * scale45y - CurrentViewRight() * scale45x; // these four form the base
verts[2] = origin + CurrentViewUp() * scale45y + CurrentViewRight() * scale45x; // the pyramid is a sprite with a point that
verts[3] = origin - CurrentViewUp() * scale45y + CurrentViewRight() * scale45x; // pokes back toward the camera through any nearby
verts[4] = origin - CurrentViewUp() * scale45y - CurrentViewRight() * scale45x; // geometry
// get screen coords of edges
Vector screen[4];
for ( int i = 0; i < 4; i++ )
{
extern int ScreenTransform( const Vector& point, Vector& screen );
if ( ScreenTransform( verts[i+1], screen[i] ) )
return 0;
}
// compute area and screen-clipped area
float w = screen[1].x - screen[0].x;
float h = screen[0].y - screen[3].y;
float ws = min(1.0f, screen[1].x) - max(-1.0f, screen[0].x);
float hs = min(1.0f, screen[0].y) - max(-1.0f, screen[3].y);
float area = w*h; // area can be zero when we ALT-TAB
float areaClipped = ws*hs;
float ratio = 0.0f;
if ( area != 0 )
{
// compute the ratio of the area not clipped by the frustum to total area
ratio = areaClipped / area;
ratio = clamp(ratio, 0.0f, 1.0f);
}
IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, pMaterial );
CMeshBuilder meshBuilder;
materials->BeginOcclusionQueryDrawing( queryHandle );
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 4 );
// draw a pyramid
for ( int i = 0; i < 4; i++ )
{
int a = i+1;
int b = (a%4)+1;
meshBuilder.Position3fv( verts[0].Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( verts[a].Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( verts[b].Base() );
meshBuilder.AdvanceVertex();
}
meshBuilder.End();
pMesh->Draw();
// sprite/quad proxy
#if 0
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
VectorMA (origin, -scale, CurrentViewUp(), point);
VectorMA (point, -scale, CurrentViewRight(), point);
meshBuilder.Position3fv (point.Base());
meshBuilder.AdvanceVertex();
VectorMA (origin, scale, CurrentViewUp(), point);
VectorMA (point, -scale, CurrentViewRight(), point);
meshBuilder.Position3fv (point.Base());
meshBuilder.AdvanceVertex();
VectorMA (origin, scale, CurrentViewUp(), point);
VectorMA (point, scale, CurrentViewRight(), point);
meshBuilder.Position3fv (point.Base());
meshBuilder.AdvanceVertex();
VectorMA (origin, -scale, CurrentViewUp(), point);
VectorMA (point, scale, CurrentViewRight(), point);
meshBuilder.Position3fv (point.Base());
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
#endif
materials->EndOcclusionQueryDrawing( queryHandle );
// fraction clipped by frustum
return ratio;
}
class CPixelVisSet
{
public:
void Init( const pixelvis_queryparams_t &params );
void MarkActive();
bool IsActive();
CPixelVisSet()
{
frameIssued = 0;
serial = 0;
queryList = 0xFFFF;
sizeIsScreenSpace = false;
}
public:
float proxySize;
float proxyAspect;
float fadeTimeInv;
unsigned short queryList;
unsigned short serial;
bool sizeIsScreenSpace;
private:
int frameIssued;
};
void CPixelVisSet::Init( const pixelvis_queryparams_t &params )
{
Assert( params.bSetup );
proxySize = params.proxySize;
proxyAspect = params.proxyAspect;
if ( params.fadeTime > 0.0f )
{
fadeTimeInv = 1.0f / params.fadeTime;
}
else
{
// fade in over 0.125 seconds
fadeTimeInv = 1.0f / 0.125f;
}
frameIssued = 0;
sizeIsScreenSpace = params.bSizeInScreenspace;
}
void CPixelVisSet::MarkActive()
{
frameIssued = gpGlobals->framecount;
}
bool CPixelVisSet::IsActive()
{
return (gpGlobals->framecount - frameIssued) > 1 ? false : true;
}
class CPixelVisibilityQuery
{
public:
CPixelVisibilityQuery();
~CPixelVisibilityQuery();
bool IsValid();
bool IsForView( int viewID );
bool IsActive();
float GetFractionVisible( float fadeTimeInv );
void IssueQuery( float proxySize, float proxyAspect, IMaterial *pMaterial, bool sizeIsScreenSpace );
void IssueCountingQuery( float proxySize, float proxyAspect, IMaterial *pMaterial, bool sizeIsScreenSpace );
void SetView( int viewID )
{
m_viewID = viewID;
m_brightnessTarget = 0.0f;
m_clipFraction = 1.0f;
m_frameIssued = -1;
m_failed = false;
m_wasQueriedThisFrame = false;
m_hasValidQueryResults = false;
}
public:
Vector m_origin;
int m_frameIssued;
private:
float m_brightnessTarget;
float m_clipFraction;
OcclusionQueryObjectHandle_t m_queryHandle;
OcclusionQueryObjectHandle_t m_queryHandleCount;
unsigned short m_wasQueriedThisFrame : 1;
unsigned short m_failed : 1;
unsigned short m_hasValidQueryResults : 1;
unsigned short m_pad : 13;
unsigned short m_viewID;
};
CPixelVisibilityQuery::CPixelVisibilityQuery()
{
SetView( 0xFFFF );
m_queryHandle = materials->CreateOcclusionQueryObject();
m_queryHandleCount = materials->CreateOcclusionQueryObject();
}
CPixelVisibilityQuery::~CPixelVisibilityQuery()
{
if ( m_queryHandle != INVALID_OCCLUSION_QUERY_OBJECT_HANDLE )
{
materials->DestroyOcclusionQueryObject( m_queryHandle );
}
if ( m_queryHandleCount != INVALID_OCCLUSION_QUERY_OBJECT_HANDLE )
{
materials->DestroyOcclusionQueryObject( m_queryHandleCount );
}
}
bool CPixelVisibilityQuery::IsValid()
{
return (m_queryHandle != INVALID_OCCLUSION_QUERY_OBJECT_HANDLE) ? true : false;
}
bool CPixelVisibilityQuery::IsForView( int viewID )
{
return m_viewID == viewID ? true : false;
}
bool CPixelVisibilityQuery::IsActive()
{
return (gpGlobals->framecount - m_frameIssued) > 1 ? false : true;
}
float CPixelVisibilityQuery::GetFractionVisible( float fadeTimeInv )
{
if ( !IsValid() )
return 0.0f;
if ( !m_wasQueriedThisFrame )
{
m_wasQueriedThisFrame = true;
int pixels = -1;
int pixelsPossible = -1;
if ( r_pixelvisibility_partial.GetBool() )
{
if ( m_frameIssued != -1 )
{
pixelsPossible = materials->OcclusionQuery_GetNumPixelsRendered( m_queryHandleCount );
pixels = materials->OcclusionQuery_GetNumPixelsRendered( m_queryHandle );
}
if ( r_pixelvisibility_spew.GetBool() && CurrentViewID() == 0 )
{
DevMsg( 1, "Pixels visible: %d (qh:%d) Pixels possible: %d (qh:%d) (frame:%d)\n", pixels, m_queryHandle, pixelsPossible, m_queryHandleCount, gpGlobals->framecount );
}
if ( pixels < 0 || pixelsPossible < 0 )
{
m_failed = m_frameIssued != -1 ? true : false;
return m_brightnessTarget * m_clipFraction;
}
m_hasValidQueryResults = true;
if ( pixelsPossible > 0 )
{
float target = (float)pixels / (float)pixelsPossible;
target = (target >= 0.95f) ? 1.0f : (target < 0.0f) ? 0.0f : target;
float rate = gpGlobals->frametime * fadeTimeInv;
m_brightnessTarget = Approach( target, m_brightnessTarget, rate ); // fade in / out
}
else
{
m_brightnessTarget = 0.0f;
}
}
else
{
if ( m_frameIssued != -1 )
{
pixels = materials->OcclusionQuery_GetNumPixelsRendered( m_queryHandle );
}
if ( r_pixelvisibility_spew.GetBool() && CurrentViewID() == 0 )
{
DevMsg( 1, "Pixels visible: %d (qh:%d) (frame:%d)\n", pixels, m_queryHandle, gpGlobals->framecount );
}
if ( pixels < 0 )
{
m_failed = m_frameIssued != -1 ? true : false;
return m_brightnessTarget * m_clipFraction;
}
m_hasValidQueryResults = true;
if ( m_frameIssued == gpGlobals->framecount-1 )
{
float rate = gpGlobals->frametime * fadeTimeInv;
float target = 0.0f;
if ( pixels > 0 )
{
// fade in slower than you fade out
rate *= 0.5f;
target = 1.0f;
}
m_brightnessTarget = Approach( target, m_brightnessTarget, rate ); // fade in / out
}
else
{
m_brightnessTarget = 0.0f;
}
}
}
return m_brightnessTarget * m_clipFraction;
}
void CPixelVisibilityQuery::IssueQuery( float proxySize, float proxyAspect, IMaterial *pMaterial, bool sizeIsScreenSpace )
{
if ( !m_failed )
{
Assert( IsValid() );
if ( r_pixelvisibility_spew.GetBool() && CurrentViewID() == 0 )
{
DevMsg( 1, "Draw Proxy: qh:%d org:<%d,%d,%d> (frame:%d)\n", m_queryHandle, (int)m_origin[0], (int)m_origin[1], (int)m_origin[2], gpGlobals->framecount );
}
m_clipFraction = PixelVisibility_DrawProxy( m_queryHandle, m_origin, proxySize, proxyAspect, pMaterial, sizeIsScreenSpace );
}
m_frameIssued = gpGlobals->framecount;
m_wasQueriedThisFrame = false;
m_failed = false;
}
void CPixelVisibilityQuery::IssueCountingQuery( float proxySize, float proxyAspect, IMaterial *pMaterial, bool sizeIsScreenSpace )
{
if ( !m_failed )
{
Assert( IsValid() );
#if 0
// this centers it on the screen.
// This is nice because it makes the glows fade as they get partially clipped by the view frustum
// But it introduces sub-pixel errors (off by one row/column of pixels) so the glows shimmer
// UNDONE: Compute an offset center coord that matches sub-pixel coords with the real glow position
// UNDONE: Or frustum clip the sphere/geometry and fade based on proxy size
Vector origin = m_origin - CurrentViewOrigin();
float dot = DotProduct(CurrentViewForward(), origin);
origin = CurrentViewOrigin() + dot * CurrentViewForward();
#endif
PixelVisibility_DrawProxy( m_queryHandleCount, m_origin, proxySize, proxyAspect, pMaterial, sizeIsScreenSpace );
}
}
//Precahce the effects
CLIENTEFFECT_REGISTER_BEGIN( PrecacheOcclusionProxy )
CLIENTEFFECT_MATERIAL( "engine/occlusionproxy" )
CLIENTEFFECT_MATERIAL( "engine/occlusionproxy_countdraw" )
CLIENTEFFECT_REGISTER_END()
class CPixelVisibilitySystem : public CAutoGameSystem
{
public:
// GameSystem: Level init, shutdown
virtual void LevelInitPreEntity();
virtual void LevelShutdownPostEntity();
// locals
CPixelVisibilitySystem();
float GetFractionVisible( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle );
void EndView();
void EndScene();
unsigned short FindQueryForView( CPixelVisSet *pSet, int viewID );
unsigned short FindOrCreateQueryForView( CPixelVisSet *pSet, int viewID );
void DeleteUnusedQueries( CPixelVisSet *pSet, bool bDeleteAll );
void DeleteUnusedSets( bool bDeleteAll );
void ShowQueries( bool show );
unsigned short AllocQuery();
unsigned short AllocSet();
void FreeSet( unsigned short node );
CPixelVisSet *FindOrCreatePixelVisSet( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle );
bool SupportsOcclusion() { return m_hwCanTestGlows; }
void DebugInfo()
{
Msg("Pixel vis system using %d sets total (%d in free list), %d queries total (%d in free list)\n",
m_setList.TotalCount(), m_setList.Count(m_freeSetsList), m_queryList.TotalCount(), m_queryList.Count( m_freeQueriesList ) );
}
private:
CUtlMultiList< CPixelVisSet, unsigned short > m_setList;
CUtlMultiList<CPixelVisibilityQuery, unsigned short> m_queryList;
unsigned short m_freeQueriesList;
unsigned short m_activeSetsList;
unsigned short m_freeSetsList;
unsigned short m_pad0;
IMaterial *m_pProxyMaterial;
IMaterial *m_pDrawMaterial;
bool m_hwCanTestGlows;
bool m_drawQueries;
};
static CPixelVisibilitySystem g_PixelVisibilitySystem;
CPixelVisibilitySystem::CPixelVisibilitySystem() : CAutoGameSystem( "CPixelVisibilitySystem" )
{
m_hwCanTestGlows = true;
m_drawQueries = false;
}
// Level init, shutdown
void CPixelVisibilitySystem::LevelInitPreEntity()
{
m_hwCanTestGlows = r_dopixelvisibility.GetBool() && engine->GetDXSupportLevel() >= 80;
if ( m_hwCanTestGlows )
{
unsigned short query = materials->CreateOcclusionQueryObject();
if ( query != INVALID_OCCLUSION_QUERY_OBJECT_HANDLE )
{
materials->DestroyOcclusionQueryObject( query );
}
else
{
m_hwCanTestGlows = false;
}
}
m_pProxyMaterial = materials->FindMaterial("engine/occlusionproxy", TEXTURE_GROUP_CLIENT_EFFECTS);
m_pProxyMaterial->IncrementReferenceCount();
m_pDrawMaterial = materials->FindMaterial("engine/occlusionproxy_countdraw", TEXTURE_GROUP_CLIENT_EFFECTS);
m_pDrawMaterial->IncrementReferenceCount();
m_freeQueriesList = m_queryList.CreateList();
m_activeSetsList = m_setList.CreateList();
m_freeSetsList = m_setList.CreateList();
}
void CPixelVisibilitySystem::LevelShutdownPostEntity()
{
m_pProxyMaterial->DecrementReferenceCount();
m_pProxyMaterial = NULL;
m_pDrawMaterial->DecrementReferenceCount();
m_pDrawMaterial = NULL;
DeleteUnusedSets(true);
m_setList.Purge();
m_queryList.Purge();
m_freeQueriesList = m_queryList.InvalidIndex();
m_activeSetsList = m_setList.InvalidIndex();
m_freeSetsList = m_setList.InvalidIndex();
}
float CPixelVisibilitySystem::GetFractionVisible( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle )
{
if ( !m_hwCanTestGlows || building_cubemaps.GetBool() )
{
return GlowSightDistance( params.position, true ) > 0 ? 1.0f : 0.0f;
}
if ( CurrentViewID() < 0 )
return 0.0f;
CPixelVisSet *pSet = FindOrCreatePixelVisSet( params, queryHandle );
Assert( pSet );
unsigned short node = FindOrCreateQueryForView( pSet, CurrentViewID() );
m_queryList[node].m_origin = params.position;
float fraction = m_queryList[node].GetFractionVisible( pSet->fadeTimeInv );
pSet->MarkActive();
return fraction;
}
void CPixelVisibilitySystem::EndView()
{
if ( !PixelVisibility_IsAvailable() && CurrentViewID() >= 0 )
return;
if ( m_setList.Head( m_activeSetsList ) == m_setList.InvalidIndex() )
return;
IMaterial *pProxy = m_drawQueries ? m_pDrawMaterial : m_pProxyMaterial;
materials->Bind( pProxy );
// BUGBUG: If you draw both queries, the measure query fails for some reason.
if ( r_pixelvisibility_partial.GetBool() && !m_drawQueries )
{
materials->DepthRange( 0.0f, 0.01f );
unsigned short node = m_setList.Head( m_activeSetsList );
while( node != m_setList.InvalidIndex() )
{
CPixelVisSet *pSet = &m_setList[node];
unsigned short queryNode = FindQueryForView( pSet, CurrentViewID() );
if ( queryNode != m_queryList.InvalidIndex() )
{
m_queryList[queryNode].IssueCountingQuery( pSet->proxySize, pSet->proxyAspect, pProxy, pSet->sizeIsScreenSpace );
}
node = m_setList.Next( node );
}
materials->DepthRange( 0.0f, 1.0f );
}
{
unsigned short node = m_setList.Head( m_activeSetsList );
while( node != m_setList.InvalidIndex() )
{
CPixelVisSet *pSet = &m_setList[node];
unsigned short queryNode = FindQueryForView( pSet, CurrentViewID() );
if ( queryNode != m_queryList.InvalidIndex() )
{
m_queryList[queryNode].IssueQuery( pSet->proxySize, pSet->proxyAspect, pProxy, pSet->sizeIsScreenSpace );
}
node = m_setList.Next( node );
}
}
}
void CPixelVisibilitySystem::EndScene()
{
DeleteUnusedSets(false);
}
unsigned short CPixelVisibilitySystem::FindQueryForView( CPixelVisSet *pSet, int viewID )
{
unsigned short node = m_queryList.Head( pSet->queryList );
while ( node != m_queryList.InvalidIndex() )
{
if ( m_queryList[node].IsForView( viewID ) )
return node;
node = m_queryList.Next( node );
}
return m_queryList.InvalidIndex();
}
unsigned short CPixelVisibilitySystem::FindOrCreateQueryForView( CPixelVisSet *pSet, int viewID )
{
unsigned short node = FindQueryForView( pSet, viewID );
if ( node != m_queryList.InvalidIndex() )
return node;
node = AllocQuery();
m_queryList.LinkToHead( pSet->queryList, node );
m_queryList[node].SetView( viewID );
return node;
}
void CPixelVisibilitySystem::DeleteUnusedQueries( CPixelVisSet *pSet, bool bDeleteAll )
{
unsigned short node = m_queryList.Head( pSet->queryList );
while ( node != m_queryList.InvalidIndex() )
{
unsigned short next = m_queryList.Next( node );
if ( bDeleteAll || !m_queryList[node].IsActive() )
{
m_queryList.Unlink( pSet->queryList, node);
m_queryList.LinkToHead( m_freeQueriesList, node );
}
node = next;
}
}
void CPixelVisibilitySystem::DeleteUnusedSets( bool bDeleteAll )
{
unsigned short node = m_setList.Head( m_activeSetsList );
while ( node != m_setList.InvalidIndex() )
{
unsigned short next = m_setList.Next( node );
CPixelVisSet *pSet = &m_setList[node];
if ( bDeleteAll || !m_setList[node].IsActive() )
{
DeleteUnusedQueries( pSet, true );
}
else
{
DeleteUnusedQueries( pSet, false );
}
if ( m_queryList.Head(pSet->queryList) == m_queryList.InvalidIndex() )
{
FreeSet( node );
}
node = next;
}
}
void CPixelVisibilitySystem::ShowQueries( bool show )
{
m_drawQueries = show;
}
unsigned short CPixelVisibilitySystem::AllocQuery()
{
unsigned short node = m_queryList.Head(m_freeQueriesList);
if ( node != m_queryList.InvalidIndex() )
{
m_queryList.Unlink( m_freeQueriesList, node );
}
else
{
node = m_queryList.Alloc();
}
return node;
}
unsigned short CPixelVisibilitySystem::AllocSet()
{
unsigned short node = m_setList.Head(m_freeSetsList);
if ( node != m_setList.InvalidIndex() )
{
m_setList.Unlink( m_freeSetsList, node );
}
else
{
node = m_setList.Alloc();
m_setList[node].queryList = m_queryList.CreateList();
}
m_setList.LinkToHead( m_activeSetsList, node );
return node;
}
void CPixelVisibilitySystem::FreeSet( unsigned short node )
{
m_setList.Unlink( m_activeSetsList, node );
m_setList.LinkToHead( m_freeSetsList, node );
m_setList[node].serial++;
}
CPixelVisSet *CPixelVisibilitySystem::FindOrCreatePixelVisSet( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle )
{
if ( queryHandle[0] )
{
unsigned short handle = queryHandle[0] & 0xFFFF;
handle--;
unsigned short serial = queryHandle[0] >> 16;
if ( m_setList.IsValidIndex(handle) && m_setList[handle].serial == serial )
{
return &m_setList[handle];
}
}
unsigned short node = AllocSet();
m_setList[node].Init( params );
unsigned int out = m_setList[node].serial;
unsigned short nodeHandle = node + 1;
out <<= 16;
out |= nodeHandle;
queryHandle[0] = out;
return &m_setList[node];
}
void PixelvisDrawChanged( ConVar *pPixelvisVar, const char *pOld )
{
g_PixelVisibilitySystem.ShowQueries( pPixelvisVar->GetBool() );
}
class CTraceFilterGlow : public CTraceFilterSimple
{
public:
DECLARE_CLASS( CTraceFilterGlow, CTraceFilterSimple );
CTraceFilterGlow( const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple(passentity, collisionGroup) {}
virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
IClientUnknown *pUnk = (IClientUnknown*)pHandleEntity;
ICollideable *pCollide = pUnk->GetCollideable();
if ( pCollide->GetSolid() != SOLID_VPHYSICS && pCollide->GetSolid() != SOLID_BSP )
return false;
return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
}
};
float GlowSightDistance( const Vector &glowOrigin, bool bShouldTrace )
{
float dist = (glowOrigin - CurrentViewOrigin()).Length();
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
if ( local )
{
dist *= local->GetFOVDistanceAdjustFactor();
}
if ( bShouldTrace )
{
Vector end = glowOrigin;
// HACKHACK: trace 4" from destination in case the glow is inside some parent object
// allow a little error...
if ( dist > 4 )
{
end -= CurrentViewForward()*4;
}
int traceFlags = MASK_OPAQUE|CONTENTS_MONSTER|CONTENTS_DEBRIS;
CTraceFilterGlow filter(NULL, COLLISION_GROUP_NONE);
trace_t tr;
UTIL_TraceLine( CurrentViewOrigin(), end, traceFlags, &filter, &tr );
if ( tr.fraction != 1.0f )
return -1;
}
return dist;
}
void PixelVisibility_EndCurrentView()
{
g_PixelVisibilitySystem.EndView();
}
void PixelVisibility_EndScene()
{
g_PixelVisibilitySystem.EndScene();
}
float PixelVisibility_FractionVisible( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle )
{
if ( !queryHandle )
{
return GlowSightDistance( params.position, true ) > 0.0f ? 1.0f : 0.0f;
}
else
{
return g_PixelVisibilitySystem.GetFractionVisible( params, queryHandle );
}
}
bool PixelVisibility_IsAvailable()
{
return r_dopixelvisibility.GetBool() && g_PixelVisibilitySystem.SupportsOcclusion();
}
CON_COMMAND( pixelvis_debug, "Dump debug info" )
{
g_PixelVisibilitySystem.DebugInfo();
}

View File

@ -0,0 +1,53 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_PIXEL_VISIBILITY_H
#define C_PIXEL_VISIBILITY_H
#ifdef _WIN32
#pragma once
#endif
const float PIXELVIS_DEFAULT_PROXY_SIZE = 2.0f;
const float PIXELVIS_DEFAULT_FADE_TIME = 0.0625f;
typedef int pixelvis_handle_t;
struct pixelvis_queryparams_t
{
pixelvis_queryparams_t()
{
bSetup = false;
}
void Init( const Vector &origin, float proxySizeIn = PIXELVIS_DEFAULT_PROXY_SIZE, float proxyAspectIn = 1.0f, float fadeTimeIn = PIXELVIS_DEFAULT_FADE_TIME )
{
position = origin;
proxySize = proxySizeIn;
proxyAspect = proxyAspectIn;
fadeTime = fadeTimeIn;
bSetup = true;
bSizeInScreenspace = false;
}
Vector position;
float proxySize;
float proxyAspect;
float fadeTime;
bool bSetup;
bool bSizeInScreenspace;
};
float PixelVisibility_FractionVisible( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle );
float StandardGlowBlend( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle, int rendermode, int renderfx, int alpha, float *pscale );
void PixelVisibility_EndCurrentView();
void PixelVisibility_EndScene();
float GlowSightDistance( const Vector &glowOrigin, bool bShouldTrace );
// returns true if the video hardware is doing the tests, false is traceline is doing so.
bool PixelVisibility_IsAvailable();
#endif // C_PIXEL_VISIBILITY_H

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