diff --git a/.gitattributes b/.gitattributes
index 8309c7d7..437f140a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,9 +1,5 @@
-creategameprojects text
-createallprojects text
-xcode_ccache_wrapper text
-vpc text
-vpc_linux binary
-vpc_osx binary
+buildallprojects text
+vpc binary
*.sh text
*.bat text
@@ -37,15 +33,13 @@ vpc_osx binary
*.asm text
.gitignore text
-sourcesdk_def.mak text
-smdlexp.mak text
-README text
+README.md text
CONTRIBUTING text
LICENSE text
*.exe binary
+*.dll binary
protoc binary
ccache binary
-gtest_output_test_golden_lin.txt binary
-mod_*_english.txt binary
+*_english.txt binary
diff --git a/.gitignore b/.gitignore
index b2eabb93..47340f78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,3 +54,451 @@ config.cfg
# shader files
*.tmp
+# GCH
+*.h.gch
+*.h.gch.d
+
+*.sln
+*.slnx
+*.vcproj
+*.vcxproj
+*.vcxproj.*
+*.obj
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+*.userprefs
+mono_crash.*
+.vs/*
+*.pdb
+*.log
+*.tlog
+*.exp
+*.FileListAbsolute.txt
+
+evntprov.h
+
+generated_proto_*
+*.pb.cc
+*.pb.hh
+
+*_Release/
+*_Debug/
+Release/x64/*
+Debug/x64/*
+Release_*/
+Debug_*/
+*.lastbuildstate
+*.recipe
+
+*_nut.h # vscript autogen file
+
+*.vpc.sentinel
+*.vpc_crc
+*.vpc_cache
+
+*_nut.h
+
+__vpc__/
+_vpc_/
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
\ No newline at end of file
diff --git a/CONTRIBUTING b/CONTRIBUTING
index feeb7dab..809ecd58 100644
--- a/CONTRIBUTING
+++ b/CONTRIBUTING
@@ -36,4 +36,3 @@ fine community-maintained repositories instead:
If you are going to make a pull request, please keep them as granular as
possible. Pull requests with 3-4 unrelated changes in them aren't going to
be accepted.
-
diff --git a/LICENSE b/LICENSE
index 3ade2f32..5f937d3a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,43 +1,23 @@
SOURCE 1 SDK LICENSE
-Source SDK Copyright(c) Valve Corp.
+Copyright(c) Valve Corporation. All rights reserved
-THIS DOCUMENT DESCRIBES A CONTRACT BETWEEN YOU AND VALVE
-CORPORATION ("Valve"). PLEASE READ IT BEFORE DOWNLOADING OR USING
-THE SOURCE ENGINE SDK ("SDK"). BY DOWNLOADING AND/OR USING THE
-SOURCE ENGINE SDK YOU ACCEPT THIS LICENSE. IF YOU DO NOT AGREE TO
-THE TERMS OF THIS LICENSE PLEASE DONT DOWNLOAD OR USE THE SDK.
+THESE LICENSE TERMS ARE AN AGREEMENT BETWEEN YOU AND VALVE CORPORATION ("VALVE") FOR THE SOURCE 1 SDK (“SDK”).
+PLEASE READ THEM BEFORE DOWNLOADING OR USING THE SDK. BY USING THE SDK, YOU ACKNOWLEDGE THAT YOU HAVE READ AND AGREE
+TO BE BOUND BY THESE LICENSE TERMS. IF YOU DO NOT AGREE TO THESE TERMS, YOU MAY NOT USE THE SDK.
- You may, free of charge, download and use the SDK to develop a modified Valve game
-running on the Source engine. You may distribute your modified Valve game in source and
-object code form, but only for free. Terms of use for Valve games are found in the Steam
-Subscriber Agreement located here: http://store.steampowered.com/subscriber_agreement/
+You may, free of charge, use, copy, and modify the SDK to develop a modified Valve game running on Valve's Source 1 engine,
+which game can be distributed in source and object code form if it is free and meets the terms of use for Valve games in the
+Steam Subscriber Agreement located here: http://store.steampowered.com/subscriber_agreement/. You may also distribute the SDK
+(or any substantial portions of the SDK) and any modifications you make to the SDK in both source code and object code form,
+provided you meet the following conditions: distributions of the SDK must (1) be free of charge; (2) include this LICENSE file
+and thirdpartylegalnotices.txt; and (3) include the above copyright notice and the additional legal provisions below.
- You may copy, modify, and distribute the SDK and any modifications you make to the
-SDK in source and object code form, but only for free. Any distribution of this SDK must
-include this LICENSE file and thirdpartylegalnotices.txt.
+DISCLAIMER OF WARRANTIES. THE SDK AND ANY OTHER MATERIAL YOU DOWNLOAD IS PROVIDED BY VALVE "AS IS" AND “AS AVAILABLE” WITHOUT
+WARRANTY OF ANY KIND. VALVE EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND WHETHER EXPRESS OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, TITLE AND FITNESS FOR A PARTICULAR PURPOSE.
+
+LIMITATION OF LIABILITY. VALVE AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES WHATSOEVER ) THAT MAY BE INCURRED BY YOU EVEN IF VALVE HAS BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
- Any distribution of the SDK or a substantial portion of the SDK must include the above
-copyright notice and the following:
-
- DISCLAIMER OF WARRANTIES. THE SOURCE SDK AND ANY
- OTHER MATERIAL DOWNLOADED BY LICENSEE IS PROVIDED
- "AS IS". VALVE AND ITS SUPPLIERS DISCLAIM ALL
- WARRANTIES WITH RESPECT TO THE SDK, EITHER EXPRESS
- OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED
- WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT,
- TITLE AND FITNESS FOR A PARTICULAR PURPOSE.
-
- LIMITATION OF LIABILITY. IN NO EVENT SHALL VALVE OR
- ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
- (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
- BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
- BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
- ARISING OUT OF THE USE OF OR INABILITY TO USE THE
- ENGINE AND/OR THE SDK, EVEN IF VALVE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-
-If you would like to use the SDK for a commercial purpose, please contact Valve at
-sourceengine@valvesoftware.com.
+
\ No newline at end of file
diff --git a/README b/README
deleted file mode 100644
index 3ade2f32..00000000
--- a/README
+++ /dev/null
@@ -1,43 +0,0 @@
- SOURCE 1 SDK LICENSE
-
-Source SDK Copyright(c) Valve Corp.
-
-THIS DOCUMENT DESCRIBES A CONTRACT BETWEEN YOU AND VALVE
-CORPORATION ("Valve"). PLEASE READ IT BEFORE DOWNLOADING OR USING
-THE SOURCE ENGINE SDK ("SDK"). BY DOWNLOADING AND/OR USING THE
-SOURCE ENGINE SDK YOU ACCEPT THIS LICENSE. IF YOU DO NOT AGREE TO
-THE TERMS OF THIS LICENSE PLEASE DONT DOWNLOAD OR USE THE SDK.
-
- You may, free of charge, download and use the SDK to develop a modified Valve game
-running on the Source engine. You may distribute your modified Valve game in source and
-object code form, but only for free. Terms of use for Valve games are found in the Steam
-Subscriber Agreement located here: http://store.steampowered.com/subscriber_agreement/
-
- You may copy, modify, and distribute the SDK and any modifications you make to the
-SDK in source and object code form, but only for free. Any distribution of this SDK must
-include this LICENSE file and thirdpartylegalnotices.txt.
-
- Any distribution of the SDK or a substantial portion of the SDK must include the above
-copyright notice and the following:
-
- DISCLAIMER OF WARRANTIES. THE SOURCE SDK AND ANY
- OTHER MATERIAL DOWNLOADED BY LICENSEE IS PROVIDED
- "AS IS". VALVE AND ITS SUPPLIERS DISCLAIM ALL
- WARRANTIES WITH RESPECT TO THE SDK, EITHER EXPRESS
- OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED
- WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT,
- TITLE AND FITNESS FOR A PARTICULAR PURPOSE.
-
- LIMITATION OF LIABILITY. IN NO EVENT SHALL VALVE OR
- ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
- (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
- BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
- BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
- ARISING OUT OF THE USE OF OR INABILITY TO USE THE
- ENGINE AND/OR THE SDK, EVEN IF VALVE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-
-If you would like to use the SDK for a commercial purpose, please contact Valve at
-sourceengine@valvesoftware.com.
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..4344b6d8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,67 @@
+# Source SDK 2013
+
+Source code for Source SDK 2013.
+
+Contains the game code for Half-Life 2, HL2: DM and TF2.
+
+**Now including Team Fortress 2! ✨**
+
+## Build instructions
+
+Clone the repository using the following command:
+
+`git clone https://github.com/ValveSoftware/source-sdk-2013`
+
+### Windows
+
+Requirements:
+ - Source SDK 2013 Multiplayer installed via Steam
+ - Visual Studio 2022
+
+Inside the cloned directory, navigate to `src`, run:
+```bat
+createallprojects.bat
+```
+This will generate the Visual Studio project `everything.sln` which will be used to build your mod.
+
+Then, on the menu bar, go to `Build > Build Solution`, and wait for everything to build.
+
+You can then select the `Client (Mod Name)` project you wish to run, right click and select `Set as Startup Project` and hit the big green `> Local Windows Debugger` button on the tool bar in order to launch your mod.
+
+The default launch options should be already filled in for the `Release` configuration.
+
+### Linux
+
+Requirements:
+ - Source SDK 2013 Multiplayer installed via Steam
+ - podman
+
+Inside the cloned directory, navigate to `src`, run:
+```bash
+./buildallprojects
+```
+
+This will build all the projects related to the SDK and your mods automatically against the Steam Runtime.
+
+You can then, in the root of the cloned directory, you can navigate to `game` and run your mod by launching the build launcher for your mod project, eg:
+```bash
+./mod_tf
+```
+
+*Mods that are distributed on Steam MUST be built against the Steam Runtime, which the above steps will automatically do for you.*
+
+## Distributing your Mod
+
+There is guidance on distributing your mod both on and off Steam available at the following link:
+
+https://partner.steamgames.com/doc/sdk/uploading/distributing_source_engine
+
+## Additional Resources
+
+- [Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Source_SDK_2013)
+
+## License
+
+The SDK is licensed to users on a non-commercial basis under the [SOURCE 1 SDK LICENSE](LICENSE), which is contained in the [LICENSE](LICENSE) file in the root of the repository.
+
+For more information, see [Distributing your Mod](#markdown-header-distributing-your-mod).
diff --git a/game/bin/linux64/libsteam_api.so b/game/bin/linux64/libsteam_api.so
new file mode 100644
index 00000000..d755843a
Binary files /dev/null and b/game/bin/linux64/libsteam_api.so differ
diff --git a/game/bin/x64/steam_api64.dll b/game/bin/x64/steam_api64.dll
new file mode 100644
index 00000000..2b428120
Binary files /dev/null and b/game/bin/x64/steam_api64.dll differ
diff --git a/game/mod_hl2mp/gameinfo.txt b/game/mod_hl2mp/gameinfo.txt
index 2f49bead..2246f253 100644
--- a/game/mod_hl2mp/gameinfo.txt
+++ b/game/mod_hl2mp/gameinfo.txt
@@ -2,17 +2,17 @@
{
game "My First HL2MP Mod"
title "HALF+LIFE'"
- title2 "deathmatch mod"
+ title2 "deathmatch"
type multiplayer_only
nomodels 0
nohimodel 1
nocrosshair 1
+ supportsvr 1
hidden_maps
{
"test_speakers" 1
"test_hardware" 1
}
- supportsvr 1
FileSystem
@@ -20,66 +20,76 @@
SteamAppId 243750
//
- // The code that loads this file automatically does a few things here:
+ // Setup engine search paths.
//
- // 1. For each "Game" search path, it adds a "GameBin" path, in
\bin
- // 2. For each "Game" search path, it adds another "Game" path in front of it with _ at the end.
- // For example: c:\hl2\cstrike on a french machine would get a c:\hl2\cstrike_french path added to it.
- // 3. For the first "Game" search path, it adds a search path called "MOD".
- // 4. For the first "Game" search path, it adds a search path called "DEFAULT_WRITE_PATH".
+ // If a search path contains "_english", and the current language is not english, then
+ // another search path will be inserted above the english one by replacing "_english" with
+ // the appropriate language.
//
-
+ // To debug how the engine has parsed this file, type "path" at the console.
//
// Search paths are relative to the base directory, which is where hl2.exe is found.
//
// |gameinfo_path| points at the directory where gameinfo.txt is.
- // We always want to mount that directory relative to gameinfo.txt, so
- // people can mount stuff in c:\mymod, and the main game resources are in
- // someplace like c:\program files\valve\steam\steamapps\half-life 2.
+ // |all_source_engine_paths| points at the directory cintaining HL2 shared content.
//
SearchPaths
{
+
// First, mount all user customizations. This will search for VPKs and subfolders
// and mount them in alphabetical order. The easiest way to distribute a mod is to
// pack up the custom content into a VPK. To "install" a mod, just drop it in this
// folder.
//
// Note that this folder is scanned only when the game is booted.
- game+mod hl2mp/custom/*
- game+mod hl2/custom/*
+ game+mod mod_hl2mp/custom/*
// Now search loose files. We'll set the directory containing the gameinfo.txt file
// as the first "mod" search path (after any user customizations). This is also the one
// that's used when writing to the "mod" path.
- game+mod+mod_write+default_write_path |gameinfo_path|.
+ mod+mod_write |gameinfo_path|.
+ game+game_write |gameinfo_path|.
+ default_write_path |gameinfo_path|.
gamebin |gameinfo_path|bin
// We search VPK files before ordinary folders, because most files will be found in
// VPK and we can avoid making thousands of file system calls to attempt to open files
// in folders where they don't exist. (Searching a VPK is much faster than making an operating
// system call.)
- game_lv hl2/hl2_lv.vpk
- game+mod hl2mp/hl2mp_english.vpk
- game+mod hl2mp/hl2mp_pak.vpk
- game |all_source_engine_paths|hl2/hl2_english.vpk
- game |all_source_engine_paths|hl2/hl2_pak.vpk
- game |all_source_engine_paths|hl2/hl2_textures.vpk
- game |all_source_engine_paths|hl2/hl2_sound_vo_english.vpk
- game |all_source_engine_paths|hl2/hl2_sound_misc.vpk
- game |all_source_engine_paths|hl2/hl2_misc.vpk
- platform |all_source_engine_paths|platform/platform_misc.vpk
+ game+mod |appid_243750|hl2mp/hl2mp_english.vpk
+ game+mod |appid_243750|hl2mp/hl2mp_pak.vpk
- // Add the HL2 directory as a game search path. This is also where where writes
- // to the "game" path go.
- game+game_write hl2mp
+ game |appid_243750|hl2_complete/hl2_complete_textures.vpk
+ game |appid_243750|hl2_complete/hl2_complete_sound_vo_english.vpk
+ game |appid_243750|hl2_complete/hl2_complete_sound_misc.vpk
+ game |appid_243750|hl2_complete/hl2_complete_misc.vpk
- // Where the game's binaries are
- gamebin hl2mp/bin
+ game |appid_243750|hl2/hl2_textures.vpk
+ game |appid_243750|hl2/hl2_sound_vo_english.vpk
+ game |appid_243750|hl2/hl2_sound_misc.vpk
+ game |appid_243750|hl2/hl2_misc.vpk
+
+ platform |appid_243750|platform/platform_misc.vpk
+
+ game |appid_243750|hl2mp
// Last, mount in shared HL2 loose files
- game |all_source_engine_paths|hl2mp
- game |all_source_engine_paths|hl2
- platform |all_source_engine_paths|platform
+ game |appid_243750|hl2_complete
+ game |appid_243750|hl2
+ platform |appid_243750|platform
+
+ // Random files downloaded from gameservers go into a seperate directory, so
+ // that it's easy to keep those files segregated from the official game files
+ // or customizations intentially installed by the user.
+ //
+ // This directory is searched LAST. If you visit a server and download
+ // a custom model, etc, we don't want that file to override the default
+ // game file indefinitely (after you have left the server). Servers CAN have
+ // custom content that overrides the default game files, it just needs to be
+ // packed up in the .bsp file so that it will be mounted as a map search pack.
+ // The map search pack is mounted at the top of the search path list,
+ // but only while you are connected that server and on that map.
+ game+download mod_hl2mp/download
}
}
}
diff --git a/game/mod_hl2mp/resource/ClientScheme.res b/game/mod_hl2mp/resource/ClientScheme.res
deleted file mode 100644
index ea342416..00000000
--- a/game/mod_hl2mp/resource/ClientScheme.res
+++ /dev/null
@@ -1,1583 +0,0 @@
-///////////////////////////////////////////////////////////
-// Tracker scheme resource file
-//
-// sections:
-// Colors - all the colors used by the scheme
-// BaseSettings - contains settings for app to use to draw controls
-// Fonts - list of all the fonts used by app
-// Borders - description of all the borders
-//
-///////////////////////////////////////////////////////////
-Scheme
-{
- //////////////////////// COLORS ///////////////////////////
- //////////////////////// COLORS ///////////////////////////
- Colors
- {
- // base colors
- "Orange" "255 176 0 255"
- "OrangeDim" "255 176 0 120"
- "LightOrange" "188 112 0 128"
-
- "Red" "192 28 0 140"
- "Black" "0 0 0 196"
- "TransparentBlack" "0 0 0 196"
- "TransparentLightBlack" "0 0 0 90"
-
- "Blank" "0 0 0 0"
- "ForTesting" "255 0 0 32"
- "ForTesting_Magenta" "255 0 255 255"
- "ForTesting_MagentaDim" "255 0 255 120"
- }
-
- ///////////////////// BASE SETTINGS ////////////////////////
- //
- // default settings for all panels
- // controls use these to determine their settings
- BaseSettings
- {
- "FgColor" "255 220 0 100"
- "BgColor" "0 0 0 76"
-
- "Panel.FgColor" "255 220 0 100"
- "Panel.BgColor" "0 0 0 76"
-
- "BrightFg" "255 220 0 255"
-
- "DamagedBg" "180 0 0 200"
- "DamagedFg" "180 0 0 230"
- "BrightDamagedFg" "255 0 0 255"
-
- // weapon selection colors
- "SelectionNumberFg" "255 220 0 255"
- "SelectionTextFg" "255 220 0 255"
- "SelectionEmptyBoxBg" "0 0 0 80"
- "SelectionBoxBg" "0 0 0 80"
- "SelectionSelectedBoxBg" "0 0 0 80"
-
- "ZoomReticleColor" "255 220 0 255"
-
- // HL1-style HUD colors
- "Yellowish" "255 160 0 255"
- "Normal" "255 208 64 255"
- "Caution" "255 48 0 255"
-
- // Top-left corner of the "Half-Life 2" on the main screen
- "Main.Title1.X" "76"
- "Main.Title1.Y" "184"
- "Main.Title1.Color" "255 255 255 255"
-
- // Top-left corner of the "DEATHMATCH" on the main screen
- "Main.Title2.X" "315"
- "Main.Title2.Y" "222"
- "Main.Title2.Color" "255 255 255 180"
-
- // Top-left corner of the menu on the main screen
- "Main.Menu.X" "76"
- "Main.Menu.Y" "240"
-
- // Blank space to leave beneath the menu on the main screen
- "Main.BottomBorder" "32"
-
-
-///HERE
- // vgui_controls color specifications
- Border.Bright "LightOrange" // the lit side of a control
- Border.Dark "LightOrange" // the dark/unlit side of a control
- Border.Selection "Blank" // the additional border color for displaying the default/selected button
-
- Button.TextColor "Orange"
- Button.BgColor "Blank"
- Button.ArmedTextColor "Orange"
- Button.ArmedBgColor "Red"
- Button.DepressedTextColor "Orange"
- Button.DepressedBgColor "Red"
-
- CheckButton.TextColor "Orange"
- CheckButton.SelectedTextColor "Orange"
- CheckButton.BgColor "TransparentBlack"
- CheckButton.Border1 "Border.Dark" // the left checkbutton border
- CheckButton.Border2 "Border.Bright" // the right checkbutton border
- CheckButton.Check "Orange" // color of the check itself
-
- ComboBoxButton.ArrowColor "Orange"
- ComboBoxButton.ArmedArrowColor "Orange"
- ComboBoxButton.BgColor "TransparentBlack"
- ComboBoxButton.DisabledBgColor "Blank"
-
- Frame.BgColor "TransparentBlack"
- Frame.OutOfFocusBgColor "TransparentBlack"
- Frame.FocusTransitionEffectTime "0.0" // time it takes for a window to fade in/out on focus/out of focus
- Frame.TransitionEffectTime "0.0" // time it takes for a window to fade in/out on open/close
- Frame.AutoSnapRange "0"
- FrameGrip.Color1 "Blank"
- FrameGrip.Color2 "Blank"
- FrameTitleButton.FgColor "Blank"
- FrameTitleButton.BgColor "Blank"
- FrameTitleButton.DisabledFgColor "Blank"
- FrameTitleButton.DisabledBgColor "Blank"
- FrameSystemButton.FgColor "Blank"
- FrameSystemButton.BgColor "Blank"
- FrameSystemButton.Icon ""
- FrameSystemButton.DisabledIcon ""
- FrameTitleBar.TextColor "Orange"
- FrameTitleBar.BgColor "Blank"
- FrameTitleBar.DisabledTextColor "Orange"
- FrameTitleBar.DisabledBgColor "Blank"
-
- GraphPanel.FgColor "Orange"
- GraphPanel.BgColor "TransparentBlack"
-
- Label.TextDullColor "Orange"
- Label.TextColor "Orange"
- Label.TextBrightColor "Orange"
- Label.SelectedTextColor "Orange"
- Label.BgColor "Blank"
- Label.DisabledFgColor1 "Blank"
- Label.DisabledFgColor2 "LightOrange"
-
- ListPanel.TextColor "Orange"
- ListPanel.BgColor "TransparentBlack"
- ListPanel.SelectedTextColor "Black"
- ListPanel.SelectedBgColor "Red"
- ListPanel.SelectedOutOfFocusBgColor "Red"
- ListPanel.EmptyListInfoTextColor "Orange"
-
- Menu.TextColor "Orange"
- Menu.BgColor "TransparentBlack"
- Menu.ArmedTextColor "Orange"
- Menu.ArmedBgColor "Red"
- Menu.TextInset "6"
-
- Chat.TypingText "Orange"
-
- Panel.FgColor "OrangeDim"
- Panel.BgColor "blank"
-
- ProgressBar.FgColor "Orange"
- ProgressBar.BgColor "TransparentBlack"
-
- PropertySheet.TextColor "Orange"
- PropertySheet.SelectedTextColor "Orange"
- PropertySheet.TransitionEffectTime "0.25" // time to change from one tab to another
-
- RadioButton.TextColor "Orange"
- RadioButton.SelectedTextColor "Orange"
-
- RichText.TextColor "Orange"
- RichText.BgColor "Blank"
- RichText.SelectedTextColor "Orange"
- RichText.SelectedBgColor "Blank"
-
- ScrollBarButton.FgColor "Orange"
- ScrollBarButton.BgColor "Blank"
- ScrollBarButton.ArmedFgColor "Orange"
- ScrollBarButton.ArmedBgColor "Blank"
- ScrollBarButton.DepressedFgColor "Orange"
- ScrollBarButton.DepressedBgColor "Blank"
-
- ScrollBarSlider.FgColor "Blank" // nob color
- ScrollBarSlider.BgColor "Blank" // slider background color
-
- SectionedListPanel.HeaderTextColor "Orange"
- SectionedListPanel.HeaderBgColor "Blank"
- SectionedListPanel.DividerColor "Black"
- SectionedListPanel.TextColor "Orange"
- SectionedListPanel.BrightTextColor "Orange"
- SectionedListPanel.BgColor "TransparentLightBlack"
- SectionedListPanel.SelectedTextColor "Black"
- SectionedListPanel.SelectedBgColor "Red"
- SectionedListPanel.OutOfFocusSelectedTextColor "Black"
- SectionedListPanel.OutOfFocusSelectedBgColor "255 255 255 32"
-
- Slider.NobColor "108 108 108 255"
- Slider.TextColor "127 140 127 255"
- Slider.TrackColor "31 31 31 255"
- Slider.DisabledTextColor1 "117 117 117 255"
- Slider.DisabledTextColor2 "30 30 30 255"
-
- TextEntry.TextColor "Orange"
- TextEntry.BgColor "TransparentBlack"
- TextEntry.CursorColor "Orange"
- TextEntry.DisabledTextColor "Orange"
- TextEntry.DisabledBgColor "Blank"
- TextEntry.SelectedTextColor "Black"
- TextEntry.SelectedBgColor "Red"
- TextEntry.OutOfFocusSelectedBgColor "Red"
- TextEntry.FocusEdgeColor "TransparentBlack"
-
- ToggleButton.SelectedTextColor "Orange"
-
- Tooltip.TextColor "TransparentBlack"
- Tooltip.BgColor "Red"
-
- TreeView.BgColor "TransparentBlack"
-
- WizardSubPanel.BgColor "Blank"
-
- // scheme-specific colors
- "FgColor" "Orange"
- "BgColor" "TransparentBlack"
-
- "ViewportBG" "Blank"
- "team0" "204 204 204 255" // Spectators
- "team1" "255 64 64 255" // CT's
- "team2" "153 204 255 255" // T's
-
- "MapDescriptionText" "Orange" // the text used in the map description window
- "CT_Blue" "153 204 255 255"
- "T_Red" "255 64 64 255"
- "Hostage_Yellow" "Panel.FgColor"
- "HudIcon_Green" "0 160 0 255"
- "HudIcon_Red" "160 0 0 255"
-
- // CHudMenu
- "ItemColor" "255 167 42 200" // default 255 167 42 255
- "MenuColor" "233 208 173 255"
- "MenuBoxBg" "0 0 0 100"
-
- // weapon selection colors
- "SelectionNumberFg" "255 220 0 200"
- "SelectionTextFg" "255 220 0 200"
- "SelectionEmptyBoxBg" "0 0 0 80"
- "SelectionBoxBg" "0 0 0 80"
- "SelectionSelectedBoxBg" "0 0 0 190"
-
- // Hint message colors
- "HintMessageFg" "255 255 255 255"
- "HintMessageBg" "0 0 0 60"
-
- "ProgressBarFg" "255 30 13 255"
-
- // Top-left corner of the "Counter-Strike" on the main screen
- "Main.Title1.X" "32"
- "Main.Title1.Y" "180"
- "Main.Title1.Color" "255 255 255 255"
-
- // Top-left corner of the "SOURCE" on the main screen
- "Main.Title2.X" "380"
- "Main.Title2.Y" "205"
- "Main.Title2.Color" "255 255 255 80"
-
- // Top-left corner of the "BETA" on the main screen
- "Main.Title3.X" "460"
- "Main.Title3.Y" "-10"
- "Main.Title3.Color" "255 255 0 255"
-
- // Top-left corner of the menu on the main screen
- "Main.Menu.X" "32"
- "Main.Menu.Y" "248"
-
- // Blank space to leave beneath the menu on the main screen
- "Main.BottomBorder" "32"
- }
-
- //////////////////////// FONTS /////////////////////////////
- //
- // describes all the fonts
- Fonts
- {
- // fonts are used in order that they are listed
- // fonts are used in order that they are listed
- "DebugFixed"
- {
- "1"
- {
- "name" "Courier New"
- "tall" "14"
- "weight" "400"
- "antialias" "1"
- }
- }
- // fonts are used in order that they are listed
- "DebugFixedSmall"
- {
- "1"
- {
- "name" "Courier New"
- "tall" "14"
- "weight" "400"
- "antialias" "1"
- }
- }
- // fonts listed later in the order will only be used if they fulfill a range not already filled
- // if a font fails to load then the subsequent fonts will replace
- Default
- {
- "1"
- {
- "name" "Verdana"
- "tall" "9"
- "weight" "700"
- "antialias" "1"
- "yres" "1 599"
- }
- "2"
- {
- "name" "Verdana"
- "tall" "12"
- "weight" "700"
- "antialias" "1"
- "yres" "600 767"
- }
- "3"
- {
- "name" "Verdana"
- "tall" "14"
- "weight" "900"
- "antialias" "1"
- "yres" "768 1023"
- }
- "4"
- {
- "name" "Verdana"
- "tall" "20"
- "weight" "900"
- "antialias" "1"
- "yres" "1024 1199"
- }
- "5"
- {
- "name" "Verdana"
- "tall" "24"
- "weight" "900"
- "antialias" "1"
- "yres" "1200 10000"
- "additive" "1"
- }
- }
- "DefaultSmall"
- {
- "1"
- {
- "name" "Verdana"
- "tall" "12"
- "weight" "0"
- "range" "0x0000 0x017F"
- "yres" "480 599"
- }
- "2"
- {
- "name" "Verdana"
- "tall" "13"
- "weight" "0"
- "range" "0x0000 0x017F"
- "yres" "600 767"
- }
- "3"
- {
- "name" "Verdana"
- "tall" "14"
- "weight" "0"
- "range" "0x0000 0x017F"
- "yres" "768 1023"
- "antialias" "1"
- }
- "4"
- {
- "name" "Verdana"
- "tall" "20"
- "weight" "0"
- "range" "0x0000 0x017F"
- "yres" "1024 1199"
- "antialias" "1"
- }
- "5"
- {
- "name" "Verdana"
- "tall" "24"
- "weight" "0"
- "range" "0x0000 0x017F"
- "yres" "1200 6000"
- "antialias" "1"
- }
- "6"
- {
- "name" "Arial"
- "tall" "12"
- "range" "0x0000 0x00FF"
- "weight" "0"
- }
- }
- "DefaultVerySmall"
- {
- "1"
- {
- "name" "Verdana"
- "tall" "12"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "480 599"
- }
- "2"
- {
- "name" "Verdana"
- "tall" "13"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "600 767"
- }
- "3"
- {
- "name" "Verdana"
- "tall" "14"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "768 1023"
- "antialias" "1"
- }
- "4"
- {
- "name" "Verdana"
- "tall" "20"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "1024 1199"
- "antialias" "1"
- }
- "5"
- {
- "name" "Verdana"
- "tall" "24"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "1200 6000"
- "antialias" "1"
- }
- "6"
- {
- "name" "Verdana"
- "tall" "12"
- "range" "0x0000 0x00FF"
- "weight" "0"
- }
- "7"
- {
- "name" "Arial"
- "tall" "11"
- "range" "0x0000 0x00FF"
- "weight" "0"
- }
- }
- "MenuTitle"
- {
- "1"
- {
- "name" "Verdana Bold"
- "tall" "18"
- "weight" "500"
- }
- }
- WeaponIcons
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "64"
- "weight" "0"
- "antialias" "1"
- "additive" "1"
- "custom" "1"
- }
- }
- WeaponIconsSelected
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "64"
- "weight" "0"
- "antialias" "1"
- "blur" "5"
- "scanlines" "2"
- "additive" "1"
- "custom" "1"
- }
- }
- Crosshairs
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "40" [!$OSX]
- "tall" "41" [$OSX]
- "weight" "0"
- "antialias" "0"
- "additive" "1"
- "custom" "1"
- "yres" "1 10000"
- }
- }
- QuickInfo
- {
- "1"
- {
- "name" "HL2cross"
- "tall" "28" [!$OSX]
- "tall" "50" [$OSX]
- "weight" "0"
- "antialias" "1"
- "additive" "1"
- "custom" "1" [!$OSX]
- }
- }
- HudNumbers
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "32"
- "weight" "0"
- "antialias" "1"
- "additive" "1"
- "custom" "1"
- }
- }
- HudNumbersGlow
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "32"
- "weight" "0"
- "blur" "4"
- "scanlines" "2"
- "antialias" "1"
- "additive" "1"
- "custom" "1"
- }
- }
- HudNumbersSmall
- {
- "1"
- {
- "name" "HalfLife2" [!$OSX]
- "name" "Helvetica Bold" [$OSX]
- "tall" "16"
- "weight" "1000"
- "additive" "1"
- "antialias" "1"
- "custom" "1"
- }
- }
- HudSelectionNumbers
- {
- "1"
- {
- "name" "Verdana"
- "tall" "11"
- "weight" "700"
- "antialias" "1"
- "additive" "1"
- }
- }
- HudHintTextLarge
- {
- "1"
- {
- "name" "Verdana" [!$OSX]
- "name" "Helvetica Bold" [$OSX]
- "tall" "14"
- "weight" "1000"
- "antialias" "1"
- "additive" "1"
- }
- }
- HudHintTextSmall
- {
- "1"
- {
- "name" "Verdana" [!$OSX]
- "name" "Helvetica" [$OSX]
- "tall" "11"
- "weight" "0"
- "antialias" "1"
- "additive" "1"
- }
- }
- HudSelectionText
- {
- "1"
- {
- "name" "Verdana"
- "tall" "8"
- "weight" "700"
- "antialias" "1"
- "yres" "1 599"
- }
- "2"
- {
- "name" "Verdana"
- "tall" "10"
- "weight" "700"
- "antialias" "1"
- "yres" "600 767"
- }
- "3"
- {
- "name" "Verdana"
- "tall" "12"
- "weight" "900"
- "antialias" "1"
- "yres" "768 1023"
- }
- "4"
- {
- "name" "Verdana"
- "tall" "16"
- "weight" "900"
- "antialias" "1"
- "yres" "1024 1199"
- }
- "5"
- {
- "name" "Verdana"
- "tall" "17"
- "weight" "1000"
- "antialias" "1"
- "yres" "1200 10000"
- }
- }
- BudgetLabel
- {
- "1"
- {
- "name" "Courier New"
- "tall" "14"
- "weight" "400"
- "outline" "1"
- }
- }
- DebugOverlay
- {
- "1"
- {
- "name" "Courier New"
- "tall" "14"
- "weight" "400"
- "outline" "1"
- }
- }
- "CloseCaption_Normal"
- {
- "1"
- {
- "name" "Tahoma" [!$OSX]
- "name" "Verdana" [$OSX]
- "tall" "26" [!$OSX]
- "tall" "24" [$OSX]
- "tall" "26"
- "weight" "500"
- }
- }
- "CloseCaption_Italic"
- {
- "1"
- {
- "name" "Tahoma" [!$OSX]
- "name" "Verdana Italic" [$OSX]
- "tall" "26" [!$OSX]
- "tall" "24" [$OSX]
- "tall" "26"
- "weight" "500"
- "italic" "1"
- }
- }
- "CloseCaption_Bold"
- {
- "1"
- {
- "name" "Tahoma" [!$OSX]
- "name" "Verdana Bold" [$OSX]
- "tall" "26" [!$OSX]
- "tall" "24" [$OSX]
- "tall" "26"
- "weight" "900"
- }
- }
- "CloseCaption_BoldItalic"
- {
- "1"
- {
- "name" "Tahoma" [!$OSX]
- "name" "Verdana Bold Italic" [$OSX]
- "tall" "26" [!$OSX]
- "tall" "24" [$OSX]
- "tall" "26"
- "weight" "900"
- "italic" "1"
- }
- }
- "CloseCaption_Small"
- {
- "1"
- {
- "name" "Tahoma" [!$OSX]
- "name" "Verdana" [$OSX]
- "tall" "16" [!$OSX]
- "tall" "14" [$OSX]
- "tall_hidef" "24"
- "weight" "900"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- }
- }
- // this is the symbol font
- "Marlett"
- {
- "1"
- {
- "name" "Marlett"
- "tall" "14"
- "weight" "0"
- "symbol" "1"
- }
- }
- "Trebuchet24"
- {
- "1"
- {
- "name" "Trebuchet MS"
- "tall" "24"
- "weight" "900"
- "range" "0x0000 0x007F" // Basic Latin
- "antialias" "1"
- "additive" "1"
- }
- }
- "Trebuchet18"
- {
- "1"
- {
- "name" "Trebuchet MS"
- "tall" "18"
- "weight" "900"
- }
- }
- ClientTitleFont
- {
- "1"
- {
- "name" "HL2MP"
- "tall" "46"
- "weight" "0"
- "additive" "0"
- "antialias" "1"
- }
- }
- CreditsLogo
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "128"
- "weight" "0"
- "antialias" "1"
- "additive" "1"
- "custom" "1"
- }
- }
- CreditsText
- {
- "1"
- {
- "name" "Trebuchet MS"
- "tall" "20"
- "weight" "900"
- "antialias" "1"
- "additive" "1"
- }
- }
- CreditsOutroLogos
- {
- "1"
- {
- "name" "HalfLife2"
- "tall" "48"
- "weight" "0"
- "antialias" "1"
- "additive" "1"
- "custom" "1"
- }
- }
- CreditsOutroText
- {
- "1"
- {
- "name" "Verdana"
- "tall" "9"
- "weight" "900"
- "antialias" "1"
- }
- }
- CenterPrintText
- {
- // note that this scales with the screen resolution
- "1"
- {
- "name" "Trebuchet MS" [!$OSX]
- "name" "Helvetica" [$OSX]
- "tall" "18"
- "weight" "900"
- "antialias" "1"
- "additive" "1"
- }
- }
- "ChatFont"
- {
- "1"
- {
- "name" "Verdana"
- "tall" "12"
- "weight" "700"
- "yres" "480 599"
- "dropshadow" "1"
- }
- "2"
- {
- "name" "Verdana"
- "tall" "13"
- "weight" "700"
- "yres" "600 767"
- "dropshadow" "1"
- }
- "3"
- {
- "name" "Verdana"
- "tall" "14"
- "weight" "700"
- "yres" "768 1023"
- "dropshadow" "1"
- }
- "4"
- {
- "name" "Verdana"
- "tall" "20"
- "weight" "700"
- "yres" "1024 1199"
- "dropshadow" "1"
- }
- "5"
- {
- "name" "Verdana"
- "tall" "24"
- "weight" "700"
- "yres" "1200 10000"
- "dropshadow" "1"
- }
- }
- "TargetID"
- {
- "1"
- {
- "name" "Trebuchet MS"
- "tall" "24"
- "weight" "900"
- "range" "0x0000 0x007F" // Basic Latin
- "antialias" "1"
- "additive" "0"
- }
- }
- "HL2MPTypeDeath"
- {
- "1"
- {
- "name" "HL2MP" // csd.ttf
- "tall" "32"
- "weight" "0"
- "additive" "1"
- "antialias" "1"
- "custom" "1" [$OSX]
- }
- }
- // Used by scoreboard and spectator UI for names which don't map in the normal fashion
- "DefaultVerySmallFallBack"
- {
- "1"
- {
- "name" "Verdana"
- "tall" "10"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "480 599"
- "antialias" "1"
- }
- "2"
- {
- "name" "Verdana"
- "tall" "12"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "600 1199"
- "antialias" "1"
- }
- "3"
- {
- "name" "Verdana"
- "tall" "15"
- "weight" "0"
- "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
- "yres" "1200 6000"
- "antialias" "1"
- }
- }
-
- }
-
- //////////////////// BORDERS //////////////////////////////
- //
- // describes all the border types
- Borders
- {
- BaseBorder
- {
- "inset" "0 0 1 1"
- Left
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
- }
-
- TitleButtonBorder
- {
- "inset" "0 0 1 1"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
-
- TitleButtonDisabledBorder
- {
- "inset" "0 0 1 1"
- Left
- {
- "1"
- {
- "color" "BgColor"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "BgColor"
- "offset" "1 0"
- }
- }
- Top
- {
- "1"
- {
- "color" "BgColor"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "BgColor"
- "offset" "0 0"
- }
- }
- }
-
- TitleButtonDepressedBorder
- {
- "inset" "1 1 1 1"
- Left
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
- }
-
- ScrollBarButtonBorder
- {
- "inset" "1 0 0 0"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
-
- ScrollBarButtonDepressedBorder
- {
- "inset" "2 2 0 0"
- Left
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
- }
-
- ButtonBorder
- {
- "inset" "0 0 0 0"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 1"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
-
- FrameBorder
- {
- "inset" "0 0 1 1"
- Left
- {
- "1"
- {
- "color" "ControlBG"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "ControlBG"
- "offset" "0 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "ControlBG"
- "offset" "0 1"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "ControlBG"
- "offset" "0 0"
- }
- }
- }
-
- TabBorder
- {
- "inset" "0 0 1 1"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
- }
-
- TabActiveBorder
- {
- "inset" "0 0 1 0"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "ControlBG"
- "offset" "6 2"
- }
- }
- }
-
-
- ToolTipBorder
- {
- "inset" "0 0 1 0"
- Left
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
-
- // this is the border used for default buttons (the button that gets pressed when you hit enter)
- ButtonKeyFocusBorder
- {
- "inset" "0 0 0 0"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 1"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
-
- ButtonDepressedBorder
- {
- "inset" "0 0 0 0"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 1"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
-
- ComboBoxBorder
- {
- "inset" "0 0 1 1"
- Left
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
- }
-
- MenuBorder
- {
- "inset" "1 1 1 1"
- Left
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 1"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "1 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
- }
- BrowserBorder
- {
- "inset" "0 0 0 0"
- Left
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Right
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
-
- Top
- {
- "1"
- {
- "color" "Border.Dark"
- "offset" "0 0"
- }
- }
-
- Bottom
- {
- "1"
- {
- "color" "Border.Bright"
- "offset" "0 0"
- }
- }
- }
- }
-
-
- //////////////////////// CUSTOM FONT FILES /////////////////////////////
- //
- // specifies all the custom (non-system) font files that need to be loaded to service the above described fonts
- CustomFontFiles
- {
- "1" "resource/HALFLIFE2.ttf"
- "1" "resource/HL2MP.ttf"
- "2" "resource/HL2crosshairs.ttf"
- }
-
-}
diff --git a/game/mod_hl2mp/resource/GameMenu.res b/game/mod_hl2mp/resource/GameMenu.res
deleted file mode 100644
index bbe4cccf..00000000
--- a/game/mod_hl2mp/resource/GameMenu.res
+++ /dev/null
@@ -1,64 +0,0 @@
-"GameMenu"
-{
- "1"
- {
- "label" "#GameUI_GameMenu_ResumeGame"
- "command" "ResumeGame"
- "OnlyInGame" "1"
- }
- "2"
- {
- "label" "#GameUI_GameMenu_Disconnect"
- "command" "Disconnect"
- "OnlyInGame" "1"
- }
- "3"
- {
- "label" "#GameUI_GameMenu_PlayerList"
- "command" "OpenPlayerListDialog"
- "OnlyInGame" "1"
- }
- "4"
- {
- "label" ""
- "command" ""
- "OnlyInGame" "1"
- }
- "5"
- {
- "label" "#GameUI_GameMenu_FindServers"
- "command" "OpenServerBrowser"
- }
- "6"
- {
- "label" "#GameUI_GameMenu_CreateServer"
- "command" "OpenCreateMultiplayerGameDialog"
- }
- "7"
- {
- "label" "#GameUI_GameMenu_ActivateVR"
- "command" "engine vr_activate"
- "InGameOrder" "40"
- "OnlyWhenVREnabled" "1"
- "OnlyWhenVRInactive" "1"
- }
- "8"
- {
- "label" "#GameUI_GameMenu_DeactivateVR"
- "command" "engine vr_deactivate"
- "InGameOrder" "40"
- "OnlyWhenVREnabled" "1"
- "OnlyWhenVRActive" "1"
- }
- "10"
- {
- "label" "#GameUI_GameMenu_Options"
- "command" "OpenOptionsDialog"
- }
- "11"
- {
- "label" "#GameUI_GameMenu_Quit"
- "command" "Quit"
- }
-}
-
diff --git a/game/mod_hl2mp/scripts/HudAnimations.txt b/game/mod_hl2mp/scripts/HudAnimations.txt
index 6b4b2788..7158268e 100644
--- a/game/mod_hl2mp/scripts/HudAnimations.txt
+++ b/game/mod_hl2mp/scripts/HudAnimations.txt
@@ -55,6 +55,17 @@ event FadeInTeamLine
Animate TeamDisplay Alpha "255" Linear 0.0 0.5
}
+event WeaponHighlight
+{
+ Animate HudWeaponSelection Blur "7" Linear 0.0 0.0
+ Animate HudWeaponSelection Blur "0" Deaccel 0.01 0.75
+
+ Animate HudWeaponSelection SelectedBoxColor "250 220 0 80" Linear 0.0 0.01
+ Animate HudWeaponSelection SelectedBoxColor "BgColor" Deaccel 0.1 1.5
+ Animate HudWeaponSelection SelectedFgColor "BrightFg" Linear 0.0 0.1
+ Animate HudWeaponSelection SelectedFgColor "FgColor" Linear 5.0 1.5
+}
+
event OpenWeaponSelectionMenu
{
StopEvent CloseWeaponSelectionMenu 0.0
@@ -62,7 +73,8 @@ event OpenWeaponSelectionMenu
StopEvent FadeOutWeaponSelectionMenu 0.0
// make the display visible
- Animate HudWeaponSelection Alpha "128" Linear 0.0 0.1
+ Animate HudWeaponSelection Alpha "128" Linear 0.0 0.1 [$WIN32]
+ Animate HudWeaponSelection Alpha "192" Linear 0.0 0.1 [$X360]
Animate HudWeaponSelection SelectionAlpha "255" Linear 0.0 0.1
Animate HudWeaponSelection FgColor "FgColor" Linear 0.0 0.1
Animate HudWeaponSelection TextColor "BrightFg" Linear 0.0 0.1
@@ -81,10 +93,14 @@ event CloseWeaponSelectionMenu
event FadeOutWeaponSelectionMenu
{
// slowly hide the whole thing
- Animate HudWeaponSelection FgColor "0 0 0 0" Linear 0.0 1.5
- Animate HudWeaponSelection TextColor "0 0 0 0" Linear 0.0 1.5
- Animate HudWeaponSelection Alpha "0" Linear 0.0 1.5
- Animate HudWeaponSelection SelectionAlpha "0" Linear 0.0 1.5
+ Animate HudWeaponSelection FgColor "0 0 0 0" Linear 0.5 1.0
+ Animate HudWeaponSelection TextColor "0 0 0 0" Linear 0.5 1.0
+ Animate HudWeaponSelection Alpha "0" Linear 0.5 1.0
+ Animate HudWeaponSelection SelectionAlpha "0" Linear 0.5 1.0
+
+ Animate HudWeaponSelection WeaponBoxDist1Alpha "0 0 0 0" Linear 0.0 0.5
+ Animate HudWeaponSelection WeaponBoxDist2Alpha "0 0 0 0" Linear 0.0 0.5
+ Animate HudWeaponSelection WeaponBoxDist3Alpha "0 0 0 0" Linear 0.0 0.5
}
event SuitAuxPowerMax
@@ -116,31 +132,37 @@ event SuitAuxPowerIncreasedAbove25
event SuitAuxPowerNoItemsActive
{
// resize the aux power to be the smallest size
- Animate HudSuitPower Size "102 26" Linear 0.0 0.4
- Animate HudSuitPower Position "16 400" Linear 0.0 0.4
-// Animate HudSuitPower text_xpos "8" Linear 0.0 0.4
-// Animate HudSuitPower text_ypos "15" Linear 0.0 0.4
+ Animate HudSuitPower Size "102 26" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Position "16 400" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Size "112 30" Linear 0.0 0.4 [$DECK]
+ Animate HudSuitPower Position "16 390" Linear 0.0 0.4 [$DECK]
}
event SuitAuxPowerOneItemActive
{
// resize the aux power to fit one item
- Animate HudSuitPower Size "102 36" Linear 0.0 0.4
- Animate HudSuitPower Position "16 390" Linear 0.0 0.4
+ Animate HudSuitPower Size "102 36" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Position "16 390" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Size "112 44" Linear 0.0 0.4 [$DECK]
+ Animate HudSuitPower Position "16 372" Linear 0.0 0.4 [$DECK]
}
event SuitAuxPowerTwoItemsActive
{
// resize the aux power to fit two items
- Animate HudSuitPower Size "102 46" Linear 0.0 0.4
- Animate HudSuitPower Position "16 380" Linear 0.0 0.4
+ Animate HudSuitPower Size "102 46" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Position "16 380" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Size "112 56" Linear 0.0 0.4 [$DECK]
+ Animate HudSuitPower Position "16 364" Linear 0.0 0.4 [$DECK]
}
event SuitAuxPowerThreeItemsActive
{
// resize the aux power to fit three items
- Animate HudSuitPower Size "102 56" Linear 0.0 0.4
- Animate HudSuitPower Position "16 370" Linear 0.0 0.4
+ Animate HudSuitPower Size "102 56" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Position "16 370" Linear 0.0 0.4 [!$DECK]
+ Animate HudSuitPower Size "112 70" Linear 0.0 0.4 [$DECK]
+ Animate HudSuitPower Position "16 350" Linear 0.0 0.4 [$DECK]
}
event SuitFlashlightOn
@@ -231,8 +253,8 @@ event HudPlayerDeath
StopEvent HealthLoop 0.0
StopEvent HealthPulse 0.0
- Animate HudDamageIndicator DmgFullscreenColor "255 0 0 8" Deaccel 0.1 0.2
- Animate HudDamageIndicator DmgFullscreenColor "255 0 0 48" Deaccel 0.3 4.0
+ Animate HudDamageIndicator DmgFullscreenColor "255 0 0 96" Deaccel 0.1 0.2
+ Animate HudDamageIndicator DmgFullscreenColor "255 0 0 255" Deaccel 0.3 4.0
}
event HealthIncreasedAbove20
@@ -501,24 +523,35 @@ event WeaponChanged
}
// ran if we just changed to a weapon that needs clip ammo
-event WeaponUsesClips
+event WeaponUsesClips [!$DECK]
{
Animate HudAmmo Position "r150 432" Deaccel 0.0 0.4
Animate HudAmmo Size "132 36" Deaccel 0.0 0.4
}
+event WeaponUsesClips [$DECK]
+{
+ Animate HudAmmo Position "r162 426" Deaccel 0.0 0.4
+ Animate HudAmmo Size "144 42" Deaccel 0.0 0.4
+}
// ran if we just changed to a weapon that does not use clip ammo
-event WeaponDoesNotUseClips
+event WeaponDoesNotUseClips [!$DECK]
{
Animate HudAmmo Position "r118 432" Deaccel 0.0 0.4
Animate HudAmmo Size "100 36" Deaccel 0.0 0.4
}
+event WeaponDoesNotUseClips [$DECK]
+{
+ Animate HudAmmo Position "r130 426" Deaccel 0.0 0.4
+ Animate HudAmmo Size "120 42" Deaccel 0.0 0.4
+}
event WeaponUsesSecondaryAmmo
{
StopAnimation HudAmmo Position 0.0
StopAnimation HudAmmo Size 0.0
StopPanelAnimations HudAmmoSecondary 0.0
+ //StopPanelAnimations HudAmmo 0.0
Animate HudAmmoSecondary BgColor "250 220 0 60" Linear 0.0 0.1
Animate HudAmmoSecondary BgColor "BgColor" Deaccel 0.1 1.0
@@ -526,8 +559,10 @@ event WeaponUsesSecondaryAmmo
Animate HudAmmoSecondary FgColor "FgColor" Linear 0.2 1.5
Animate HudAmmoSecondary Alpha 255 Linear 0.0 0.1
- Animate HudAmmo Position "r222 432" Deaccel 0.0 0.5
- Animate HudAmmo Size "132 36" Deaccel 0.0 0.4
+ Animate HudAmmo Position "r222 432" Deaccel 0.0 0.5 [!$DECK]
+ Animate HudAmmo Size "132 36" Deaccel 0.0 0.4 [!$DECK]
+ Animate HudAmmo Position "r234 426" Deaccel 0.0 0.5 [$DECK]
+ Animate HudAmmo Size "144 42" Deaccel 0.0 0.4 [$DECK]
}
event WeaponDoesNotUseSecondaryAmmo
@@ -548,25 +583,54 @@ event CraneMagnetFlash
event HintMessageShow
{
- // show the hints
- Animate HudHintDisplay Alpha 255 Linear 0.0 0.5
+ StopPanelAnimations HudHintDisplay 0.0
+
+ Animate HudHintDisplay HintSize "1" Deaccel 0.0 0.3
+ Animate HudHintDisplay FgColor "FgColor" Linear 0.4 0.4
// flash text
- Animate HudHintDisplay FgColor "FgColor" Linear 0.0 0.01
- Animate HudHintDisplay FgColor "255 220 0 255" Linear 0.5 0.2
- Animate HudHintDisplay FgColor "FgColor" Linear 0.7 0.2
- Animate HudHintDisplay FgColor "255 220 0 255" Linear 1.5 0.2
- Animate HudHintDisplay FgColor "FgColor" Linear 1.7 0.2
+ Animate HudHintDisplay FgColor "FgColor" Linear 1.5 0.01
+ Animate HudHintDisplay FgColor "255 220 0 255" Linear 2.0 0.2
+ Animate HudHintDisplay FgColor "FgColor" Linear 2.2 0.2
+ Animate HudHintDisplay FgColor "255 220 0 255" Linear 3.0 0.2
+ Animate HudHintDisplay FgColor "FgColor" Linear 3.2 0.2
// hide the panel after a while
- Animate HudHintDisplay Alpha 0 Linear 12.0 1.0
+ Animate HudHintDisplay FgColor "255 220 0 0" Linear 10.0 0.2
+ Animate HudHintDisplay HintSize "0" Deaccel 10.2 0.3
}
+
event HintMessageHide
{
- Animate HudHintDisplay Alpha 0 Linear 0.0 0.5
+ Animate HudHintDisplay FgColor "255 220 0 0" Linear 0.0 0.2
+ Animate HudHintDisplay HintSize "0" Deaccel 0.2 0.3
}
+event KeyHintMessageShow
+{
+ StopPanelAnimations HudHintKeyDisplay 0.0
+
+ // show the hints
+ Animate HudHintKeyDisplay Alpha 255 Linear 0.0 0.5
+
+ // flash text
+ Animate HudHintKeyDisplay FgColor "FgColor" Linear 0.0 0.01
+ Animate HudHintKeyDisplay FgColor "255 220 0 255" Linear 0.5 0.2
+ Animate HudHintKeyDisplay FgColor "FgColor" Linear 0.7 0.2
+ Animate HudHintKeyDisplay FgColor "255 220 0 255" Linear 1.5 0.2
+ Animate HudHintKeyDisplay FgColor "FgColor" Linear 1.7 0.2
+
+ // hide the panel after a while
+ Animate HudHintKeyDisplay Alpha 0 Linear 12.0 1.0
+}
+
+event KeyHintMessageHide
+{
+ Animate HudHintKeyDisplay Alpha 0 Linear 0.0 0.5
+}
+
+
event SquadMemberAdded
{
StopEvent SquadMemberDied 0.0
@@ -638,3 +702,161 @@ event PoisonLoop
{
RunEvent PoisonPulse 0.0
}
+
+// Commentary hud element
+event ShowCommentary
+{
+ StopEvent HideCommentary 0.0
+ Animate HudCommentary Alpha 255 Linear 0.0 0.5
+}
+
+event HideCommentary
+{
+ StopEvent ShowCommentary 0.0
+ Animate HudCommentary Alpha 0 Linear 0.0 0.5
+}
+
+// Voting
+event PulseOption1
+{
+ Animate Option2Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option3Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option4Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option5Background_Selected Alpha 0 Linear 0.0 0.001
+
+ Animate Option1Background_Selected Alpha 255 Linear 0.0 0.001
+ Animate Option1Background_Selected Alpha 128 Linear 0.5 1.5
+
+ Animate YesLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate YesIcon Alpha 0 Linear 1.25 1.7
+ Animate YesRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate NoLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate NoIcon Alpha 0 Linear 1.25 1.7
+ Animate NoRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate LabelOption2 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption3 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption4 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption5 Alpha 60 Linear 1.25 1.7
+}
+
+event PulseOption2
+{
+ Animate Option1Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option3Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option4Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option5Background_Selected Alpha 0 Linear 0.0 0.001
+
+ Animate Option2Background_Selected Alpha 255 Linear 0.0 0.001
+ Animate Option2Background_Selected Alpha 128 Linear 0.5 1.5
+
+ Animate YesLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate YesIcon Alpha 0 Linear 1.25 1.7
+ Animate YesRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate NoLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate NoIcon Alpha 0 Linear 1.25 1.7
+ Animate NoRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate LabelOption1 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption3 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption4 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption5 Alpha 60 Linear 1.25 1.7
+}
+
+event PulseOption3
+{
+ Animate Option1Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option2Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option4Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option5Background_Selected Alpha 0 Linear 0.0 0.001
+
+ Animate Option3Background_Selected Alpha 255 Linear 0.0 0.001
+ Animate Option3Background_Selected Alpha 128 Linear 0.5 1.5
+
+ Animate YesLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate YesIcon Alpha 0 Linear 1.25 1.7
+ Animate YesRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate NoLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate NoIcon Alpha 0 Linear 1.25 1.7
+ Animate NoRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate LabelOption1 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption2 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption4 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption5 Alpha 60 Linear 1.25 1.7
+}
+
+event PulseOption4
+{
+ Animate Option1Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option2Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option3Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option5Background_Selected Alpha 0 Linear 0.0 0.001
+
+ Animate Option4Background_Selected Alpha 255 Linear 0.0 0.001
+ Animate Option4Background_Selected Alpha 128 Linear 0.5 1.5
+
+ Animate YesLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate YesIcon Alpha 0 Linear 1.25 1.7
+ Animate YesRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate NoLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate NoIcon Alpha 0 Linear 1.25 1.7
+ Animate NoRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate LabelOption1 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption2 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption3 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption5 Alpha 60 Linear 1.25 1.7
+}
+
+event PulseOption5
+{
+ Animate Option1Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option2Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option3Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option4Background_Selected Alpha 0 Linear 0.0 0.001
+
+ Animate Option5Background_Selected Alpha 255 Linear 0.0 0.001
+ Animate Option5Background_Selected Alpha 128 Linear 0.5 1.5
+
+ Animate YesLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate YesIcon Alpha 0 Linear 1.25 1.7
+ Animate YesRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate NoLeftLabel Alpha 0 Linear 1.25 1.7
+ Animate NoIcon Alpha 0 Linear 1.25 1.7
+ Animate NoRightLabel Alpha 0 Linear 1.25 1.7
+
+ Animate LabelOption1 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption2 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption3 Alpha 60 Linear 1.25 1.7
+ Animate LabelOption4 Alpha 60 Linear 1.25 1.7
+}
+
+event HideVoteBackgrounds
+{
+ Animate Option1Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option2Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option3Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option4Background_Selected Alpha 0 Linear 0.0 0.001
+ Animate Option5Background_Selected Alpha 0 Linear 0.0 0.001
+
+ Animate YesLeftLabel Alpha 255 Linear 0.0 0.001
+ Animate YesIcon Alpha 255 Linear 0.0 0.001
+ Animate YesRightLabel Alpha 255 Linear 0.0 0.001
+
+ Animate NoLeftLabel Alpha 255 Linear 0.0 0.001
+ Animate NoIcon Alpha 255 Linear 0.0 0.001
+ Animate NoRightLabel Alpha 255 Linear 0.0 0.001
+
+ Animate LabelOption1 Alpha 255 Linear 0.0 0.001
+ Animate LabelOption2 Alpha 255 Linear 0.0 0.001
+ Animate LabelOption3 Alpha 255 Linear 0.0 0.001
+ Animate LabelOption4 Alpha 255 Linear 0.0 0.001
+ Animate LabelOption5 Alpha 255 Linear 0.0 0.001
+}
+
diff --git a/game/mod_hl2mp/scripts/HudLayout.res b/game/mod_hl2mp/scripts/HudLayout.res
index 51945e1b..e8dee15f 100644
--- a/game/mod_hl2mp/scripts/HudLayout.res
+++ b/game/mod_hl2mp/scripts/HudLayout.res
@@ -1,6 +1,6 @@
"Resource/HudLayout.res"
{
- HudHealth
+ HudHealth [!$DECK]
{
"fieldName" "HudHealth"
"xpos" "16"
@@ -17,6 +17,23 @@
"digit_xpos" "50"
"digit_ypos" "2"
}
+ HudHealth [$DECK]
+ {
+ "fieldName" "HudHealth"
+ "xpos" "16"
+ "ypos" "426"
+ "wide" "130"
+ "tall" "42"
+ "visible" "1"
+ "enabled" "1"
+
+ "PaintBackgroundType" "2"
+
+ "text_xpos" "8"
+ "text_ypos" "23"
+ "digit_xpos" "66"
+ "digit_ypos" "0"
+ }
TargetID
{
@@ -33,7 +50,8 @@
"visible" "0"
"enabled" "1"
"xpos" "16"
- "ypos" "415"
+ "ypos" "410" [!$DECK]
+ "ypos" "400" [$DECK]
"wide" "200"
"tall" "60"
"text_xpos" "8"
@@ -80,7 +98,7 @@
"text_xpos" "33"
}
- HudSuit
+ HudSuit [!$DECK]
{
"fieldName" "HudSuit"
"xpos" "140"
@@ -92,14 +110,31 @@
"PaintBackgroundType" "2"
-
"text_xpos" "8"
"text_ypos" "20"
"digit_xpos" "50"
"digit_ypos" "2"
}
+ HudSuit [$DECK]
+ {
+ "fieldName" "HudSuit"
+ "xpos" "150"
+ "ypos" "426"
+ "wide" "120"
+ "tall" "42"
+ "visible" "1"
+ "enabled" "1"
- HudAmmo
+ "PaintBackgroundType" "2"
+
+ "text_xpos" "8"
+ "text_ypos" "23"
+ "digit_xpos" "56"
+ "digit_ypos" "0"
+ }
+
+
+ HudAmmo [!$DECK]
{
"fieldName" "HudAmmo"
"xpos" "r150"
@@ -118,8 +153,27 @@
"digit2_xpos" "98"
"digit2_ypos" "16"
}
+ HudAmmo [$DECK]
+ {
+ "fieldName" "HudAmmo"
+ "xpos" "r150"
+ "ypos" "426"
+ "wide" "152"
+ "tall" "42"
+ "visible" "1"
+ "enabled" "1"
- HudAmmoSecondary
+ "PaintBackgroundType" "2"
+
+ "text_xpos" "8"
+ "text_ypos" "24"
+ "digit_xpos" "55"
+ "digit_ypos" "0"
+ "digit2_xpos" "100"
+ "digit2_ypos" "12"
+ }
+
+ HudAmmoSecondary [!$DECK]
{
"fieldName" "HudAmmoSecondary"
"xpos" "r76"
@@ -131,11 +185,30 @@
"PaintBackgroundType" "2"
- "digit_xpos" "10"
+ "text_xpos" "8"
+ "text_ypos" "22"
+ "digit_xpos" "36"
"digit_ypos" "2"
}
+ HudAmmoSecondary [$DECK]
+ {
+ "fieldName" "HudAmmoSecondary"
+ "xpos" "r82"
+ "ypos" "426"
+ "wide" "70"
+ "tall" "42"
+ "visible" "1"
+ "enabled" "1"
+
+ "PaintBackgroundType" "2"
+
+ "text_xpos" "8"
+ "text_ypos" "24"
+ "digit_xpos" "42"
+ "digit_ypos" "0"
+ }
- HudSuitPower
+ HudSuitPower [!$DECK]
{
"fieldName" "HudSuitPower"
"visible" "1"
@@ -164,24 +237,97 @@
"PaintBackgroundType" "2"
}
+
+ HudSuitPower [$DECK]
+ {
+ "fieldName" "HudSuitPower"
+ "visible" "1"
+ "enabled" "1"
+ "xpos" "16"
+ "ypos" "386"
+ "wide" "112"
+ "tall" "54"
+
+ "AuxPowerLowColor" "255 0 0 220"
+ "AuxPowerHighColor" "255 220 0 220"
+ "AuxPowerDisabledAlpha" "70"
+
+ "BarInsetX" "8"
+ "BarInsetY" "18"
+ "BarWidth" "102"
+ "BarHeight" "5"
+ "BarChunkWidth" "6"
+ "BarChunkGap" "3"
+
+ "text_xpos" "8"
+ "text_ypos" "4"
+ "text2_xpos" "8"
+ "text2_ypos" "26"
+ "text2_gap" "14"
+
+ "PaintBackgroundType" "2"
+ }
+
+ HudPosture [$WIN32]
+ {
+ "fieldName" "HudPosture"
+ "visible" "1"
+ "PaintBackgroundType" "2"
+ "xpos" "16"
+ "ypos" "316"
+ "tall" "35"
+ "wide" "36"
+ "font" "WeaponIconsSmall"
+ "icon_xpos" "8"
+ "icon_ypos" "-2"
+ }
+ HudPosture [$X360]
+ {
+ "fieldName" "HudPosture"
+ "visible" "1"
+ "PaintBackgroundType" "2"
+ "xpos" "48"
+ "ypos" "316"
+ "tall" "36"
+ "wide" "36"
+ "font" "WeaponIconsSmall"
+ "icon_xpos" "10"
+ "icon_ypos" "2"
+ }
HudFlashlight
{
"fieldName" "HudFlashlight"
- "visible" "0"
- "enabled" "1"
- "xpos" "16"
- "ypos" "370"
- "wide" "102"
- "tall" "20"
-
- "text_xpos" "8"
- "text_ypos" "6"
- "TextColor" "255 170 0 220"
-
+ "visible" "1"
"PaintBackgroundType" "2"
+ "xpos" "270" [$WIN32]
+ "ypos" "444" [!$DECK]
+ "ypos" "436" [$DECK]
+ "xpos_hidef" "306" [$X360] // aligned to left
+ "xpos_lodef" "c-18" [$X360] // centered in screen
+ "ypos" "428" [$X360]
+ "tall" "24" [!$DECK]
+ "tall" "30" [$DECK]
+ "wide" "36" [!$DECK]
+ "wide" "46" [$DECK]
+ "font" "WeaponIconsSmall" [!$DECK]
+ "font" "FlashlightDeck" [$DECK]
+
+ "icon_xpos" "4"
+ "icon_ypos" "-8" [!$DECK]
+ "icon_ypos" "-12" [$DECK]
+
+ "BarInsetX" "4"
+ "BarInsetY" "18" [!$DECK]
+ "BarInsetY" "22" [$DECK]
+ "BarWidth" "28" [!$DECK]
+ "BarWidth" "36" [$DECK]
+ "BarHeight" "2" [!$DECK]
+ "BarChunkWidth" "2" [!$DECK]
+ "BarHeight" "3" [$DECK]
+ "BarChunkWidth" "3" [$DECK]
+ "BarChunkGap" "1"
}
-
HudDamageIndicator
{
"fieldName" "HudDamageIndicator"
@@ -205,19 +351,26 @@
"Circle1Radius" "66"
"Circle2Radius" "74"
"DashGap" "16"
- "DashHeight" "4"
+ "DashHeight" "4" [$WIN32]
+ "DashHeight" "6" [$X360]
"BorderThickness" "88"
}
-
HudWeaponSelection
{
"fieldName" "HudWeaponSelection"
- "ypos" "16"
+ "ypos" "16" [$WIN32]
+ "ypos" "32" [$X360]
"visible" "1"
"enabled" "1"
"SmallBoxSize" "32"
+ "MediumBoxWide" "95"
+ "MediumBoxWide_hidef" "78"
+ "MediumBoxTall" "50"
+ "MediumBoxTall_hidef" "50"
+ "MediumBoxWide_lodef" "74"
+ "MediumBoxTall_lodef" "50"
"LargeBoxWide" "112"
- "LargeBoxTall" "80"
+ "LargeBoxTall" "84"
"BoxGap" "8"
"SelectionNumberXPos" "4"
"SelectionNumberYPos" "4"
@@ -239,16 +392,8 @@
"fieldName" "HudDeathNotice"
"visible" "1"
"enabled" "1"
- "xpos" "r640"
- "ypos" "12"
- "wide" "628"
- "tall" "468"
-
- "MaxDeathNotices" "4"
- "LineHeight" "22"
- "RightJustify" "1" // If 1, draw notices from the right
-
- "TextFont" "Default"
+ "wide" "640"
+ "tall" "480"
}
HudVehicle
@@ -311,9 +456,11 @@
"visible" "1"
"enabled" "1"
"xpos" "c-250"
- "ypos" "276"
+ "ypos" "276" [$WIN32]
+ "ypos" "236" [$X360]
"wide" "500"
- "tall" "136"
+ "tall" "136" [$WIN32]
+ "tall" "176" [$X360]
"BgAlpha" "128"
@@ -321,21 +468,36 @@
"ItemHiddenTime" "0.2" // Nearly same as grow time so that the item doesn't start to show until growth is finished
"ItemFadeInTime" "0.15" // Once ItemHiddenTime is finished, takes this much longer to fade in
"ItemFadeOutTime" "0.3"
-
+ "topoffset" "0" [$WIN32]
+ "topoffset" "0" [$X360]
}
- HudHistoryResource
+ HudChat
+ {
+ "fieldName" "HudChat"
+ "visible" "0"
+ "enabled" "1"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "4"
+ "tall" "4"
+ }
+
+ HudHistoryResource [$WIN32]
{
"fieldName" "HudHistoryResource"
"visible" "1"
"enabled" "1"
- "xpos" "r252"
+ "xpos" "r272" [$DECK]
+ "xpos" "r252" [!$DECK]
"ypos" "40"
"wide" "248"
"tall" "320"
- "history_gap" "56"
- "icon_inset" "28"
+ "history_gap" "64" [$DECK]
+ "history_gap" "56" [!$DECK]
+ "icon_inset" "38"
+ "text_inset" "36"
"text_inset" "26"
"NumberFont" "HudNumbersSmall"
}
@@ -380,19 +542,40 @@
"fieldName" "HudPredictionDump"
"visible" "1"
"enabled" "1"
- "wide" "640"
- "tall" "480"
+ "wide" "3840"
+ "tall" "1080"
}
HudHintDisplay
{
- "fieldName" "HudHintDisplay"
+ "fieldName" "HudHintDisplay"
+ "visible" "0"
+ "enabled" "1"
+ "xpos" "c-240"
+ "ypos" "c60"
+ "xpos" "r148" [$X360]
+ "ypos" "r338" [$X360]
+ "wide" "480"
+ "tall" "100"
+ "HintSize" "1"
+ "text_xpos" "8"
+ "text_ypos" "8"
+ "center_x" "0" // center text horizontally
+ "center_y" "-1" // align text on the bottom
+ "paintbackground" "0"
+ }
+
+ HudHintKeyDisplay
+ {
+ "fieldName" "HudHintKeyDisplay"
"visible" "0"
- "enabled" "1"
- "xpos" "r120"
- "ypos" "r340"
- "wide" "100"
- "tall" "200"
+ "enabled" "1"
+ "xpos" "r120" [$WIN32]
+ "ypos" "r340" [$WIN32]
+ "xpos" "r148" [$X360]
+ "ypos" "r338" [$X360]
+ "wide" "100"
+ "tall" "200"
"text_xpos" "8"
"text_ypos" "8"
"text_xgap" "8"
@@ -402,7 +585,8 @@
"PaintBackgroundType" "2"
}
- HudSquadStatus
+
+ HudSquadStatus [!$DECK]
{
"fieldName" "HudSquadStatus"
"visible" "1"
@@ -420,14 +604,33 @@
"PaintBackgroundType" "2"
}
+ HudSquadStatus [$DECK]
+ {
+ "fieldName" "HudSquadStatus"
+ "visible" "1"
+ "enabled" "1"
+ "xpos" "r160"
+ "ypos" "372"
+ "wide" "144"
+ "tall" "46"
+ "text_xpos" "8"
+ "text_ypos" "28"
+ "SquadIconColor" "255 220 0 160"
+ "IconInsetX" "8"
+ "IconInsetY" "-10"
+ "IconGap" "39"
- HudPoisonDamageIndicator
+ "PaintBackgroundType" "2"
+ }
+
+
+ HudPoisonDamageIndicator [!$DECK]
{
"fieldName" "HudPoisonDamageIndicator"
"visible" "0"
"enabled" "1"
"xpos" "16"
- "ypos" "346"
+ "ypos" "338"
"wide" "136"
"tall" "38"
"text_xpos" "8"
@@ -436,6 +639,21 @@
"TextColor" "255 170 0 220"
"PaintBackgroundType" "2"
}
+ HudPoisonDamageIndicator [$DECK]
+ {
+ "fieldName" "HudPoisonDamageIndicator"
+ "visible" "0"
+ "enabled" "1"
+ "xpos" "16"
+ "ypos" "262"
+ "wide" "190"
+ "tall" "42"
+ "text_xpos" "8"
+ "text_ypos" "8"
+ "text_ygap" "14"
+ "TextColor" "255 170 0 220"
+ "PaintBackgroundType" "2"
+ }
HudCredits
{
"fieldName" "HudCredits"
@@ -448,58 +666,93 @@
"TextColor" "255 255 255 192"
}
- "HudChat"
- {
- "ControlName" "EditablePanel"
- "fieldName" "HudChat"
- "visible" "1"
- "enabled" "1"
- "xpos" "10"
- "ypos" "275"
- "wide" "320"
- "tall" "120"
- "PaintBackgroundType" "2"
- }
-
- AchievementNotificationPanel
- {
- "fieldName" "AchievementNotificationPanel"
- "visible" "0"
- "enabled" "0"
- }
-
- HudHintKeyDisplay
- {
- "fieldName" "HudHintKeyDisplay"
- "visible" "0"
- "enabled" "0"
- }
HUDAutoAim
{
- "fieldName" "HUDAutoAim"
- "visible" "0"
- "enabled" "0"
- }
+ "fieldName" "HUDAutoAim"
+ "visible" "1"
+ "enabled" "1"
+ "wide" "640" [$WIN32]
+ "tall" "480" [$WIN32]
+ "wide" "960" [$X360]
+ "tall" "720" [$X360]
+ }
+
+ HudCommentary
+ {
+ "fieldName" "HudCommentary"
+ "xpos" "c-190"
+ "ypos" "350"
+ "wide" "380"
+ "tall" "40"
+ "visible" "1"
+ "enabled" "1"
+
+ "PaintBackgroundType" "2"
+
+ "bar_xpos" "50"
+ "bar_ypos" "20"
+ "bar_height" "8"
+ "bar_width" "320"
+ "speaker_xpos" "50"
+ "speaker_ypos" "8"
+ "count_xpos_from_right" "10" // Counts from the right side
+ "count_ypos" "8"
+
+ "icon_texture" "vgui/hud/icon_commentary"
+ "icon_xpos" "0"
+ "icon_ypos" "0"
+ "icon_width" "40"
+ "icon_height" "40"
+ }
HudHDRDemo
{
- "fieldName" "HudHDRDemo"
- "visible" "0"
- "enabled" "0"
+ "fieldName" "HudHDRDemo"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "640"
+ "tall" "480"
+ "visible" "1"
+ "enabled" "1"
+
+ "Alpha" "255"
+ "PaintBackgroundType" "2"
+
+ "BorderColor" "0 0 0 255"
+ "BorderLeft" "16"
+ "BorderRight" "16"
+ "BorderTop" "16"
+ "BorderBottom" "64"
+ "BorderCenter" "0"
+
+ "TextColor" "255 255 255 255"
+ "LeftTitleY" "422"
+ "RightTitleY" "422"
}
-
- HudCommentary
+
+ AchievementNotificationPanel
{
- "fieldName" "HudCommentary"
- "visible" "0"
- "enabled" "0"
+ "fieldName" "AchievementNotificationPanel"
+ "visible" "1"
+ "enabled" "1"
+ "xpos" "0"
+ "ypos" "180"
+ "wide" "f10" [$WIN32]
+ "wide" "f60" [$X360]
+ "tall" "100"
}
-
- "CHudVote"
+
+ CHudVote
{
"fieldName" "CHudVote"
- "visible" "0"
- "enabled" "0"
- }
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "640"
+ "tall" "480"
+ "visible" "1"
+ "enabled" "1"
+ "bgcolor_override" "0 0 0 0"
+ "PaintBackgroundType" "0" // rounded corners
+ }
}
\ No newline at end of file
diff --git a/game/mod_hl2mp/scripts/game_sounds_weapons.txt b/game/mod_hl2mp/scripts/game_sounds_weapons.txt
index d7bc90f6..de933b66 100644
--- a/game/mod_hl2mp/scripts/game_sounds_weapons.txt
+++ b/game/mod_hl2mp/scripts/game_sounds_weapons.txt
@@ -449,7 +449,7 @@
"Weapon_PhysCannon.Launch"
{
"channel" "CHAN_WEAPON"
- "volume" "0.57"
+ "volume" "0.27"
"soundlevel" "SNDLVL_GUNFIRE"
"pitch" "110,120"
@@ -471,17 +471,17 @@
"rndwave"
{
- "wave" "weapons/physcannon/superphys_launch1.wav"
- "wave" "weapons/physcannon/superphys_launch2.wav"
- "wave" "weapons/physcannon/superphys_launch3.wav"
- "wave" "weapons/physcannon/superphys_launch4.wav"
+ "wave" ")weapons/physcannon/superphys_launch1.wav"
+ "wave" ")weapons/physcannon/superphys_launch2.wav"
+ "wave" ")weapons/physcannon/superphys_launch3.wav"
+ "wave" ")weapons/physcannon/superphys_launch4.wav"
}
}
"Weapon_PhysCannon.Charge"
{
"channel" "CHAN_ITEM"
- "volume" "0.42"
+ "volume" "0.22"
"soundlevel" "SNDLVL_NORM"
"wave" ")weapons/physcannon/physcannon_charge.wav"
}
@@ -493,13 +493,13 @@
"soundlevel" "SNDLVL_NORM"
"pitch" "70,80"
- "wave" "weapons/physcannon/physcannon_charge.wav"
+ "wave" ")weapons/physcannon/physcannon_charge.wav"
}
"Weapon_PhysCannon.DryFire"
{
"channel" "CHAN_WEAPON"
- "volume" "0.42"
+ "volume" "0.22"
"soundlevel" "SNDLVL_NORM"
"wave" ")weapons/physcannon/physcannon_dryfire.wav"
@@ -512,13 +512,13 @@
"soundlevel" "SNDLVL_NORM"
"pitch" "70,80"
- "wave" "weapons/physcannon/physcannon_dryfire.wav"
+ "wave" ")weapons/physcannon/physcannon_dryfire.wav"
}
"Weapon_PhysCannon.Pickup"
{
"channel" "CHAN_WEAPON"
- "volume" "0.42"
+ "volume" "0.22"
"soundlevel" "SNDLVL_105dB"
"wave" ")weapons/physcannon/physcannon_pickup.wav"
@@ -531,13 +531,13 @@
"soundlevel" "SNDLVL_105dB"
"pitch" "70,80"
- "wave" "weapons/physcannon/physcannon_pickup.wav"
+ "wave" ")weapons/physcannon/physcannon_pickup.wav"
}
"Weapon_PhysCannon.OpenClaws"
{
"channel" "CHAN_VOICE"
- "volume" "0.42"
+ "volume" "0.2"
"soundlevel" "SNDLVL_NORM"
"wave" ")weapons/physcannon/physcannon_claws_open.wav"
@@ -546,7 +546,7 @@
"Weapon_PhysCannon.CloseClaws"
{
"channel" "CHAN_VOICE"
- "volume" "0.42"
+ "volume" "0.2"
"soundlevel" "SNDLVL_NORM"
"wave" ")weapons/physcannon/physcannon_claws_close.wav"
@@ -555,7 +555,7 @@
"Weapon_PhysCannon.Drop"
{
"channel" "CHAN_WEAPON"
- "volume" "0.42"
+ "volume" "0.22"
"soundlevel" "SNDLVL_105dB"
"wave" ")weapons/physcannon/physcannon_drop.wav"
@@ -568,13 +568,13 @@
"soundlevel" "SNDLVL_105dB"
"pitch" "50,60"
- "wave" "weapons/physcannon/physcannon_drop.wav"
+ "wave" ")weapons/physcannon/physcannon_drop.wav"
}
"Weapon_PhysCannon.HoldSound"
{
"channel" "CHAN_STATIC"
- "volume" "1.0"
+ "volume" "0.4"
"soundlevel" "SNDLVL_NORM"
"wave" "weapons/physcannon/hold_loop.wav"
@@ -599,21 +599,21 @@
"rndwave"
{
- "wave" "weapons/physcannon/superphys_small_zap1.wav"
- "wave" "weapons/physcannon/superphys_small_zap2.wav"
- "wave" "weapons/physcannon/superphys_small_zap3.wav"
- "wave" "weapons/physcannon/superphys_small_zap4.wav"
+ "wave" ")weapons/physcannon/superphys_small_zap1.wav"
+ "wave" ")weapons/physcannon/superphys_small_zap2.wav"
+ "wave" ")weapons/physcannon/superphys_small_zap3.wav"
+ "wave" ")weapons/physcannon/superphys_small_zap4.wav"
}
}
"Weapon_PhysCannon.TooHeavy"
{
"channel" "CHAN_WEAPON"
- "volume" "0.8"
+ "volume" "0.4"
"soundlevel" "SNDLVL_NORM"
"pitch" "100"
- "wave" "weapons/physcannon/physcannon_tooheavy.wav"
+ "wave" ")weapons/physcannon/physcannon_tooheavy.wav"
}
// weapon_physgun.txt
diff --git a/game/mod_hl2mp/scripts/weapon_357.txt b/game/mod_hl2mp/scripts/weapon_357.txt
index 23ff8633..cf65f0c7 100644
--- a/game/mod_hl2mp/scripts/weapon_357.txt
+++ b/game/mod_hl2mp/scripts/weapon_357.txt
@@ -40,9 +40,14 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "e"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "e"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "q"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_ar2.txt b/game/mod_hl2mp/scripts/weapon_ar2.txt
index 13b6a594..cd4c99cd 100644
--- a/game/mod_hl2mp/scripts/weapon_ar2.txt
+++ b/game/mod_hl2mp/scripts/weapon_ar2.txt
@@ -51,14 +51,19 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "l"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "l"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "u"
}
"ammo2"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "z"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_crossbow.txt b/game/mod_hl2mp/scripts/weapon_crossbow.txt
index 59b49b40..02db4de7 100644
--- a/game/mod_hl2mp/scripts/weapon_crossbow.txt
+++ b/game/mod_hl2mp/scripts/weapon_crossbow.txt
@@ -42,9 +42,14 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "g"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "g"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmallSecondary"
"character" "w"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_crowbar.txt b/game/mod_hl2mp/scripts/weapon_crowbar.txt
index 0ad97ddc..77d6bac5 100644
--- a/game/mod_hl2mp/scripts/weapon_crowbar.txt
+++ b/game/mod_hl2mp/scripts/weapon_crowbar.txt
@@ -43,26 +43,21 @@ WeaponData
"font" "WeaponIcons"
"character" "c"
}
- "ammo2"
- {
- "file" "sprites/640hud7"
- "x" "48"
- "y" "72"
- "width" "24"
- "height" "24"
- }
"crosshair"
{
- "font" "Crosshairs"
- "character" "Q"
+ "file" "sprites/crosshairs"
+ "x" "0"
+ "y" "48"
+ "width" "24"
+ "height" "24"
}
"autoaim"
{
- "file" "sprites/crosshairs"
- "x" "0"
- "y" "48"
- "width" "24"
- "height" "24"
+ "file" "sprites/crosshairs"
+ "x" "48"
+ "y" "72"
+ "width" "24"
+ "height" "24"
}
}
}
\ No newline at end of file
diff --git a/game/mod_hl2mp/scripts/weapon_frag.txt b/game/mod_hl2mp/scripts/weapon_frag.txt
index 635e885e..25cecc4d 100644
--- a/game/mod_hl2mp/scripts/weapon_frag.txt
+++ b/game/mod_hl2mp/scripts/weapon_frag.txt
@@ -41,9 +41,14 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "k"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "k"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "v"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_physcannon.txt b/game/mod_hl2mp/scripts/weapon_physcannon.txt
index 84c4f246..2c0f68fd 100644
--- a/game/mod_hl2mp/scripts/weapon_physcannon.txt
+++ b/game/mod_hl2mp/scripts/weapon_physcannon.txt
@@ -53,14 +53,6 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "m"
}
- "ammo"
- {
- "file" "sprites/a_icons1"
- "x" "0"
- "y" "0"
- "width" "32"
- "height" "32"
- }
"crosshair"
{
"font" "Crosshairs"
diff --git a/game/mod_hl2mp/scripts/weapon_pistol.txt b/game/mod_hl2mp/scripts/weapon_pistol.txt
index a6086bc1..52e4fd70 100644
--- a/game/mod_hl2mp/scripts/weapon_pistol.txt
+++ b/game/mod_hl2mp/scripts/weapon_pistol.txt
@@ -45,9 +45,14 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "d"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "d"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "p"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_rpg.txt b/game/mod_hl2mp/scripts/weapon_rpg.txt
index ced06d0d..3f7dbfb3 100644
--- a/game/mod_hl2mp/scripts/weapon_rpg.txt
+++ b/game/mod_hl2mp/scripts/weapon_rpg.txt
@@ -48,9 +48,14 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "i"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "i"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmallSecondary"
"character" "x"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_shotgun.txt b/game/mod_hl2mp/scripts/weapon_shotgun.txt
index bb632d54..0b7f7e91 100644
--- a/game/mod_hl2mp/scripts/weapon_shotgun.txt
+++ b/game/mod_hl2mp/scripts/weapon_shotgun.txt
@@ -45,9 +45,14 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "b"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "b"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "s"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_slam.txt b/game/mod_hl2mp/scripts/weapon_slam.txt
index 0877c1d5..d9631151 100644
--- a/game/mod_hl2mp/scripts/weapon_slam.txt
+++ b/game/mod_hl2mp/scripts/weapon_slam.txt
@@ -31,6 +31,11 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "o"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "o"
+ }
"ammo"
{
"font" "WeaponIcons"
diff --git a/game/mod_hl2mp/scripts/weapon_smg1.txt b/game/mod_hl2mp/scripts/weapon_smg1.txt
index 331d1823..e5695ea7 100644
--- a/game/mod_hl2mp/scripts/weapon_smg1.txt
+++ b/game/mod_hl2mp/scripts/weapon_smg1.txt
@@ -50,14 +50,19 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "a"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "a"
+ }
"ammo"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmall"
"character" "r"
}
"ammo2"
{
- "font" "WeaponIcons"
+ "font" "WeaponIconsSmallSecondary"
"character" "t"
}
"crosshair"
diff --git a/game/mod_hl2mp/scripts/weapon_stunstick.txt b/game/mod_hl2mp/scripts/weapon_stunstick.txt
index ab114a18..f9b57f11 100644
--- a/game/mod_hl2mp/scripts/weapon_stunstick.txt
+++ b/game/mod_hl2mp/scripts/weapon_stunstick.txt
@@ -40,6 +40,11 @@ WeaponData
"font" "WeaponIconsSelected"
"character" "n"
}
+ "weapon_small"
+ {
+ "font" "WeaponIconsSmall"
+ "character" "n"
+ }
"ammo"
{
"font" "WeaponIcons"
@@ -55,19 +60,16 @@ WeaponData
}
"crosshair"
{
- "file" "sprites/crosshairs"
- "x" "0"
- "y" "48"
- "width" "24"
- "height" "24"
+ "font" "Crosshairs"
+ "character" "Q"
}
"autoaim"
{
- "file" "sprites/crosshairs"
- "x" "48"
- "y" "72"
- "width" "24"
- "height" "24"
+ "file" "sprites/crosshairs"
+ "x" "0"
+ "y" "48"
+ "width" "24"
+ "height" "24"
}
}
}
\ No newline at end of file
diff --git a/game/mod_hl2mp/steam.inf b/game/mod_hl2mp/steam.inf
new file mode 100644
index 00000000..3e5da25a
--- /dev/null
+++ b/game/mod_hl2mp/steam.inf
@@ -0,0 +1,6 @@
+PatchVersion=2000
+ClientVersion=2000
+ServerVersion=2000
+ProductName=mod_hl2mp
+appID=243750
+ServerAppID=244310
diff --git a/game/mod_tf/gameinfo.txt b/game/mod_tf/gameinfo.txt
new file mode 100644
index 00000000..40b8994d
--- /dev/null
+++ b/game/mod_tf/gameinfo.txt
@@ -0,0 +1,81 @@
+"GameInfo"
+{
+ game "Frog Fortress 2"
+ type multiplayer_only
+ nomodels 1
+ nohimodel 1
+ nocrosshair 0
+ hidden_maps
+ {
+ "test_speakers" 1
+ "test_hardware" 1
+ }
+ nodegraph 0
+ GameData "tf.fgd"
+ AdditionalLocalization "tf"
+ InstancePath "maps/instances/"
+ advcrosshair 1
+ supportsvr 0
+ ReplayRequired 1
+
+ DependsOnAppID 440
+
+ FileSystem
+ {
+ SteamAppId 243750
+
+ SearchPaths
+ {
+ // First, mount all user customizations. This will search for VPKs and subfolders
+ // and mount them in alphabetical order. The easiest way to distribute a mod is to
+ // pack up the custom content into a VPK. To "install" a mod, just drop it in this
+ // folder.
+ //
+ // Note that this folder is scanned only when the game is booted.
+ game+mod mod_tf/custom/*
+ // Enable this if you want to load your TF custom content.
+ //game+mod |appid_440|tf/custom/*
+
+ // Now search loose files. We'll set the directory containing the gameinfo.txt file
+ // as the first "mod" search path (after any user customizations). This is also the one
+ // that's used when writing to the "mod" path.
+ mod+mod_write |gameinfo_path|.
+ game+game_write |gameinfo_path|.
+ default_write_path |gameinfo_path|.
+ gamebin |gameinfo_path|bin
+
+ // We search VPK files before ordinary folders, because most files will be found in
+ // VPK and we can avoid making thousands of file system calls to attempt to open files
+ // in folders where they don't exist. (Searching a VPK is much faster than making an operating
+ // system call.)
+ game_lv |appid_440|tf/tf2_lv.vpk
+ game+mod |appid_440|tf/tf2_textures.vpk
+ game+mod |appid_440|tf/tf2_sound_vo_english.vpk
+ game+mod |appid_440|tf/tf2_sound_misc.vpk
+ game+mod+vgui |appid_440|tf/tf2_misc.vpk
+ game |appid_243750|hl2/hl2_textures.vpk
+ game |appid_243750|hl2/hl2_sound_vo_english.vpk
+ game |appid_243750|hl2/hl2_sound_misc.vpk
+ game+vgui |appid_243750|hl2/hl2_misc.vpk
+ platform+vgui |appid_243750|platform/platform_misc.vpk
+
+ // Last, mount in shared HL2 and TF2 loose files
+ game |appid_440|tf
+ game |appid_243750|hl2
+ platform |appid_243750|platform
+
+ // Random files downloaded from gameservers go into a seperate directory, so
+ // that it's easy to keep those files segregated from the official game files
+ // or customizations intentially installed by the user.
+ //
+ // This directory is searched LAST. If you visit a server and download
+ // a custom model, etc, we don't want that file to override the default
+ // game file indefinitely (after you have left the server). Servers CAN have
+ // custom content that overrides the default game files, it just needs to be
+ // packed up in the .bsp file so that it will be mounted as a map search pack.
+ // The map search pack is mounted at the top of the search path list,
+ // but only while you are connected that server and on that map.
+ game+download mod_tf/download
+ }
+ }
+}
\ No newline at end of file
diff --git a/game/mod_tf/materials/logo/new_tf2_logo.vmt b/game/mod_tf/materials/logo/new_tf2_logo.vmt
new file mode 100644
index 00000000..c8e8620d
--- /dev/null
+++ b/game/mod_tf/materials/logo/new_tf2_logo.vmt
@@ -0,0 +1,6 @@
+"UnlitGeneric"
+{
+ "$basetexture" "logo\new_tf2_logo"
+ "$translucent" 1
+ "$ignorez" 1
+}
diff --git a/game/mod_tf/materials/logo/new_tf2_logo.vtf b/game/mod_tf/materials/logo/new_tf2_logo.vtf
new file mode 100644
index 00000000..185629e3
Binary files /dev/null and b/game/mod_tf/materials/logo/new_tf2_logo.vtf differ
diff --git a/game/mod_tf/resource/game.ico b/game/mod_tf/resource/game.ico
new file mode 100644
index 00000000..afc2739a
Binary files /dev/null and b/game/mod_tf/resource/game.ico differ
diff --git a/game/mod_tf/resource/mod_tf_english.txt b/game/mod_tf/resource/mod_tf_english.txt
new file mode 100644
index 00000000..edf73c79
Binary files /dev/null and b/game/mod_tf/resource/mod_tf_english.txt differ
diff --git a/game/mod_tf/resource/ui/CharInfoLoadoutSubPanel.res b/game/mod_tf/resource/ui/CharInfoLoadoutSubPanel.res
new file mode 100644
index 00000000..f1ee4252
--- /dev/null
+++ b/game/mod_tf/resource/ui/CharInfoLoadoutSubPanel.res
@@ -0,0 +1,2001 @@
+"Resource/UI/CharInfoLoadoutSubPanel.res"
+{
+ "CharInfoLoadoutSubPanel"
+ {
+ "ControlName" "Frame"
+ "fieldName" "CharInfoLoadoutSubPanel"
+ "xpos" "0"
+ "ypos" "40"
+ "wide" "f0"
+ "tall" "480"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "settitlebarvisible" "0"
+ "PaintBackgroundType" "0"
+ "bgcolor_override" "46 43 42 255"
+ "infocus_bgcolor_override" "46 43 42 255"
+ "outoffocus_bgcolor_override" "46 43 42 255"
+
+ "selectlabely_default" "25"
+ "selectlabely_onchanges" "15"
+
+ "class_ypos" "40"
+ "class_xdelta" "5"
+ "class_wide_min" "60"
+ "class_wide_max" "100"
+ "class_tall_min" "120"
+ "class_tall_max" "200"
+ "class_distance_min" "7"
+ "class_distance_max" "100"
+
+ "itemcountcolor" "200 80 60 255"
+ "itemcountcolor_noitems" "117 107 94 255"
+ }
+
+ "scout"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "scout"
+ "xpos" "c-300"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout scout"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_scout_red"
+ "inactiveimage" "class_sel_sm_scout_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "soldier"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "soldier"
+ "xpos" "c-250"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout soldier"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_soldier_red"
+ "inactiveimage" "class_sel_sm_soldier_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "pyro"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "pyro"
+ "xpos" "c-200"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout pyro"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_pyro_red"
+ "inactiveimage" "class_sel_sm_pyro_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "demoman"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "demoman"
+ "xpos" "c-110"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout demoman"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_demo_red"
+ "inactiveimage" "class_sel_sm_demo_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "heavyweapons"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "heavyweapons"
+ "xpos" "c-60"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout heavy"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_heavy_red"
+ "inactiveimage" "class_sel_sm_heavy_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "engineer"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "engineer"
+ "xpos" "c-10"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout engineer"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_engineer_red"
+ "inactiveimage" "class_sel_sm_engineer_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "medic"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "medic"
+ "xpos" "c78"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout medic"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_medic_red"
+ "inactiveimage" "class_sel_sm_medic_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "sniper"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "sniper"
+ "xpos" "c128"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout sniper"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_sniper_red"
+ "inactiveimage" "class_sel_sm_sniper_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "spy"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "spy"
+ "xpos" "c178"
+ "ypos" "120"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "120"
+ "autoResize" "0"
+ "pinCorner" "2"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "loadout spy"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "class_sel_sm_spy_red"
+ "inactiveimage" "class_sel_sm_spy_inactive"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "ShowBackpackButton"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "ShowBackpackButton"
+ "xpos" "c-90"
+ "ypos" "235"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "60"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "backpack"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "..\hud\backpack_01"
+ "inactiveimage" "..\hud\backpack_01_grey"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "ShowBackpackLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "ShowBackpackLabel"
+ "font" "HudFontSmallestBold"
+ "labelText" "#BackpackTitle"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "5"
+ "zpos" "7"
+ "wide" "120"
+ "tall" "20"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+
+ "pin_to_sibling" "ShowBackpackButton"
+ "pin_corner_to_sibling" "4"
+ "pin_to_sibling_corner" "6"
+ }
+ "ShowArmoryButton"
+ {
+ "ControlName" "ImageButton"
+ "fieldName" "ShowArmoryButton"
+ "xpos" "c30"
+ "ypos" "235"
+ "zpos" "6"
+ "wide" "60"
+ "tall" "60"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "textAlignment" "south-west"
+ "Command" "armory"
+ "Default" "0"
+ "font" "MenuKeys"
+ "scaleImage" "1"
+ "activeimage" "catalog_book"
+ "inactiveimage" "catalog_book_gray"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ "ShowArmoryLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "ShowArmoryLabel"
+ "font" "HudFontSmallestBold"
+ "labelText" "#Armory"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "5"
+ "zpos" "7"
+ "wide" "120"
+ "tall" "20"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+
+ "pin_to_sibling" "ShowArmoryButton"
+ "pin_corner_to_sibling" "4"
+ "pin_to_sibling_corner" "6"
+ }
+
+ "ClassLabel"
+ {
+ "ControlName" "Label"
+ "fieldName" "ClassLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "classname"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "200"
+ "zpos" "1"
+ "wide" "300"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "0"
+ "enabled" "1"
+ }
+ "ItemsLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "ItemsLabel"
+ "font" "HudFontSmall"
+ "labelText" "classname"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "215"
+ "zpos" "1"
+ "wide" "300"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "0"
+ "enabled" "1"
+ "fgcolor" "117 107 94 255"
+ "centerwrap" "1"
+ }
+
+ "NoSteamLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "NoSteamLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#NoSteamNoItems"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "250"
+ "zpos" "1"
+ "wide" "f0"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "0"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NoGCLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "NoGCLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#NoGCNoItems"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "250"
+ "zpos" "1"
+ "wide" "f0"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "0"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "SelectLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "SelectLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#SelectClassLoadout"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "300"
+ "zpos" "1"
+ "wide" "f0"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "117 107 94 255"
+ }
+ "LoadoutChangesLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "LoadoutChangesLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#LoadoutChangesUpdate"
+ "textAlignment" "north"
+ "xpos" "0"
+ "ypos" "35"
+ "zpos" "1"
+ "wide" "f0"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+
+ "class_loadout_panel"
+ {
+ "ControlName" "CClassLoadoutPanel"
+ "fieldName" "class_loadout_panel"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "f0"
+ "tall" "400"
+ "zpos" "500"
+ "visible" "0"
+ }
+ "backpack_panel"
+ {
+ "ControlName" "CBackpackPanel"
+ "fieldName" "backpack_panel"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "f0"
+ "tall" "400"
+ "zpos" "500"
+ "visible" "0"
+ }
+
+ "ShowExplanationsButton"
+ {
+ "ControlName" "CExButton"
+ "fieldName" "ShowExplanationsButton"
+ "xpos" "c275"
+ "ypos" "10"
+ "zpos" "100"
+ "wide" "20"
+ "tall" "20"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" "?"
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "Command" "show_explanations"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "StartExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "StartExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "140"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c-150"
+ "end_y" "190"
+ "end_wide" "300"
+ "end_tall" "155"
+ "callout_inparents_x" "c0"
+ "callout_inparents_y" "150"
+ "next_explanation" "BackpackExplanation"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#LoadoutExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "260"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#LoadoutExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "45"
+ "wide" "260"
+ "tall" "85"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "280"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "125"
+ "zpos" "-1"
+ "wide" "300"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NextButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "NextButton"
+ "xpos" "260"
+ "ypos" "125"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "nextexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_forward"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "BackpackExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "BackpackExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "120"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c-320"
+ "end_y" "60"
+ "end_wide" "250"
+ "end_tall" "130"
+ "callout_inparents_x" "c-255"
+ "callout_inparents_y" "240"
+ "next_explanation" "CraftingExplanation"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#BackpackExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "210"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#BackpackExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "45"
+ "wide" "210"
+ "tall" "65"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "230"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PrevButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "PrevButton"
+ "xpos" "10"
+ "ypos" "100"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "prevexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_back"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "100"
+ "zpos" "-1"
+ "wide" "250"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NextButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "NextButton"
+ "xpos" "210"
+ "ypos" "100"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "nextexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_forward"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "CraftingExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "CraftingExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "120"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c-210"
+ "end_y" "60"
+ "end_wide" "250"
+ "end_tall" "140"
+ "callout_inparents_x" "c-130"
+ "callout_inparents_y" "240"
+ "next_explanation" "ArmoryExplanation"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#CraftingExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "210"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#CraftingExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "45"
+ "wide" "210"
+ "tall" "65"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "230"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PrevButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "PrevButton"
+ "xpos" "10"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "prevexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_back"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "110"
+ "zpos" "-1"
+ "wide" "250"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NextButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "NextButton"
+ "xpos" "210"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "nextexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_forward"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "ArmoryExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "ArmoryExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "120"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c-120"
+ "end_y" "60"
+ "end_wide" "250"
+ "end_tall" "140"
+ "callout_inparents_x" "c0"
+ "callout_inparents_y" "240"
+ "next_explanation" "TradingExplanation"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#ArmoryExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "210"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#ArmoryExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "45"
+ "wide" "210"
+ "tall" "65"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "230"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PrevButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "PrevButton"
+ "xpos" "10"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "prevexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_back"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "110"
+ "zpos" "-1"
+ "wide" "250"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NextButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "NextButton"
+ "xpos" "210"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "nextexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_forward"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "TradingExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "TradingExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "120"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c-30"
+ "end_y" "60"
+ "end_wide" "250"
+ "end_tall" "140"
+ "callout_inparents_x" "c130"
+ "callout_inparents_y" "240"
+ "next_explanation" "PatternsExplanation"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#TradingExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "210"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#TradingExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "45"
+ "wide" "210"
+ "tall" "65"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "230"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PrevButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "PrevButton"
+ "xpos" "10"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "prevexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_back"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "110"
+ "zpos" "-1"
+ "wide" "250"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NextButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "NextButton"
+ "xpos" "210"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "nextexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_forward"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "PatternsExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "PatternsExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "120"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c130"
+ "end_y" "60"
+ "end_wide" "250"
+ "end_tall" "140"
+ "callout_inparents_x" "c255"
+ "callout_inparents_y" "240"
+ "next_explanation" "ExplanationExplanation"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#WeaponPatternsExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "210"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#WeaponPatternsExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "35"
+ "wide" "210"
+ "tall" "75"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "230"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PrevButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "PrevButton"
+ "xpos" "10"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "prevexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_back"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "110"
+ "zpos" "-1"
+ "wide" "250"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ "NextButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "NextButton"
+ "xpos" "210"
+ "ypos" "110"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "nextexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_forward"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "ExplanationExplanation"
+ {
+ "ControlName" "CExplanationPopup"
+ "fieldName" "ExplanationExplanation"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "10000"
+ "wide" "250"
+ "tall" "120"
+ "visible" "0"
+ "PaintBackgroundType" "2"
+ "paintbackground" "0"
+ "border" "MainMenuHighlightBorder"
+
+ "force_close" "1"
+ "end_x" "c100"
+ "end_y" "100"
+ "end_wide" "250"
+ "end_tall" "120"
+ "callout_inparents_x" "c285"
+ "callout_inparents_y" "30"
+
+ "TitleLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TitleLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "#ExplanationExplanation_Title"
+ "textAlignment" "north"
+ "xpos" "20"
+ "ypos" "10"
+ "wide" "210"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "TextLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "TextLabel"
+ "font" "HudFontSmall"
+ "labelText" "#ExplanationExplanation_Text"
+ "textAlignment" "north-west"
+ "xpos" "20"
+ "ypos" "45"
+ "wide" "210"
+ "tall" "65"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "wrap" "1"
+ "fgcolor_override" "46 43 42 255"
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "230"
+ "ypos" "5"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "close"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ "PrevButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "PrevButton"
+ "xpos" "10"
+ "ypos" "90"
+ "zpos" "10"
+ "wide" "30"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "prevexplanation"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "200 80 60 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "255 255 255 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "30"
+ "tall" "30"
+ "visible" "1"
+ "enabled" "1"
+ "image" "blog_back"
+ "scaleImage" "1"
+ }
+ }
+ "PositionLabel"
+ {
+ "ControlName" "CExLabel"
+ "fieldName" "PositionLabel"
+ "font" "HudFontSmallBold"
+ "labelText" "%explanationnumber%"
+ "textAlignment" "center"
+ "xpos" "0"
+ "ypos" "90"
+ "zpos" "-1"
+ "wide" "250"
+ "tall" "30"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "fgcolor_override" "200 80 60 255"
+ }
+ }
+
+ "armory_panel"
+ {
+ "ControlName" "CArmoryPanel"
+ "fieldName" "armory_panel"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "f0"
+ "tall" "400"
+ "zpos" "500"
+ "visible" "0"
+ }
+
+ "InspectionPanel"
+ {
+ "fieldName" "InspectionPanel"
+ "xpos" "cs-0.5"
+ "ypos" "0"
+ "zpos" "2000"
+ "wide" "f0"
+ "tall" "f100"
+ "visible" "0"
+ "proportionaltoparent" "1"
+ "bgcolor_override" "30 25 25 245"
+ }
+
+}
diff --git a/game/mod_tf/resource/ui/CharInfoPanel.res b/game/mod_tf/resource/ui/CharInfoPanel.res
new file mode 100644
index 00000000..55f5ca57
--- /dev/null
+++ b/game/mod_tf/resource/ui/CharInfoPanel.res
@@ -0,0 +1,256 @@
+"Resource/UI/CharInfoPanel.res"
+{
+ "character_info"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "character_info"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "f0"
+ "tall" "480"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "settitlebarvisible" "1"
+ "PaintBackgroundType" "0"
+ "bgcolor_override" "46 43 42 0"
+ "infocus_bgcolor_override" "46 43 42 0"
+ "outoffocus_bgcolor_override" "46 43 42 0"
+
+ "title" "#CharInfoAndSetup"
+ "title_font" "HudFontMediumBold"
+ "titletextinsetX" "40"
+ "titletextinsetY" "0"
+ "titlebarfgcolor_override" "200 187 161 255"
+ "titlebardisabledfgcolor_override" "200 187 161 255"
+ "titlebarbgcolor_override" "46 43 42 255"
+
+ "clientinsetx_override" "0"
+ "sheetinset_bottom" "40"
+ }
+
+ "BackgroundHeader"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "BackgroundHeader"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "-2"
+ "wide" "f0"
+ "tall" "120"
+ "visible" "1"
+ "enabled" "1"
+ "image" "loadout_header"
+ "tileImage" "1"
+ }
+ "BackgroundFooter"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "BackgroundFooter"
+ "xpos" "0"
+ "ypos" "420"
+ "zpos" "1"
+ "wide" "f0"
+ "tall" "60"
+ "visible" "1"
+ "enabled" "1"
+ "image" "loadout_bottom_gradient"
+ "tileImage" "1"
+ }
+ "FooterLine"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "FooterLine"
+ "xpos" "0"
+ "ypos" "420"
+ "zpos" "2"
+ "wide" "f0"
+ "tall" "10"
+ "visible" "1"
+ "enabled" "1"
+ "image" "loadout_solid_line"
+ "scaleImage" "1"
+ }
+
+ "Sheet"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "Sheet"
+ "tabxindent" "80"
+ "tabxdelta" "10"
+ "tabwidth" "240"
+ "tabheight" "20"
+ "transition_time" "0"
+ "yoffset" "14"
+
+ "HeaderLine"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "HeaderLine"
+ "xpos" "0"
+ "ypos" "32"
+ "zpos" "5"
+ "wide" "f0"
+ "tall" "10"
+ "visible" "1"
+ "enabled" "1"
+ "image" "loadout_solid_line"
+ "scaleImage" "1"
+ }
+
+ "tabskv"
+ {
+ "textinsetx" "40"
+ "font" "HudFontMediumSmallBold"
+ "selectedcolor" "200 187 161 255"
+ "unselectedcolor" "130 120 104 255"
+ "defaultBgColor_override" "46 43 42 255"
+ "paintbackground" "0"
+ "activeborder_override" "OutlinedGreyBox"
+ "normalborder_override" "OutlinedDullGreyBox"
+ }
+ }
+
+ "BackButton"
+ {
+ "ControlName" "CExButton"
+ "fieldName" "BackButton"
+ "xpos" "c-295"
+ "ypos" "437"
+ "zpos" "2"
+ "wide" "100"
+ "tall" "25"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" "#TF_BackCarat"
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "Command" "back"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "ClearButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "ClearButton"
+ "xpos" "c-150"
+ "ypos" "437"
+ "zpos" "2"
+ "wide" "25"
+ "tall" "25"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "image_drawcolor" "235 226 202 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "5"
+ "ypos" "5"
+ "zpos" "1"
+ "wide" "15"
+ "tall" "15"
+ "visible" "1"
+ "enabled" "1"
+ "image" "glyph_workshop_delete"
+ "scaleImage" "1"
+ }
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "Command" "clear_loadout_ui"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "ResetButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "ResetButton"
+ "xpos" "c-185"
+ "ypos" "437"
+ "zpos" "2"
+ "wide" "25"
+ "tall" "25"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" ""
+ "image_drawcolor" "235 226 202 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "5"
+ "ypos" "5"
+ "zpos" "1"
+ "wide" "15"
+ "tall" "15"
+ "visible" "1"
+ "enabled" "1"
+ "image" "glyph_server"
+ "scaleImage" "1"
+ }
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ "Command" "reset_loadout_ui"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+
+ "LocalInfo"
+ {
+ "ControlName" "Label"
+ "fieldName" "LocalInfo"
+ "xpos" "c-115"
+ "ypos" "438"
+ "zpos" "2"
+ "wide" "640"
+ "tall" "25"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labelText" "#TF_SDK_LocalLoadout"
+ "image_drawcolor" "235 226 202 255"
+ "font" "HudFontSmall"
+ "textAlignment" "west"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "0"
+ }
+
+ "NotificationsPresentPanel"
+ {
+ "ControlName" "CNotificationsPresentPanel"
+ "fieldName" "NotificationsPresentPanel"
+ "xpos" "r200"
+ "ypos" "10"
+ "zpos" "10000"
+ "wide" "190"
+ "tall" "50"
+ "visible" "0"
+ "enabled" "1"
+ }
+}
diff --git a/game/mod_tf/resource/ui/MatchMakingDashboard.res b/game/mod_tf/resource/ui/MatchMakingDashboard.res
new file mode 100644
index 00000000..76f9a156
--- /dev/null
+++ b/game/mod_tf/resource/ui/MatchMakingDashboard.res
@@ -0,0 +1,865 @@
+"Resource/UI/MatchMakingDashboard.res"
+{
+ "MMDashboard"
+ {
+ "fieldName" "MMDashboard"
+ "visible" "1"
+ "enabled" "1"
+ "xpos" "cs-0.5"
+ "ypos" "-5"
+ "zpos" "10001"
+ "wide" "f0"
+ "tall" "35"
+ "keyboardinputenabled" "0"
+
+ "collapsed_height" "0"
+ "expanded_height" "35"
+ "resize_time" "0.2"
+ }
+
+ "TopBar"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "TopBar"
+ "xpos" "cs-0.5"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "f0"
+ "tall" "35"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "pinCorner" "2"
+ "autoResize" "1"
+
+ "Gradient"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "Gradient"
+ "xpos" "0"
+ "ypos" "0"
+ "wide" "p0.5"
+ "tall" "f6"
+ "zpos" "0"
+ "visible" "1"
+ "enabled" "1"
+ "rotation" "2"
+ "proportionaltoparent" "1"
+ "scaleimage" "1"
+ "mouseinputenabled" "0"
+ "alpha" "100"
+
+ "image" "gradient_pure_black"
+ }
+
+ "BGPanel"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "BGPanel"
+ "xpos" "cs-0.5"
+ "ypos" "0"
+ "zpos" "-1"
+ "wide" "p1.1"
+ "tall" "f5"
+ "visible" "1"
+ "PaintBackgroundType" "2"
+ "border" "ReplayDefaultBorder"
+ "proportionaltoparent" "1"
+ }
+
+ "OuterShadow"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "OuterShadow"
+ "xpos" "cs-0.5"
+ "ypos" "cs-0.5"
+ "zpos" "-2"
+ "wide" "p1.1"
+ "tall" "p1"
+ "visible" "1"
+ "PaintBackgroundType" "2"
+ "border" "OuterShadowBorder"
+ "proportionaltoparent" "1"
+ }
+
+ "ToggleChatButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "ToggleChatButton"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "100"
+ "wide" "40"
+ "tall" "f6"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallestBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "toggle_chat"
+ "proportionaltoparent" "1"
+ "labeltext" ""
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "2"
+ "roundedcorners" "0"
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+
+ "image_drawcolor" "TanLight"
+ "image_armedcolor" "TanLight"
+
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "cs-0.5"
+ "ypos" "rs1-2"
+ "zpos" "1"
+ "wide" "20"
+ "tall" "20"
+ "visible" "1"
+ "enabled" "1"
+ "scaleImage" "1"
+ "proportionaltoparent" "1"
+ "image" "glyph_chat"
+ }
+ }
+
+ "PartySlot0"
+ {
+ "ControlName" "CDashboardPartyMember"
+ "fieldName" "PartySlot0"
+ "xpos" "40"
+ "ypos" "rs1-6"
+ "zpos" "100"
+ "wide" "o1"
+ "tall" "24"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+
+ "party_slot" "0"
+ }
+
+ "PartySlot1"
+ {
+ "ControlName" "CDashboardPartyMember"
+ "fieldName" "PartySlot1"
+ "xpos" "64"
+ "ypos" "rs1-6"
+ "zpos" "100"
+ "wide" "o1"
+ "tall" "24"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+
+ "party_slot" "1"
+ }
+
+ "PartySlot2"
+ {
+ "ControlName" "CDashboardPartyMember"
+ "fieldName" "PartySlot2"
+ "xpos" "88"
+ "ypos" "rs1-6"
+ "zpos" "100"
+ "wide" "o1"
+ "tall" "24"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+
+ "party_slot" "2"
+ }
+
+ "PartySlot3"
+ {
+ "ControlName" "CDashboardPartyMember"
+ "fieldName" "PartySlot3"
+ "xpos" "112"
+ "ypos" "rs1-6"
+ "zpos" "100"
+ "wide" "o1"
+ "tall" "24"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+
+ "party_slot" "3"
+ }
+
+ "PartySlot4"
+ {
+ "ControlName" "CDashboardPartyMember"
+ "fieldName" "PartySlot4"
+ "xpos" "136"
+ "ypos" "rs1-6"
+ "zpos" "100"
+ "wide" "o1"
+ "tall" "24"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+
+ "party_slot" "4"
+ }
+
+ "PartySlot5"
+ {
+ "ControlName" "CDashboardPartyMember"
+ "fieldName" "PartySlot5"
+ "xpos" "160"
+ "ypos" "rs1-6"
+ "zpos" "100"
+ "wide" "o1"
+ "tall" "24"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+
+ "party_slot" "5"
+ }
+
+ "QueueContainer"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "QueueContainer"
+ "xpos" "cs-0.5"
+ "ypos" "-50"
+ "zpos" "111"
+ "wide" "220"
+ "tall" "f0"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "OuterShadow"
+ {
+ "ControlName" "Panel"
+ "fieldName" "OuterShadow"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "-1"
+ "wide" "f0"
+ "tall" "f0"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "border" "OuterShadowBorderThin"
+ }
+
+ "BGPanel"
+ {
+ "ControlName" "Panel"
+ "fieldName" "BGPanel"
+ "xpos" "cs-0.5"
+ "ypos" "cs-0.5"
+ "zpos" "0"
+ "wide" "f4"
+ "tall" "f4"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "border" "ReplayDefaultBorder"
+ }
+
+ "QueueLogoButton"
+ {
+ "ControlName" "Button"
+ "fieldName" "QueueLogoButton"
+ "xpos" "0"
+ "ypos" "1"
+ "zpos" "10"
+ "wide" "o1"
+ "tall" "f0"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "1"
+ "Command" "queue_logo_clicked"
+ "proportionaltoparent" "1"
+ "actionsignallevel" "3"
+ "button_activation_type" "1"
+
+ "paintbackground" "0"
+ "paintborder" "0"
+ }
+
+ "CTFLogoPanel"
+ {
+ "ControlName" "CTFLogoPanel"
+ "fieldname" "CTFLogoPanel"
+ "xpos" "0"
+ "ypos" "1"
+ "zpos" "5"
+ "wide" "o1"
+ "tall" "f0"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "radius" "10"
+ "velocity" "100"
+
+ "fgcolor_override" "TFOrange"
+ }
+
+ "QueueText"
+ {
+ "ControlName" "CAutoFittingLabel"
+ "fieldName" "QueueText"
+ "xpos" "33"
+ "ypos" "1"
+ "wide" "f55"
+ "zpos" "100"
+ "tall" "f0"
+ "visible" "1"
+ "enabled" "1"
+ "font" "HudFontSmallestBold"
+ "fgcolor_override" "TanLight"
+ "textAlignment" "west"
+ "labelText" "%queue_state%"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "0"
+
+ "fonts"
+ {
+ "0"
+ {
+ "font" "HudFontSmallestBold" // TF2 Build 11
+ }
+ "1"
+ {
+ "font" "StorePromotionsTitle" // TF2 Build 10
+ }
+ "2"
+ {
+ "font" "FontStorePrice" // TF2 Build 9
+ }
+ }
+ }
+
+ "MultiQueuesManageButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "MultiQueuesManageButton"
+ "xpos" "rs1-6"
+ "ypos" "11"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "1"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "manage_queues"
+ "proportionaltoparent" "1"
+ "actionsignallevel" "3"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "glyph_options"
+ "scaleImage" "1"
+ }
+ }
+
+ "CloseButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "CloseButton"
+ "xpos" "rs1-6"
+ "ypos" "11"
+ "zpos" "10"
+ "wide" "14"
+ "tall" "14"
+ "autoResize" "0"
+ "pinCorner" "0"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "labeltext" ""
+ "font" "HudFontSmallBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "default" "1"
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ "Command" "leave_queue"
+ "proportionaltoparent" "1"
+ "actionsignallevel" "3"
+
+ "paintbackground" "0"
+
+ "defaultFgColor_override" "46 43 42 255"
+ "armedFgColor_override" "235 226 202 255"
+ "depressedFgColor_override" "46 43 42 255"
+
+ "image_drawcolor" "117 107 94 255"
+ "image_armedcolor" "200 80 60 255"
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "image" "close_button"
+ "scaleImage" "1"
+ }
+ }
+ }
+
+ "JoinPartyLobbyContainer"
+ {
+ "ControlName" "EditablePanel"
+ "fieldName" "JoinPartyLobbyContainer"
+ "xpos" "cs-0.5"
+ "ypos" "-50"
+ "zpos" "110"
+ "wide" "220"
+ "tall" "f0"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "OuterShadow"
+ {
+ "ControlName" "Panel"
+ "fieldName" "OuterShadow"
+ "xpos" "0"
+ "ypos" "0"
+ "zpos" "-1"
+ "wide" "f0"
+ "tall" "f0"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "border" "OuterShadowBorderThin"
+ }
+
+ "BGPanel"
+ {
+ "ControlName" "Panel"
+ "fieldName" "BGPanel"
+ "xpos" "cs-0.5"
+ "ypos" "cs-0.5"
+ "zpos" "0"
+ "wide" "f6"
+ "tall" "f6"
+ "visible" "1"
+ "proportionaltoparent" "1"
+
+ "border" "ReplayDefaultBorder"
+ }
+
+ "PromptText"
+ {
+ "ControlName" "Label"
+ "fieldName" "PromptText"
+ "xpos" "cs-0.5"
+ "ypos" "1"
+ "wide" "f35"
+ "zpos" "100"
+ "tall" "f0"
+ "visible" "1"
+ "enabled" "1"
+ "font" "HudFontSmallestBold"
+ "fgcolor_override" "TanLight"
+ "textAlignment" "west"
+ "labelText" "#TF_MM_JoinPartyLobby_Prompt"
+ "proportionaltoparent" "1"
+ "mouseinputenabled" "0"
+ }
+
+ "JoinNowButton"
+ {
+ "ControlName" "CExButton"
+ "fieldName" "JoinNowButton"
+ "xpos" "rs1-10"
+ "ypos" "rs1-9"
+ "wide" "40"
+ "zpos" "100"
+ "tall" "15"
+
+ if_queued
+ {
+ "xpos" "cs-0.5"
+ "wide" "150"
+ }
+
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallestBold"
+ "textAlignment" "center"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "join_party_match"
+ "proportionaltoparent" "1"
+ "labeltext" "#TF_MM_JoinPartyLobby_Join"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "3"
+
+ "armedBgColor_override" "CreditsGreen"
+ "defaultBgColor_override" "SaleGreen"
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+ }
+ }
+
+ "QuitButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "QuitButton"
+ "xpos" "rs1"
+ "ypos" "0"
+ "zpos" "100"
+ "wide" "30"
+ "tall" "f6"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallBold"
+ "textAlignment" "west"
+ "textinsetx" "0"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "quit"
+ "proportionaltoparent" "1"
+ "labeltext" ""
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "2"
+ "RoundedCorners" "0"
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+
+ "armedBgColor_override" "192 28 0 150"
+ "defaultBgColor_override" "192 28 0 50"
+
+ "defaultFgColor_override" "TanLight"
+ "armedFgColor_override" "TanLight"
+
+ "image_drawcolor" "TanLight"
+ "image_armedcolor" "TanLight"
+
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "cs-0.5"
+ "ypos" "rs1-5"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "scaleImage" "1"
+ "proportionaltoparent" "1"
+ "image" "glyph_quit"
+ "drawcolor_override" "TanLight"
+ }
+ }
+
+ "DisconnectButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "DisconnectButton"
+ "xpos" "rs1"
+ "ypos" "0"
+ "zpos" "100"
+ "wide" "110"
+ "wide" "110" [!$POSIX]
+ "wide" "115" [$POSIX]
+ "tall" "f6"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallBold"
+ "textAlignment" "west"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "quit"
+ "proportionaltoparent" "1"
+ "labeltext" "#TF_Disconnect"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "2"
+ "RoundedCorners" "0"
+ "textinsety" "2.5"
+ "textinsetx" "26"
+ "use_proportional_insets" "1"
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+
+ "armedBgColor_override" "192 28 0 150"
+ "defaultBgColor_override" "192 28 0 50"
+
+ "defaultFgColor_override" "TanLight"
+ "armedFgColor_override" "TanLight"
+
+ "image_drawcolor" "TanLight"
+ "image_armedcolor" "TanLight"
+
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "6"
+ "ypos" "rs1-5"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "scaleImage" "1"
+ "proportionaltoparent" "1"
+ "image" "glyph_disconnect"
+ "drawcolor_override" "TanLight"
+ }
+ }
+
+ "ResumeButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "ResumeButton"
+ "xpos" "rs1-31-131"
+ "ypos" "0"
+ "zpos" "100"
+ "wide" "90" [!$POSIX]
+ "wide" "95" [$POSIX]
+ "tall" "f6"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "0"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallBold"
+ "textAlignment" "west"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "resume_game"
+ "proportionaltoparent" "1"
+ "labeltext" "#MMenu_ResumeGame"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "2"
+ "roundedcorners" "1"
+ "textinsety" "2.5"
+ "textinsetx" "26"
+ "use_proportional_insets" "1"
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+
+ // "armedBgColor_override" "CreditsGreen"
+ // "defaultBgColor_override" "GreenSolid"
+
+ "defaultFgColor_override" "TanLight"
+ "armedFgColor_override" "TanLight"
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "235 226 202 255"
+
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "6"
+ "ypos" "10"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "scaleImage" "1"
+ "proportionaltoparent" "1"
+ "image" "icon_resume"
+ "drawcolor_override" "TanLight"
+ }
+ }
+
+ "FindAGameButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "FindAGameButton"
+ "xpos" "rs1-31"
+ "ypos" "0"
+ "zpos" "100"
+ "wide" "115" [!$POSIX]
+ "wide" "120" [$POSIX]
+ "tall" "f6"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallBold"
+ "textAlignment" "west"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "find_game"
+ "proportionaltoparent" "1"
+ "labeltext" "#MMenu_FindAGame"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "2"
+ "roundedcorners" "1"
+ "textinsety" "2.5"
+ "textinsetx" "26"
+ "use_proportional_insets" "1"
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+
+ "armedBgColor_override" "CreditsGreen"
+ "defaultBgColor_override" "GreenSolid"
+
+ "defaultFgColor_override" "TanLight"
+ "armedFgColor_override" "TanLight"
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "235 226 202 255"
+
+ "SubImage"
+ {
+ "ControlName" "ImagePanel"
+ "fieldName" "SubImage"
+ "xpos" "6"
+ "ypos" "10"
+ "zpos" "1"
+ "wide" "14"
+ "tall" "14"
+ "visible" "1"
+ "enabled" "1"
+ "scaleImage" "1"
+ "proportionaltoparent" "1"
+ "image" "glyph_multiplayer"
+ "drawcolor_override" "TanLight"
+ }
+ }
+
+ "HostGameButton"
+ {
+ "ControlName" "CExImageButton"
+ "fieldName" "HostGameButton"
+ "xpos" "rs1-145"
+ "ypos" "0"
+ "zpos" "100"
+ "wide" "115"
+ "tall" "f6"
+ "autoResize" "0"
+ "pinCorner" "3"
+ "visible" "1"
+ "enabled" "1"
+ "tabPosition" "0"
+ "font" "HudFontSmallBold"
+ "textAlignment" "west"
+ "dulltext" "0"
+ "brighttext" "0"
+ "Command" "create_server"
+ "proportionaltoparent" "1"
+ "labeltext" "#MMenu_HostAGame"
+ "mouseinputenabled" "1"
+ "keyboardinputenabled" "0"
+ "actionsignallevel" "2"
+ "roundedcorners" "1"
+ "textinsety" "2.5"
+ "textinsetx" "15"
+ "use_proportional_insets" "1"
+
+
+ "sound_depressed" "UI/buttonclick.wav"
+ "sound_released" "UI/buttonclickrelease.wav"
+
+ "armedBgColor_override" "LighterDarkBrown"
+ "defaultBgColor_override" "DarkBrown"
+
+ "defaultFgColor_override" "TanLight"
+ "armedFgColor_override" "TanLight"
+ "image_drawcolor" "235 226 202 255"
+ "image_armedcolor" "235 226 202 255"
+
+ }
+ }
+}
diff --git a/game/mod_tf/steam.inf b/game/mod_tf/steam.inf
new file mode 100644
index 00000000..31aac9ee
--- /dev/null
+++ b/game/mod_tf/steam.inf
@@ -0,0 +1,6 @@
+PatchVersion=2000
+ClientVersion=2000
+ServerVersion=2000
+ProductName=mod_tf
+appID=243750
+ServerAppID=244310
diff --git a/game/thirdpartylegalnotices.txt b/game/thirdpartylegalnotices.txt
new file mode 100644
index 00000000..f417b485
--- /dev/null
+++ b/game/thirdpartylegalnotices.txt
@@ -0,0 +1,912 @@
+The Source engine and Valve games use Third Party code for certain functions. The
+required legal notices for using such code are reproduced below in accordance with
+Valve�s obligations to provide such notices:
+
+************************************************************************************
+Xzip/Xunzip:
+************************************************************************************
+
+ // This is version 2002-Feb-16 of the Info-ZIP copyright and license. The
+ // definitive version of this document should be available at
+ // ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely.
+ //
+ // Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
+ //
+ // For the purposes of this copyright and license, "Info-ZIP" is defined as
+ // the following set of individuals:
+ //
+ // Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
+ // Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase,
+ // Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
+ // David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
+ // Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
+ // Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler,
+ // Antoine Verheijen, Paul von Behren, Rich Wales, Mike White
+ //
+ // This software is provided "as is", without warranty of any kind, express
+ // or implied. In no event shall Info-ZIP or its contributors be held liable
+ // for any direct, indirect, incidental, special or consequential damages
+ // arising out of the use of or inability to use this software.
+ //
+ // Permission is granted to anyone to use this software for any purpose,
+ // including commercial applications, and to alter it and redistribute it
+ // freely, subject to the following restrictions:
+ //
+ // 1. Redistributions of source code must retain the above copyright notice,
+ // definition, disclaimer, and this list of conditions.
+ //
+ // 2. Redistributions in binary form (compiled executables) must reproduce
+ // the above copyright notice, definition, disclaimer, and this list of
+ // conditions in documentation and/or other materials provided with the
+ // distribution. The sole exception to this condition is redistribution
+ // of a standard UnZipSFX binary as part of a self-extracting archive;
+ // that is permitted without inclusion of this license, as long as the
+ // normal UnZipSFX banner has not been removed from the binary or disabled.
+ //
+ // 3. Altered versions--including, but not limited to, ports to new
+ // operating systems, existing ports with new graphical interfaces, and
+ // dynamic, shared, or static library versions--must be plainly marked
+ // as such and must not be misrepresented as being the original source.
+ // Such altered versions also must not be misrepresented as being
+ // Info-ZIP releases--including, but not limited to, labeling of the
+ // altered versions with the names "Info-ZIP" (or any variation thereof,
+ // including, but not limited to, different capitalizations),
+ // "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of
+ // Info-ZIP. Such altered versions are further prohibited from
+ // misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or
+ // of the Info-ZIP URL(s).
+ //
+ // 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip",
+ // "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its
+ // own source and binary releases.
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+************************************************************************************
+JPEG image support:
+************************************************************************************
+
+ The Source engine and SDK also make use of library functions for working with .jpg
+ files. Specifically, the Source engine jpeg library is based in part on the work of
+ the Independent JPEG Group (IJG). The original source code and project files for the IJG's
+ JPEG libraries may be found at: http://www.ijg.org/files/jpegsrc.v6b.tar.gz
+
+ The following is the README. File from that archive and is produced in accordance with the legal
+ notices required by the library:
+
+ The Independent JPEG Group's JPEG software
+ ==========================================
+
+ README for release 6b of 27-Mar-1998
+ ====================================
+
+ This distribution contains the sixth public release of the Independent JPEG
+ Group's free JPEG software. You are welcome to redistribute this software and
+ to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+ Serious users of this software (particularly those incorporating it into
+ larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
+ our electronic mailing list. Mailing list members are notified of updates
+ and have a chance to participate in technical discussions, etc.
+
+ This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
+ Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
+ Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
+ Group.
+
+ IJG is not affiliated with the official ISO JPEG standards committee.
+
+
+ DOCUMENTATION ROADMAP
+ =====================
+
+ This file contains the following sections:
+
+ OVERVIEW General description of JPEG and the IJG software.
+ LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
+ REFERENCES Where to learn more about JPEG.
+ ARCHIVE LOCATIONS Where to find newer versions of this software.
+ RELATED SOFTWARE Other stuff you should get.
+ FILE FORMAT WARS Software *not* to get.
+ TO DO Plans for future IJG releases.
+
+ Other documentation files in the distribution are:
+
+ User documentation:
+ install.doc How to configure and install the IJG software.
+ usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
+ rdjpgcom, and wrjpgcom.
+ *.1 Unix-style man pages for programs (same info as usage.doc).
+ wizard.doc Advanced usage instructions for JPEG wizards only.
+ change.log Version-to-version change highlights.
+ Programmer and internal documentation:
+ libjpeg.doc How to use the JPEG library in your own programs.
+ example.c Sample code for calling the JPEG library.
+ structure.doc Overview of the JPEG library's internal structure.
+ filelist.doc Road map of IJG files.
+ coderules.doc Coding style rules --- please read if you contribute code.
+
+ Please read at least the files install.doc and usage.doc. Useful information
+ can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
+ ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
+
+ If you want to understand how the JPEG code works, we suggest reading one or
+ more of the REFERENCES, then looking at the documentation files (in roughly
+ the order listed) before diving into the code.
+
+
+ OVERVIEW
+ ========
+
+ This package contains C software to implement JPEG image compression and
+ decompression. JPEG (pronounced "jay-peg") is a standardized compression
+ method for full-color and gray-scale images. JPEG is intended for compressing
+ "real-world" scenes; line drawings, cartoons and other non-realistic images
+ are not its strong suit. JPEG is lossy, meaning that the output image is not
+ exactly identical to the input image. Hence you must not use JPEG if you
+ have to have identical output bits. However, on typical photographic images,
+ very good compression levels can be obtained with no visible change, and
+ remarkably high compression levels are possible if you can tolerate a
+ low-quality image. For more details, see the references, or just experiment
+ with various compression settings.
+
+ This software implements JPEG baseline, extended-sequential, and progressive
+ compression processes. Provision is made for supporting all variants of these
+ processes, although some uncommon parameter settings aren't implemented yet.
+ For legal reasons, we are not distributing code for the arithmetic-coding
+ variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting
+ the hierarchical or lossless processes defined in the standard.
+
+ We provide a set of library routines for reading and writing JPEG image files,
+ plus two sample applications "cjpeg" and "djpeg", which use the library to
+ perform conversion between JPEG and some other popular image file formats.
+ The library is intended to be reused in other applications.
+
+ In order to support file conversion and viewing software, we have included
+ considerable functionality beyond the bare JPEG coding/decoding capability;
+ for example, the color quantization modules are not strictly part of JPEG
+ decoding, but they are essential for output to colormapped file formats or
+ colormapped displays. These extra functions can be compiled out of the
+ library if not required for a particular application. We have also included
+ "jpegtran", a utility for lossless transcoding between different JPEG
+ processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
+ inserting and extracting textual comments in JFIF files.
+
+ The emphasis in designing this software has been on achieving portability and
+ flexibility, while also making it fast enough to be useful. In particular,
+ the software is not intended to be read as a tutorial on JPEG. (See the
+ REFERENCES section for introductory material.) Rather, it is intended to
+ be reliable, portable, industrial-strength code. We do not claim to have
+ achieved that goal in every aspect of the software, but we strive for it.
+
+ We welcome the use of this software as a component of commercial products.
+ No royalty is required, but we do ask for an acknowledgement in product
+ documentation, as described under LEGAL ISSUES.
+
+
+ LEGAL ISSUES
+ ============
+
+ In plain English:
+
+ 1. We don't promise that this software works. (But if you find any bugs,
+ please let us know!)
+ 2. You can use this software for whatever you want. You don't have to pay us.
+ 3. You may not pretend that you wrote this software. If you use it in a
+ program, you must acknowledge somewhere in your documentation that
+ you've used the IJG code.
+
+ In legalese:
+
+ The authors make NO WARRANTY or representation, either express or implied,
+ with respect to this software, its quality, accuracy, merchantability, or
+ fitness for a particular purpose. This software is provided "AS IS", and you,
+ its user, assume the entire risk as to its quality and accuracy.
+
+ This software is copyright (C) 1991-1998, Thomas G. Lane.
+ All Rights Reserved except as specified below.
+
+ Permission is hereby granted to use, copy, modify, and distribute this
+ software (or portions thereof) for any purpose, without fee, subject to these
+ conditions:
+ (1) If any part of the source code for this software is distributed, then this
+ README file must be included, with this copyright and no-warranty notice
+ unaltered; and any additions, deletions, or changes to the original files
+ must be clearly indicated in accompanying documentation.
+ (2) If only executable code is distributed, then the accompanying
+ documentation must state that "this software is based in part on the work of
+ the Independent JPEG Group".
+ (3) Permission for use of this software is granted only if the user accepts
+ full responsibility for any undesirable consequences; the authors accept
+ NO LIABILITY for damages of any kind.
+
+ These conditions apply to any software derived from or based on the IJG code,
+ not just to the unmodified library. If you use our work, you ought to
+ acknowledge us.
+
+ Permission is NOT granted for the use of any IJG author's name or company name
+ in advertising or publicity relating to this software or products derived from
+ it. This software may be referred to only as "the Independent JPEG Group's
+ software".
+
+ We specifically permit and encourage the use of this software as the basis of
+ commercial products, provided that all warranty or liability claims are
+ assumed by the product vendor.
+
+
+ ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+ sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+ by the usual distribution terms of the Free Software Foundation; principally,
+ that you must include source code if you redistribute it. (See the file
+ ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
+ of any program generated from the IJG code, this does not limit you more than
+ the foregoing paragraphs do.
+
+ The Unix configuration script "configure" was produced with GNU Autoconf.
+ It is copyright by the Free Software Foundation but is freely distributable.
+ The same holds for its supporting scripts (config.guess, config.sub,
+ ltconfig, ltmain.sh). Another support script, install-sh, is copyright
+ by M.I.T. but is also freely distributable.
+
+ It appears that the arithmetic coding option of the JPEG spec is covered by
+ patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
+ legally be used without obtaining one or more licenses. For this reason,
+ support for arithmetic coding has been removed from the free JPEG software.
+ (Since arithmetic coding provides only a marginal gain over the unpatented
+ Huffman mode, it is unlikely that very many implementations will support it.)
+ So far as we are aware, there are no patent restrictions on the remaining
+ code.
+
+ The IJG distribution formerly included code to read and write GIF files.
+ To avoid entanglement with the Unisys LZW patent, GIF reading support has
+ been removed altogether, and the GIF writer has been simplified to produce
+ "uncompressed GIFs". This technique does not use the LZW algorithm; the
+ resulting GIF files are larger than usual, but are readable by all standard
+ GIF decoders.
+
+ We are required to state that
+ "The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated."
+
+
+ REFERENCES
+ ==========
+
+ We highly recommend reading one or more of these references before trying to
+ understand the innards of the JPEG software.
+
+ The best short technical introduction to the JPEG compression algorithm is
+ Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
+ Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+ (Adjacent articles in that issue discuss MPEG motion picture compression,
+ applications of JPEG, and related topics.) If you don't have the CACM issue
+ handy, a PostScript file containing a revised version of Wallace's article is
+ available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually
+ a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
+ omits the sample images that appeared in CACM, but it includes corrections
+ and some added material. Note: the Wallace article is copyright ACM and IEEE,
+ and it may not be used for commercial purposes.
+
+ A somewhat less technical, more leisurely introduction to JPEG can be found in
+ "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
+ M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
+ good explanations and example C code for a multitude of compression methods
+ including JPEG. It is an excellent source if you are comfortable reading C
+ code but don't know much about data compression in general. The book's JPEG
+ sample code is far from industrial-strength, but when you are ready to look
+ at a full implementation, you've got one here...
+
+ The best full description of JPEG is the textbook "JPEG Still Image Data
+ Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
+ by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
+ The book includes the complete text of the ISO JPEG standards (DIS 10918-1
+ and draft DIS 10918-2). This is by far the most complete exposition of JPEG
+ in existence, and we highly recommend it.
+
+ The JPEG standard itself is not available electronically; you must order a
+ paper copy through ISO or ITU. (Unless you feel a need to own a certified
+ official copy, we recommend buying the Pennebaker and Mitchell book instead;
+ it's much cheaper and includes a great deal of useful explanatory material.)
+ In the USA, copies of the standard may be ordered from ANSI Sales at (212)
+ 642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
+ doesn't take credit card orders, but Global does.) It's not cheap: as of
+ 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
+ shipping/handling. The standard is divided into two parts, Part 1 being the
+ actual specification, while Part 2 covers compliance testing methods. Part 1
+ is titled "Digital Compression and Coding of Continuous-tone Still Images,
+ Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
+ 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
+ Continuous-tone Still Images, Part 2: Compliance testing" and has document
+ numbers ISO/IEC IS 10918-2, ITU-T T.83.
+
+ Some extensions to the original JPEG standard are defined in JPEG Part 3,
+ a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG
+ currently does not support any Part 3 extensions.
+
+ The JPEG standard does not specify all details of an interchangeable file
+ format. For the omitted details we follow the "JFIF" conventions, revision
+ 1.02. A copy of the JFIF spec is available from:
+ Literature Department
+ C-Cube Microsystems, Inc.
+ 1778 McCarthy Blvd.
+ Milpitas, CA 95035
+ phone (408) 944-6300, fax (408) 944-6314
+ A PostScript version of this document is available by FTP at
+ ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
+ version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
+ the figures.
+
+ The TIFF 6.0 file format specification can be obtained by FTP from
+ ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
+ found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
+ IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
+ Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
+ (Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or
+ from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision
+ of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
+ Although IJG's own code does not support TIFF/JPEG, the free libtiff library
+ uses our library to implement TIFF/JPEG per the Note. libtiff is available
+ from ftp://ftp.sgi.com/graphics/tiff/.
+
+
+ ARCHIVE LOCATIONS
+ =================
+
+ The "official" archive site for this software is ftp.uu.net (Internet
+ address 192.48.96.9). The most recent released version can always be found
+ there in directory graphics/jpeg. This particular version will be archived
+ as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have
+ direct Internet access, UUNET's archives are also available via UUCP; contact
+ help@uunet.uu.net for information on retrieving files that way.
+
+ Numerous Internet sites maintain copies of the UUNET files. However, only
+ ftp.uu.net is guaranteed to have the latest official version.
+
+ You can also obtain this software in DOS-compatible "zip" archive format from
+ the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
+ on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
+ "JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net
+ release.
+
+ The JPEG FAQ (Frequently Asked Questions) article is a useful source of
+ general information about JPEG. It is updated constantly and therefore is
+ not included in this distribution. The FAQ is posted every two weeks to
+ Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
+ It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
+ and other news.answers archive sites, including the official news.answers
+ archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
+ If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
+ with body
+ send usenet/news.answers/jpeg-faq/part1
+ send usenet/news.answers/jpeg-faq/part2
+
+
+ RELATED SOFTWARE
+ ================
+
+ Numerous viewing and image manipulation programs now support JPEG. (Quite a
+ few of them use this library to do so.) The JPEG FAQ described above lists
+ some of the more popular free and shareware viewers, and tells where to
+ obtain them on Internet.
+
+ If you are on a Unix machine, we highly recommend Jef Poskanzer's free
+ PBMPLUS software, which provides many useful operations on PPM-format image
+ files. In particular, it can convert PPM images to and from a wide range of
+ other formats, thus making cjpeg/djpeg considerably more useful. The latest
+ version is distributed by the NetPBM group, and is available from numerous
+ sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
+ Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
+ you are likely to have difficulty making it work on any non-Unix machine.
+
+ A different free JPEG implementation, written by the PVRG group at Stanford,
+ is available from ftp://havefun.stanford.edu/pub/jpeg/. This program
+ is designed for research and experimentation rather than production use;
+ it is slower, harder to use, and less portable than the IJG code, but it
+ is easier to read and modify. Also, the PVRG code supports lossless JPEG,
+ which we do not. (On the other hand, it doesn't do progressive JPEG.)
+
+
+ FILE FORMAT WARS
+ ================
+
+ Some JPEG programs produce files that are not compatible with our library.
+ The root of the problem is that the ISO JPEG committee failed to specify a
+ concrete file format. Some vendors "filled in the blanks" on their own,
+ creating proprietary formats that no one else could read. (For example, none
+ of the early commercial JPEG implementations for the Macintosh were able to
+ exchange compressed files.)
+
+ The file format we have adopted is called JFIF (see REFERENCES). This format
+ has been agreed to by a number of major commercial JPEG vendors, and it has
+ become the de facto standard. JFIF is a minimal or "low end" representation.
+ We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
+ Technical Note #2) for "high end" applications that need to record a lot of
+ additional data about an image. TIFF/JPEG is fairly new and not yet widely
+ supported, unfortunately.
+
+ The upcoming JPEG Part 3 standard defines a file format called SPIFF.
+ SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
+ be able to read the most common variant of SPIFF. SPIFF has some technical
+ advantages over JFIF, but its major claim to fame is simply that it is an
+ official standard rather than an informal one. At this point it is unclear
+ whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
+ standard. IJG intends to support SPIFF once the standard is frozen, but we
+ have not decided whether it should become our default output format or not.
+ (In any case, our decoder will remain capable of reading JFIF indefinitely.)
+
+ Various proprietary file formats incorporating JPEG compression also exist.
+ We have little or no sympathy for the existence of these formats. Indeed,
+ one of the original reasons for developing this free software was to help
+ force convergence on common, open format standards for JPEG files. Don't
+ use a proprietary file format!
+
+
+ TO DO
+ =====
+
+ The major thrust for v7 will probably be improvement of visual quality.
+ The current method for scaling the quantization tables is known not to be
+ very good at low Q values. We also intend to investigate block boundary
+ smoothing, "poor man's variable quantization", and other means of improving
+ quality-vs-file-size performance without sacrificing compatibility.
+
+ In future versions, we are considering supporting some of the upcoming JPEG
+ Part 3 extensions --- principally, variable quantization and the SPIFF file
+ format.
+
+ As always, speeding things up is of great interest.
+
+ Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
+
+************************************************************************************
+Celt Codec:
+************************************************************************************
+
+ Copyright 2001-2009 Jean-Marc Valin, Timothy B. Terriberry,
+ CSIRO, and other contributors
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ - Neither the name of Internet Society, IETF or IETF Trust, nor the
+ names of specific contributors, may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+************************************************************************************
+SPEEX Codes:
+************************************************************************************
+ SPEEX � 2002-2003, Jean-Marc Valin/Xiph.Org Foundation
+ Redistribution and use in source and binary forms, with or without modification, are permitted
+ provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ conditions and the following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the Xiph.org Foundation nor the names of its contributors may be
+ used to endorse or promote products derived from this software without specific prior
+ written permission.
+ This software is provided by the copyright holders and contributors �as is� and any express or
+ implied warranties, including, but not limited to, the implied warranties of merchantability and
+ fitness for a particular purpose are disclaimed. In no event shall the foundation or contributors be
+ liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including,
+ but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or
+ business interruption) however caused and on any theory of liability, whether in contract, strict
+ liability, or tort (including negligence or otherwise) arising in any way out of the use of this
+ software, even if advised of the possibility of such damage.
+
+************************************************************************************
+google-perftools:
+************************************************************************************
+
+ http://code.google.com/p/gperftools/
+
+ Copyright (c) 2012, Google Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ For Google libjingle:
+ http://sourceforge.net/projects/libjingle/
+ Copyright (c) 2004--2005, Google Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+
+************************************************************************************
+CakePHP:
+************************************************************************************
+
+ CakePHP(tm) : Rapid Development Framework
+ Copyright 2005-2007, Cake Software Foundation, Inc.
+ 1785 E. Sahara Avenue, Suite 490-204
+ Las Vegas, Nevada 89104
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+************************************************************************************
+LZMA
+************************************************************************************
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+
+************************************************************************************
+Fast Pow Function
+************************************************************************************
+
+ /*
+ * (c) Ian Stephenson
+ *
+ * ian@dctsystems.co.uk
+ *
+ * Fast pow() reference implementation
+ */
+
+ Used with permission from author
+
+ For libantlr3c:
+ // [The "BSD licence"]
+ // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
+ // http://www.temporal-wave.com
+ // http://www.linkedin.com/in/jimidle
+ //
+ // All rights reserved.
+ //
+ // Redistribution and use in source and binary forms, with or without
+ // modification, are permitted provided that the following conditions
+ // are met:
+ // 1. Redistributions of source code must retain the above copyright
+ // notice, this list of conditions and the following disclaimer.
+ // 2. Redistributions in binary form must reproduce the above copyright
+ // notice, this list of conditions and the following disclaimer in the
+ // documentation and/or other materials provided with the distribution.
+ // 3. The name of the author may not be used to endorse or promote products
+ // derived from this software without specific prior written permission.
+ //
+ // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+************************************************************************************
+Autodesk� FBX�:
+************************************************************************************
+
+ �This software contains Autodesk� FBX� code developed by Autodesk, Inc. Copyright 2012 Autodesk, Inc.
+ All rights, reserved. Such code is provided �as is� and Autodesk, Inc. disclaims any and all warranties,
+ whether express or implied, including without limitation the implied warranties of merchantability, fitness for a
+ particular purpose or non-infringement of third party rights. In no event shall Autodesk, Inc. be liable for any
+ direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to,
+ procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however
+ caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or
+ otherwise) arising in any way out of such code.�
+
+************************************************************************************
+OpenSSL:
+************************************************************************************
+
+ * This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ /* ====================================================================
+ * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be
+ used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ *
+ */
+
+
+ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an
+ acknowledgement:
+ * "This product includes software written by Tim Hudson
+ (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+************************************************************************************
+Google protocol buffers
+************************************************************************************
+
+ // Protocol Buffers - Google's data interchange format
+ // Copyright 2008 Google Inc. All rights reserved.
+ // http://code.google.com/p/protobuf/
+ //
+ // Redistribution and use in source and binary forms, with or without
+ // modification, are permitted provided that the following conditions are
+ // met:
+ //
+ // * Redistributions of source code must retain the above copyright
+ // notice, this list of conditions and the following disclaimer.
+ // * Redistributions in binary form must reproduce the above
+ // copyright notice, this list of conditions and the following disclaimer
+ // in the documentation and/or other materials provided with the
+ // distribution.
+ // * Neither the name of Google Inc. nor the names of its
+ // contributors may be used to endorse or promote products derived from
+ // this software without specific prior written permission.
+ //
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ // Author: kenton@google.com (Kenton Varda)
+ // Based on original Protocol Buffers design by
+ // Sanjay Ghemawat, Jeff Dean, and others.
+
+************************************************************************************
+Google Snappy
+************************************************************************************
+
+ // Copyright 2005 Google Inc. All Rights Reserved.
+ //
+ // Redistribution and use in source and binary forms, with or without
+ // modification, are permitted provided that the following conditions are
+ // met:
+ //
+ // * Redistributions of source code must retain the above copyright
+ // notice, this list of conditions and the following disclaimer.
+ // * Redistributions in binary form must reproduce the above
+ // copyright notice, this list of conditions and the following disclaimer
+ // in the documentation and/or other materials provided with the
+ // distribution.
+ // * Neither the name of Google Inc. nor the names of its
+ // contributors may be used to endorse or promote products derived from
+ // this software without specific prior written permission.
+ //
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+************************************************************************************
+VAudio MiniMP3
+************************************************************************************
+
+Copyright 2022 Joshua Ashton and Josh Dowell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+************************************************************************************
+Godot Engine
+************************************************************************************
+
+Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md).
+Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.vscode/tasks.json b/src/.vscode/tasks.json
new file mode 100644
index 00000000..87e569e8
--- /dev/null
+++ b/src/.vscode/tasks.json
@@ -0,0 +1,23 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Build All Projects",
+ "type": "shell",
+ "command": "./buildallprojects",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": {
+ "base": "$gcc",
+ "fileLocation": ["relative", "${workspaceFolder}"]
+ },
+ "presentation": {
+ "reveal": "always",
+ "panel": "shared"
+ }
+ }
+ ]
+}
+
diff --git a/src/buildallprojects b/src/buildallprojects
new file mode 100755
index 00000000..12c1b83b
--- /dev/null
+++ b/src/buildallprojects
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+set -euo pipefail
+
+script=$(readlink -f -- "$0")
+pushd "$(dirname -- "$script")" > /dev/null
+
+source sdk_container
+run_in_sniper "$@"
+
+if [ $# -eq 0 ]; then
+ export VPC_NINJA_BUILD_MODE="release"
+else
+ if [[ "$1" == "debug" ]]; then
+ export VPC_NINJA_BUILD_MODE="debug"
+ elif [[ "$1" == "release" ]]; then
+ export VPC_NINJA_BUILD_MODE="release"
+ else
+ echo "Usage: $0 [debug|release]"
+ exit 1
+ fi
+fi
+
+solution_out="_vpc_/ninja/sdk_everything_$VPC_NINJA_BUILD_MODE"
+
+if [[ ! -e "$solution_out.ninja" ]]; then
+ devtools/bin/vpc /hl2mp /tf /linux64 /ninja /define:SOURCESDK +everything /mksln "$solution_out"
+
+ # Generate compile commands.
+ ninja -f "$solution_out.ninja" -t compdb > compile_commands.json
+ # Remove some unsupported clang commands.
+ sed -i 's/-fpredictive-commoning//g; s/-fvar-tracking-assignments//g' compile_commands.json
+ sed -i 's|/my_mod/src|.|g' compile_commands.json
+fi
+
+ninja -f "$solution_out.ninja" -j$(nproc)
+
+popd
diff --git a/src/common/GameUI/IGameConsole.h b/src/common/GameUI/IGameConsole.h
new file mode 100644
index 00000000..7fc84db5
--- /dev/null
+++ b/src/common/GameUI/IGameConsole.h
@@ -0,0 +1,45 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef IGAMECONSOLE_H
+#define IGAMECONSOLE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/interface.h"
+
+namespace vgui
+{
+ typedef uintp VPANEL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: interface to game/dev console
+//-----------------------------------------------------------------------------
+abstract_class IGameConsole : public IBaseInterface
+{
+public:
+ // activates the console, makes it visible and brings it to the foreground
+ virtual void Activate() = 0;
+
+ virtual void Initialize() = 0;
+
+ // hides the console
+ virtual void Hide() = 0;
+
+ // clears the console
+ virtual void Clear() = 0;
+
+ // return true if the console has focus
+ virtual bool IsConsoleVisible() = 0;
+
+ virtual void SetParent( vgui::VPANEL parent ) = 0;
+};
+
+#define GAMECONSOLE_INTERFACE_VERSION "GameConsole004"
+
+#endif // IGAMECONSOLE_H
diff --git a/src/common/GameUI/ObjectList.cpp b/src/common/GameUI/ObjectList.cpp
new file mode 100644
index 00000000..7da11005
--- /dev/null
+++ b/src/common/GameUI/ObjectList.cpp
@@ -0,0 +1,243 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#include
+#include
+#include "ObjectList.h"
+#include "tier1/strtools.h"
+
+//#include "port.h"
+//#include "mem.h"
+// memdbgon must be the last include file in a .cpp file!!!
+#include
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+ObjectList::ObjectList()
+{
+ head = tail = current = NULL;
+ number = 0;
+}
+
+ObjectList::~ObjectList()
+{
+ Clear( false );
+}
+
+bool ObjectList::AddHead(void * newObject)
+{
+ // create new element
+ element_t * newElement = (element_t *) calloc(1, sizeof(element_t));
+
+ if (newElement == NULL )
+ return false; // out of memory
+
+ // insert element
+ newElement->object = newObject;
+
+ if (head)
+ {
+ newElement->next = head;
+ head->prev = newElement;
+ };
+
+ head = newElement;
+
+ // if list was empty set new tail
+ if (tail==NULL) tail = head;
+
+ number++;
+
+ return true;
+
+}
+
+void * ObjectList::RemoveHead()
+{
+ void * retObj;
+
+ // check head is present
+ if (head)
+ {
+ retObj = head->object;
+ element_t * newHead = head->next;
+ if (newHead) newHead->prev = NULL;
+
+ // if only one element is in list also update tail
+ // if we remove this prev element
+ if (tail==head) tail = NULL;
+
+ free(head);
+ head = newHead;
+
+ number--;
+
+ } else
+ retObj = NULL;
+
+ return retObj;
+}
+
+bool ObjectList::AddTail(void * newObject)
+{
+ element_t * newElement = (element_t *) calloc(1, sizeof(element_t));
+
+ if (newElement == NULL)
+ return false; // out of memory;
+
+ newElement->object = newObject;
+
+ if (tail)
+ {
+ newElement->prev = tail;
+ tail->next = newElement;
+ }
+
+ tail = newElement;
+
+ // if list was empty set new head
+ if (head==NULL) head = tail;
+
+ number++;
+
+ return true;
+
+}
+
+void * ObjectList::RemoveTail()
+{
+ void * retObj;
+
+ // check tail is present
+ if (tail)
+ {
+ retObj = tail->object;
+ element_t * newTail = tail->prev;
+ if (newTail) newTail->next = NULL;
+
+ // if only one element is in list also update tail
+ // if we remove this prev element
+ if (head==tail) head = NULL;
+
+ free(tail);
+ tail = newTail;
+
+ number--;
+
+ } else
+ retObj = NULL;
+
+ return retObj;
+}
+
+bool ObjectList::IsEmpty()
+{
+ return ( head == NULL );
+}
+
+int ObjectList::CountElements()
+{
+ return number;
+}
+
+bool ObjectList::Contains(void * object)
+{
+ element_t * e = head;
+
+ while(e && e->object!=object) { e = e->next;}
+
+ if ( e )
+ {
+ current = e;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void ObjectList::Clear( bool freeElementsMemory )
+{
+ element_t * ne;
+
+ element_t * e = head;
+ while(e)
+ {
+ ne = e->next;
+
+ if ( freeElementsMemory && e->object )
+ free( e->object );
+
+ free(e);
+ e = ne;
+ }
+
+ head = tail = current = NULL;
+ number = 0;
+
+}
+
+bool ObjectList::Remove( void * object )
+{
+ element_t * e = head;
+
+ while(e && e->object!=object) { e = e->next;}
+
+ if (e!=NULL)
+ {
+ if (e->prev) e->prev->next = e->next;
+ if (e->next) e->next->prev = e->prev;
+ if (head==e) head = e->next;
+ if (tail==e) tail = e->prev;
+ if (current == e) current= e->next;
+ free(e);
+ number--;
+ }
+
+ return (e!=NULL);
+}
+
+void ObjectList::Init()
+{
+ head = tail = current = NULL;
+ number = 0;
+}
+
+void * ObjectList::GetFirst()
+{
+ if (head)
+ {
+ current = head->next;
+ return head->object;
+ }
+ else
+ {
+ current = NULL;
+ return NULL;
+ };
+
+}
+
+void * ObjectList::GetNext()
+{
+ void * retObj = NULL;
+ if (current)
+ {
+ retObj = current->object;
+ current = current->next;
+ }
+ return retObj;
+}
+
+bool ObjectList::Add(void *newObject)
+{
+ return AddTail( newObject );
+}
+
diff --git a/src/common/GameUI/ObjectList.h b/src/common/GameUI/ObjectList.h
new file mode 100644
index 00000000..b52a0cea
--- /dev/null
+++ b/src/common/GameUI/ObjectList.h
@@ -0,0 +1,58 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// ObjectList.h: interface for the ObjectList class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifndef OBJECTLIST_H
+#define OBJECTLIST_H
+
+#pragma once
+
+#include "IObjectContainer.h" // Added by ClassView
+
+class ObjectList : public IObjectContainer
+{
+public:
+ void Init();
+ bool Add( void * newObject );
+ void * GetFirst();
+ void * GetNext();
+
+
+
+ ObjectList();
+ virtual ~ObjectList();
+
+ void Clear( bool freeElementsMemory );
+ int CountElements();
+ void * RemoveTail();
+ void * RemoveHead();
+
+ bool AddTail(void * newObject);
+ bool AddHead(void * newObject);
+ bool Remove(void * object);
+ bool Contains(void * object);
+ bool IsEmpty();
+
+ typedef struct element_s {
+ element_s * prev; // pointer to the last element or NULL
+ element_s * next; // pointer to the next elemnet or NULL
+ void * object; // the element's object
+ } element_t;
+
+protected:
+
+ element_t * head; // first element in list
+ element_t * tail; // last element in list
+ element_t * current; // current element in list
+ int number;
+
+};
+
+#endif // !defined
diff --git a/src/common/GameUI/Random.cpp b/src/common/GameUI/Random.cpp
new file mode 100644
index 00000000..ec179868
--- /dev/null
+++ b/src/common/GameUI/Random.cpp
@@ -0,0 +1,131 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Basic random number generator
+//
+// $NoKeywords: $
+//===========================================================================//
+
+
+#include
+#include "Random.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define IA 16807
+#define IM 2147483647
+#define IQ 127773
+#define IR 2836
+#define NTAB 32
+#define NDIV (1+(IM-1)/NTAB)
+
+static long idum = 0;
+
+void SeedRandomNumberGenerator(long lSeed)
+{
+ if (lSeed)
+ {
+ idum = lSeed;
+ }
+ else
+ {
+ idum = -time(NULL);
+ }
+ if (1000 < idum)
+ {
+ idum = -idum;
+ }
+ else if (-1000 < idum)
+ {
+ idum -= 22261048;
+ }
+}
+
+long ran1(void)
+{
+ int j;
+ long k;
+ static long iy=0;
+ static long iv[NTAB];
+
+ if (idum <= 0 || !iy)
+ {
+ if (-(idum) < 1) idum=1;
+ else idum = -(idum);
+ for (j=NTAB+7;j>=0;j--)
+ {
+ k=(idum)/IQ;
+ idum=IA*(idum-k*IQ)-IR*k;
+ if (idum < 0) idum += IM;
+ if (j < NTAB) iv[j] = idum;
+ }
+ iy=iv[0];
+ }
+ k=(idum)/IQ;
+ idum=IA*(idum-k*IQ)-IR*k;
+ if (idum < 0) idum += IM;
+ j=iy/NDIV;
+ iy=iv[j];
+ iv[j] = idum;
+
+ return iy;
+}
+
+// fran1 -- return a random floating-point number on the interval [0,1)
+//
+#define AM (1.0/IM)
+#define EPS 1.2e-7
+#define RNMX (1.0-EPS)
+float fran1(void)
+{
+ float temp = (float)AM*ran1();
+ if (temp > RNMX) return (float)RNMX;
+ else return temp;
+}
+
+#ifndef _XBOX
+float RandomFloat( float flLow, float flHigh )
+{
+ if (idum == 0)
+ {
+ SeedRandomNumberGenerator(0);
+ }
+
+ float fl = fran1(); // float in [0,1)
+ return (fl * (flHigh-flLow)) + flLow; // float in [low,high)
+}
+#endif
+
+long RandomLong( long lLow, long lHigh )
+{
+ if (idum == 0)
+ {
+ SeedRandomNumberGenerator(0);
+ }
+
+ unsigned long maxAcceptable;
+ unsigned long x = lHigh-lLow+1;
+ unsigned long n;
+ if (x <= 0 || MAX_RANDOM_RANGE < x-1)
+ {
+ return lLow;
+ }
+
+ // The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE]
+ // to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
+ // the uniform distribution unfavorably. Even for a worst case x, the loop is
+ // guaranteed to be taken no more than half the time, so for that worst case x,
+ // the average number of times through the loop is 2. For cases where x is
+ // much smaller than MAX_RANDOM_RANGE, the average number of times through the
+ // loop is very close to 1.
+ //
+ maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
+ do
+ {
+ n = ran1();
+ } while (n > maxAcceptable);
+
+ return lLow + (n % x);
+}
+
+
diff --git a/src/common/GameUI/Random.h b/src/common/GameUI/Random.h
new file mode 100644
index 00000000..90beb783
--- /dev/null
+++ b/src/common/GameUI/Random.h
@@ -0,0 +1,30 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generalized 32-bit random number generator
+// Range is 0x00000000 - 0x7FFFFFFF
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef RANDOM_H
+#define RANDOM_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+// the random number seeding is automatic
+
+#define MAX_RANDOM_RANGE 0x7FFFFFFFUL
+
+// restarts random generator
+// setting lSeed to 0 causes the current time to be used as the seed
+// random number generator will automatically seed itself on first use with current time if this is not called
+extern void SeedRandomNumberGenerator(long lSeed = 0);
+
+// returns a random integer of range [low, high]
+extern long RandomLong( long lLow, long lHigh );
+
+// returns a random float of range [low, high)
+extern float RandomFloat( float flLow, float flHigh );
+
+#endif // RANDOM_H
diff --git a/src/common/GameUI/cvarslider.cpp b/src/common/GameUI/cvarslider.cpp
new file mode 100644
index 00000000..7691f1e2
--- /dev/null
+++ b/src/common/GameUI/cvarslider.cpp
@@ -0,0 +1,334 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#include "cvarslider.h"
+#include
+#include "tier1/KeyValues.h"
+#include "tier1/convar.h"
+#include
+#include
+
+#define CVARSLIDER_SCALE_FACTOR 100.0f
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include
+
+using namespace vgui;
+
+DECLARE_BUILD_FACTORY( CCvarSlider );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CCvarSlider::CCvarSlider( Panel *parent, const char *name ) : Slider( parent, name )
+{
+ SetupSlider( 0, 1, "", false );
+ m_bCreatedInCode = false;
+
+ AddActionSignalTarget( this );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CCvarSlider::CCvarSlider( Panel *parent, const char *panelName, char const *caption,
+ float minValue, float maxValue, char const *cvarname, bool bAllowOutOfRange )
+ : Slider( parent, panelName )
+{
+ AddActionSignalTarget( this );
+
+ SetupSlider( minValue, maxValue, cvarname, bAllowOutOfRange );
+
+ // For backwards compatability. Ignore .res file settings for forced setup sliders.
+ m_bCreatedInCode = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange )
+{
+ // make sure min/max don't go outside cvar range if there's one
+ UIConVarRef var( g_pVGui->GetVGUIEngine(), cvarname, true );
+ if ( var.IsValid() )
+ {
+ float flCVarMin;
+ if ( var.GetMin( flCVarMin ) )
+ {
+ minValue = m_bUseConVarMinMax ? flCVarMin : MAX( minValue, flCVarMin );
+ }
+ float flCVarMax;
+ if ( var.GetMax( flCVarMax ) )
+ {
+ maxValue = m_bUseConVarMinMax ? flCVarMax : MIN( maxValue, flCVarMax );
+ }
+ }
+
+ m_flMinValue = minValue;
+ m_flMaxValue = maxValue;
+
+ // scale by CVARSLIDER_SCALE_FACTOR
+ SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) );
+
+ char szMin[ 32 ];
+ char szMax[ 32 ];
+
+ Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue );
+ Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue );
+
+ SetTickCaptions( szMin, szMax );
+
+ Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) );
+
+ m_bModifiedOnce = false;
+ m_bAllowOutOfRange = bAllowOutOfRange;
+
+ // Set slider to current value
+ Reset();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CCvarSlider::~CCvarSlider()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::ApplySettings( KeyValues *inResourceData )
+{
+ BaseClass::ApplySettings( inResourceData );
+
+ if ( !m_bCreatedInCode )
+ {
+ float minValue = inResourceData->GetFloat( "minvalue", 0 );
+ float maxValue = inResourceData->GetFloat( "maxvalue", 1 );
+ const char *cvarname = inResourceData->GetString( "cvar_name", "" );
+ bool bAllowOutOfRange = inResourceData->GetInt( "allowoutofrange", 0 ) != 0;
+ SetupSlider( minValue, maxValue, cvarname, bAllowOutOfRange );
+
+ if ( GetParent() )
+ {
+ // HACK: If our parent is a property page, we want the dialog containing it
+ if ( dynamic_cast(GetParent()) && GetParent()->GetParent() )
+ {
+ GetParent()->GetParent()->AddActionSignalTarget( this );
+ }
+ else
+ {
+ GetParent()->AddActionSignalTarget( this );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get control settings for editing
+//-----------------------------------------------------------------------------
+void CCvarSlider::GetSettings( KeyValues *outResourceData )
+{
+ BaseClass::GetSettings(outResourceData);
+
+ if ( !m_bCreatedInCode )
+ {
+ outResourceData->SetFloat( "minvalue", m_flMinValue );
+ outResourceData->SetFloat( "maxvalue", m_flMaxValue );
+ outResourceData->SetString( "cvar_name", m_szCvarName );
+ outResourceData->SetInt( "allowoutofrange", m_bAllowOutOfRange );
+ }
+}
+
+void CCvarSlider::SetCVarName( char const *cvarname )
+{
+ Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) );
+
+ m_bModifiedOnce = false;
+
+ // Set slider to current value
+ Reset();
+}
+
+void CCvarSlider::SetMinMaxValues( float minValue, float maxValue, bool bSetTickDisplay )
+{
+ SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) );
+
+ if ( bSetTickDisplay )
+ {
+ char szMin[ 32 ];
+ char szMax[ 32 ];
+
+ Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue );
+ Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue );
+
+
+ SetTickCaptions( szMin, szMax );
+ }
+
+ // Set slider to current value
+ Reset();
+}
+
+void CCvarSlider::SetTickColor( Color color )
+{
+ m_TickColor = color;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::Paint()
+{
+ // Get engine's current value
+// float curvalue = engine->pfnGetCvarFloat( m_szCvarName );
+ UIConVarRef var( g_pVGui->GetVGUIEngine(), m_szCvarName, true );
+ if ( !var.IsValid() )
+ return;
+ float curvalue = var.GetFloat();
+
+ // did it get changed from under us?
+ if (curvalue != m_fStartValue)
+ {
+ int val = (int)( CVARSLIDER_SCALE_FACTOR * curvalue );
+ m_fStartValue = curvalue;
+ m_fCurrentValue = curvalue;
+
+ SetValue( val );
+ m_iStartValue = GetValue();
+ }
+
+ BaseClass::Paint();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::ApplyChanges()
+{
+ if (m_bModifiedOnce)
+ {
+ m_iStartValue = GetValue();
+ if (m_bAllowOutOfRange)
+ {
+ m_fStartValue = m_fCurrentValue;
+ }
+ else
+ {
+ m_fStartValue = (float) m_iStartValue / CVARSLIDER_SCALE_FACTOR;
+ }
+
+ //engine->Cvar_SetValue( m_szCvarName, m_fStartValue );
+ UIConVarRef var( g_pVGui->GetVGUIEngine(), m_szCvarName, true );
+ if ( !var.IsValid() )
+ return;
+ var.SetValue( (float)m_fStartValue );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+float CCvarSlider::GetSliderValue()
+{
+ if (m_bAllowOutOfRange)
+ {
+ return m_fCurrentValue;
+ }
+ else
+ {
+ return ((float)GetValue())/ CVARSLIDER_SCALE_FACTOR;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::SetSliderValue(float fValue)
+{
+ int nVal = (int)( CVARSLIDER_SCALE_FACTOR * fValue );
+ SetValue( nVal, false);
+
+ // remember this slider value
+ m_iLastSliderValue = GetValue();
+
+ if (m_fCurrentValue != fValue)
+ {
+ m_fCurrentValue = fValue;
+ m_bModifiedOnce = true;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::Reset()
+{
+ // Set slider to current value
+// m_fStartValue = engine->pfnGetCvarFloat( m_szCvarName );
+ UIConVarRef var( g_pVGui->GetVGUIEngine(), m_szCvarName, true );
+ if ( !var.IsValid() )
+ {
+ m_fCurrentValue = m_fStartValue = 0.0f;
+ SetValue( 0, false );
+ m_iStartValue = GetValue();
+ m_iLastSliderValue = m_iStartValue;
+ return;
+ }
+ m_fStartValue = var.GetFloat();
+ m_fCurrentValue = m_fStartValue;
+
+ int value = (int)( CVARSLIDER_SCALE_FACTOR * m_fStartValue );
+ SetValue( value, false );
+
+ m_iStartValue = GetValue();
+ m_iLastSliderValue = m_iStartValue;
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CCvarSlider::HasBeenModified()
+{
+ if (GetValue() != m_iStartValue)
+ {
+ m_bModifiedOnce = true;
+ }
+
+ return m_bModifiedOnce;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : position -
+//-----------------------------------------------------------------------------
+void CCvarSlider::OnSliderMoved()
+{
+ if (HasBeenModified())
+ {
+ if (m_iLastSliderValue != GetValue())
+ {
+ m_iLastSliderValue = GetValue();
+ m_fCurrentValue = ((float) m_iLastSliderValue)/CVARSLIDER_SCALE_FACTOR;
+ }
+
+ // tell parent that we've been modified
+ PostActionSignal(new KeyValues("ControlModified"));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvarSlider::OnSliderDragEnd( void )
+{
+ if ( !m_bCreatedInCode )
+ {
+ ApplyChanges();
+ }
+}
\ No newline at end of file
diff --git a/src/common/GameUI/cvarslider.h b/src/common/GameUI/cvarslider.h
new file mode 100644
index 00000000..b03417ab
--- /dev/null
+++ b/src/common/GameUI/cvarslider.h
@@ -0,0 +1,63 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CVARSLIDER_H
+#define CVARSLIDER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include
+
+class CCvarSlider : public vgui::Slider
+{
+ DECLARE_CLASS_SIMPLE( CCvarSlider, vgui::Slider );
+
+public:
+
+ CCvarSlider( vgui::Panel *parent, const char *panelName );
+ CCvarSlider( vgui::Panel *parent, const char *panelName, char const *caption,
+ float minValue, float maxValue, char const *cvarname, bool bAllowOutOfRange=false );
+ ~CCvarSlider();
+
+ void SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange );
+
+ void SetCVarName( char const *cvarname );
+ void SetMinMaxValues( float minValue, float maxValue, bool bSetTickdisplay = true );
+ void SetTickColor( Color color );
+
+ virtual void Paint();
+
+ virtual void ApplySettings( KeyValues *inResourceData );
+ virtual void GetSettings( KeyValues *outResourceData );
+
+ void ApplyChanges();
+ float GetSliderValue();
+ void SetSliderValue(float fValue);
+ void Reset();
+ bool HasBeenModified();
+
+private:
+ MESSAGE_FUNC( OnSliderMoved, "SliderMoved" );
+ MESSAGE_FUNC( OnSliderDragEnd, "SliderDragEnd" );
+
+ CPanelAnimationVar( bool, m_bUseConVarMinMax, "use_convar_minmax", "0" );
+
+ bool m_bAllowOutOfRange;
+ bool m_bModifiedOnce;
+ float m_fStartValue;
+ int m_iStartValue;
+ int m_iLastSliderValue;
+ float m_fCurrentValue;
+ char m_szCvarName[ 64 ];
+
+ bool m_bCreatedInCode;
+ float m_flMinValue;
+ float m_flMaxValue;
+};
+
+#endif // CVARSLIDER_H
diff --git a/src/common/GameUI/scriptobject.cpp b/src/common/GameUI/scriptobject.cpp
new file mode 100644
index 00000000..a59aa055
--- /dev/null
+++ b/src/common/GameUI/scriptobject.cpp
@@ -0,0 +1,1155 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+// CScriptObject and CDescription class definitions
+//
+#include "scriptobject.h"
+#include
+#include
+#include
+#include
+#include "filesystem.h"
+#include "tier1/convar.h"
+#include "cdll_int.h"
+#include "vgui/IVGui.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+static char token[ 1024 ];
+
+extern IVEngineClient *engine;
+
+void StripFloatTrailingZeros(char *str)
+{
+ // scan for a '.'
+ char *period = strchr(str, '.');
+ if (!period)
+ return;
+
+ // start at the end and scan back to the period
+ char *end = 0;
+ for ( end = str + strlen(str) - 1; end > period; --end )
+ {
+ if (*end == '0')
+ {
+ *end = '\0';
+ }
+ else
+ {
+ // we've hit a real value, stop truncating
+ break;
+ }
+ }
+
+ // if we've made it up to the period, kill that to
+ if ( *end == '.' )
+ {
+ *end = '\0';
+ }
+}
+
+/////////////////////
+objtypedesc_t objtypes[] =
+{
+ { O_BOOL , "BOOL" },
+ { O_NUMBER, "NUMBER" },
+ { O_LIST , "LIST" },
+ { O_STRING, "STRING" },
+ { O_OBSOLETE , "OBSOLETE" },
+ { O_SLIDER , "SLIDER" },
+ { O_CATEGORY, "CATEGORY" },
+ { O_BUTTON, "BUTTON" },
+};
+
+mpcontrol_t::mpcontrol_t( Panel *parent, char const *panelName )
+: Panel( parent, panelName )
+{
+ type = O_BADTYPE;
+ pControl = NULL;
+ pPrompt = NULL;
+ pScrObj = NULL;
+
+ next = NULL;
+
+ SetPaintBackgroundEnabled( false );
+}
+
+void mpcontrol_t::OnSizeChanged( int wide, int tall )
+{
+ int inset = 4;
+
+ if ( pPrompt )
+ {
+ int w = wide / 2;
+
+ if ( pControl )
+ {
+ pControl->SetBounds( w + 20, inset, w - 20, tall - 2 * inset );
+ }
+ pPrompt->SetBounds( 0, inset, w + 20, tall - 2 * inset );
+ }
+ else
+ {
+ if ( pControl )
+ {
+ pControl->SetBounds( 0, inset, wide, tall - 2 * inset );
+ }
+ }
+}
+
+CScriptListItem::CScriptListItem()
+{
+ pNext = NULL;
+ memset( szItemText, 0, 128 );
+ memset( szValue, 0, 256 );
+}
+
+CScriptListItem::CScriptListItem( char const *strItem, char const *strValue )
+{
+ pNext = NULL;
+ Q_strncpy( szItemText, strItem, sizeof( szItemText ) );
+ Q_strncpy( szValue , strValue, sizeof( szValue ) );
+}
+
+CScriptObject::CScriptObject( void )
+{
+ type = O_BOOL;
+ bSetInfo = false; // Prepend "Setinfo" to keyvalue pair in config?
+ pNext = NULL;
+ pListItems = NULL;
+ tooltip[0] = '\0';
+}
+
+CScriptObject::~CScriptObject()
+{
+ RemoveAndDeleteAllItems();
+}
+
+void CScriptObject::RemoveAndDeleteAllItems( void )
+{
+ CScriptListItem *p, *n;
+
+ p = pListItems;
+ while ( p )
+ {
+ n = p->pNext;
+ delete p;
+ p = n;
+ }
+ pListItems = NULL;
+}
+
+void CScriptObject::SetCurValue( char const *strValue )
+{
+ Q_strncpy( curValue, strValue, sizeof( curValue ) );
+
+ fcurValue = (float)atof( curValue );
+
+ if ( type == O_NUMBER || type == O_BOOL || type == O_SLIDER )
+ {
+ StripFloatTrailingZeros( curValue );
+ }
+}
+
+void CScriptObject::AddItem( CScriptListItem *pItem )
+{
+ // Link it into the end of the list;
+ CScriptListItem *p;
+ p = pListItems;
+ if ( !p )
+ {
+ pListItems = pItem;
+ pItem->pNext = NULL;
+ return;
+ }
+
+ while ( p )
+ {
+ if ( !p->pNext )
+ {
+ p->pNext = pItem;
+ pItem->pNext = NULL;
+ return;
+ }
+ p = p->pNext;
+ }
+}
+
+/*
+===================
+UTIL_StripInvalidCharacters
+
+Removes any possible formatting codes and double quote characters from the input string
+===================
+*/
+void UTIL_StripInvalidCharacters( char *pszInput, int maxlen )
+{
+ char szOutput[4096];
+ char *pIn, *pOut;
+
+ pIn = pszInput;
+ pOut = szOutput;
+
+ *pOut = '\0';
+
+ while ( *pIn )
+ {
+ if ( ( *pIn != '"' ) &&
+ ( *pIn != '%' ) )
+ {
+ *pOut++ = *pIn;
+ }
+ pIn++;
+ }
+
+ *pOut = '\0';
+
+ // Copy back over, in place
+ Q_strncpy( pszInput, szOutput, maxlen );
+}
+
+void FixupString( char *inString, int maxlen )
+{
+ char szBuffer[ 4096 ];
+ Q_strncpy( szBuffer, inString, sizeof( szBuffer ) );
+ UTIL_StripInvalidCharacters( szBuffer, sizeof( szBuffer ) );
+ Q_strncpy( inString, szBuffer, maxlen );
+}
+
+/*
+===================
+CleanFloat
+
+Removes any ".000" from the end of floats
+===================
+*/
+char * CleanFloat( float val )
+{
+ static int curstring = 0;
+ static char string[2][32];
+ curstring = ( curstring + 1 ) % 2;
+
+ Q_snprintf( string[curstring], sizeof( string[curstring] ), "%f", val );
+
+ char * str = string[curstring];
+
+ char * tmp = str;
+ if ( !str || !*str || !strchr( str, '.' ) )
+ return str;
+
+ while ( *tmp )
+ ++tmp;
+ --tmp;
+
+ while ( *tmp == '0' && tmp > str )
+ {
+ *tmp = 0;
+ --tmp;
+ }
+
+ if ( *tmp == '.' )
+ {
+ *tmp = 0;
+ }
+
+ return str;
+}
+
+void CScriptObject::WriteToScriptFile( FileHandle_t fp )
+{
+ if ( type == O_OBSOLETE )
+ return;
+
+ FixupString( cvarname, sizeof( cvarname ) );
+ g_pFullFileSystem->FPrintf( fp, "\t\"%s\"\r\n", cvarname );
+
+ g_pFullFileSystem->FPrintf( fp, "\t{\r\n" );
+
+ CScriptListItem *pItem;
+
+ FixupString( prompt, sizeof( prompt ) );
+ FixupString( tooltip, sizeof( tooltip ) );
+
+ switch ( type )
+ {
+ case O_BOOL:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[0] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ BOOL }\r\n" );
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%i\" }\r\n", (int)fcurValue ? 1 : 0 );
+ break;
+ case O_NUMBER:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[0] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ NUMBER %s %s }\r\n", CleanFloat(fMin), CleanFloat(fMax) );
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) );
+ break;
+ case O_STRING:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[0] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ STRING }\r\n" );
+ FixupString( curValue, sizeof( curValue ) );
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", curValue );
+ break;
+ case O_LIST:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[0] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{\r\n\t\t\tLIST\r\n" );
+
+ pItem = pListItems;
+ while ( pItem )
+ {
+ UTIL_StripInvalidCharacters( pItem->szItemText, sizeof( pItem->szItemText ) );
+ UTIL_StripInvalidCharacters( pItem->szValue, sizeof( pItem->szValue ) );
+ g_pFullFileSystem->FPrintf( fp, "\t\t\t\"%s\" \"%s\"\r\n",
+ pItem->szItemText, pItem->szValue );
+
+ pItem = pItem->pNext;
+ }
+
+ g_pFullFileSystem->FPrintf( fp, "\t\t}\r\n");
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) );
+ break;
+ case O_SLIDER:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[0] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ SLIDER %s %s }\r\n", CleanFloat(fMin), CleanFloat(fMax) );
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) );
+ break;
+ case O_CATEGORY:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[0] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ CATEGORY }\r\n" );
+ break;
+ case O_BUTTON:
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
+ if ( tooltip[ 0 ] )
+ {
+ g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip );
+ }
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ BUTTON }\r\n" );
+ FixupString( curValue, sizeof( curValue ) );
+ g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", curValue );
+ break;
+ }
+
+ if ( bSetInfo )
+ g_pFullFileSystem->FPrintf( fp, "\t\tSetInfo\r\n" );
+
+ g_pFullFileSystem->FPrintf( fp, "\t}\r\n\r\n" );
+}
+
+void CScriptObject::WriteToFile( FileHandle_t fp )
+{
+ if ( type == O_OBSOLETE || type == O_CATEGORY || type == O_BUTTON )
+ return;
+
+ FixupString( cvarname, sizeof( cvarname ) );
+ g_pFullFileSystem->FPrintf( fp, "\"%s\"\t\t", cvarname );
+
+ CScriptListItem *pItem;
+ float fVal;
+
+ switch ( type )
+ {
+ case O_BOOL:
+ g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", fcurValue != 0.0 ? "1" : "0" );
+ break;
+ case O_NUMBER:
+ case O_SLIDER:
+ fVal = fcurValue;
+ if ( fMin != -1.0 )
+ fVal = max( fVal, fMin );
+ if ( fMax != -1.0 )
+ fVal = min( fVal, fMax );
+ g_pFullFileSystem->FPrintf( fp, "\"%f\"\r\n", fVal );
+ break;
+ case O_STRING:
+ FixupString( curValue, sizeof( curValue ) );
+ g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", curValue );
+ break;
+ case O_LIST:
+ pItem = pListItems;
+ while ( pItem )
+ {
+ if ( !Q_stricmp( pItem->szValue, curValue ) )
+ break;
+
+ pItem = pItem->pNext;
+ }
+
+ if ( pItem )
+ {
+ UTIL_StripInvalidCharacters( pItem->szValue, sizeof( pItem->szValue ) );
+ g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", pItem->szValue );
+ }
+ else //Couln't find index
+ {
+ g_pFullFileSystem->FPrintf( fp, "\"0\"\r\n" );
+ }
+ break;
+ }
+}
+
+void CScriptObject::WriteToConfig( void )
+{
+ if ( type == O_OBSOLETE || type == O_CATEGORY || type == O_BUTTON )
+ return;
+
+ char *pszKey;
+ char szValue[2048];
+
+ pszKey = ( char * )cvarname;
+
+ CScriptListItem *pItem;
+ float fVal;
+
+ switch ( type )
+ {
+ case O_BOOL:
+ Q_snprintf( szValue, sizeof( szValue ), "%s", fcurValue != 0.0 ? "1" : "0" );
+ break;
+ case O_NUMBER:
+ case O_SLIDER:
+ fVal = fcurValue;
+ if ( fMin != -1.0 )
+ fVal = max( fVal, fMin );
+ if ( fMax != -1.0 )
+ fVal = min( fVal, fMax );
+ Q_snprintf( szValue, sizeof( szValue ), "%f", fVal );
+ break;
+ case O_STRING:
+ Q_snprintf( szValue, sizeof( szValue ), "\"%s\"", (char *)curValue );
+ UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) );
+ break;
+ case O_LIST:
+ pItem = pListItems;
+ while ( pItem )
+ {
+ if ( !Q_stricmp( pItem->szValue, curValue ) )
+ break;
+
+ pItem = pItem->pNext;
+ }
+
+ if ( pItem )
+ {
+ Q_snprintf( szValue, sizeof( szValue ), "%s", pItem->szValue );
+ UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) );
+ }
+ else //Couldn't find index
+ {
+ Q_strncpy( szValue, "0", sizeof( szValue ) );
+ }
+ break;
+ }
+
+ char command[ 256 ];
+ if ( bSetInfo )
+ {
+ Q_snprintf( command, sizeof(command), "setinfo %s \"%s\"\n", pszKey, szValue );
+ }
+ else
+ {
+ Q_snprintf( command, sizeof(command), "%s \"%s\"\n", pszKey, szValue );
+ }
+
+ engine->ClientCmd_Unrestricted( command );
+
+ // CFG_SetKey( g_szCurrentConfigFile, pszKey, szValue, bSetInfo );
+}
+
+
+objtype_t CScriptObject::GetType( char *pszType )
+{
+ int i;
+ int nTypes;
+
+ nTypes = sizeof( objtypes ) / sizeof( objtypedesc_t);
+
+ for ( i = 0; i < nTypes; i++ )
+ {
+ if ( !stricmp( objtypes[i].szDescription, pszType ) )
+ return objtypes[i].type;
+ }
+
+ return O_BADTYPE;
+}
+
+bool CScriptObject::ReadFromBuffer( const char **pBuffer, bool isNewObject )
+{
+ // Get the first token.
+ // The cvar we are setting
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( isNewObject )
+ {
+ Q_strncpy( cvarname, token, sizeof( cvarname ) );
+ }
+
+ // Parse the {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( strcmp( token, "{" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ // Parse the Prompt
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( isNewObject )
+ {
+ Q_strncpy( prompt, token, sizeof( prompt ) );
+ }
+
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ // If it's not a {, consider it the optional tooltip
+ if ( strcmp( token, "{" ) )
+ {
+ Q_strncpy( tooltip, token, sizeof( tooltip ) );
+
+ // Parse the next {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+ }
+
+ if ( strcmp( token, "{" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ // Now parse the type:
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ objtype_t newType = GetType( token );
+ if ( isNewObject )
+ {
+ type = newType;
+ }
+ if ( newType == O_BADTYPE )
+ {
+ Msg( "Type '%s' unknown", token );
+ return false;
+ }
+
+ // If it's a category, we're done.
+ if ( newType == O_CATEGORY )
+ {
+ // Parse the }
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+ if ( strcmp( token, "}" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ // Parse the final }
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+ if ( strcmp( token, "}" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+ return true;
+ }
+
+ switch ( newType )
+ {
+ case O_OBSOLETE:
+ case O_BOOL:
+ case O_STRING:
+ case O_BUTTON:
+ // Parse the next {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( strcmp( token, "}" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+ break;
+ case O_NUMBER:
+ case O_SLIDER:
+ // Parse the Min
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( isNewObject )
+ {
+ fMin = (float)atof( token );
+ }
+
+ // Parse the Min
+ *pBuffer = engine->ParseFile( *pBuffer, token , sizeof( token ));
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( isNewObject )
+ {
+ fMax = (float)atof( token );
+ }
+
+ // Parse the next {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( strcmp( token, "}" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+ break;
+ case O_LIST:
+ // Parse items until we get the }
+ while ( 1 )
+ {
+ // Parse the next {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ // Done?
+ if ( !strcmp( token, "}" ) )
+ break;
+
+ //
+ // Add the item to a list somewhere
+ // AddItem( token )
+ char strItem[ 128 ];
+ char strValue[128];
+
+ Q_strncpy( strItem, token, sizeof( strItem ) );
+
+ // Parse the value
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ Q_strncpy( strValue, token, sizeof( strValue ) );
+
+ if ( isNewObject )
+ {
+ CScriptListItem *pItem;
+ pItem = new CScriptListItem( strItem, strValue );
+
+ AddItem( pItem );
+ }
+ }
+ break;
+ }
+
+ //
+ // Now read in the default value
+
+ // Parse the {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( strcmp( token, "{" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ // Parse the default
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ //if ( strlen( token ) <= 0 )
+ // return false;
+
+ // Set the values
+ Q_strncpy( defValue, token, sizeof( defValue ) );
+ fdefValue = (float)atof( token );
+
+ if (type == O_NUMBER || type == O_SLIDER)
+ {
+ StripFloatTrailingZeros( defValue );
+ }
+
+ SetCurValue( defValue );
+
+ // Parse the }
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( strcmp( token, "}" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ // Parse the final }
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( !stricmp( token, "SetInfo" ) )
+ {
+ bSetInfo = true;
+ // Parse the final }
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+ }
+
+ if ( strcmp( token, "}" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ return true;
+}
+
+/////////////////////////
+CDescription::CDescription( void )
+{
+ pObjList = NULL;
+}
+
+CDescription::~CDescription()
+{
+ CScriptObject *p, *n;
+
+ p = pObjList;
+ while ( p )
+ {
+ n = p->pNext;
+ p->pNext = NULL;
+ p->MarkForDeletion();
+ //delete p;
+ p = n;
+ }
+
+ pObjList = NULL;
+
+ if ( m_pszHintText )
+ free( m_pszHintText );
+ if ( m_pszDescriptionType )
+ free( m_pszDescriptionType );
+}
+
+CScriptObject * CDescription::FindObject( const char *pszObjectName )
+{
+ if ( !pszObjectName )
+ return NULL;
+
+ CScriptObject *p;
+ p = pObjList;
+ while ( p )
+ {
+ if ( !stricmp( pszObjectName, p->cvarname ) )
+ return p;
+ p = p->pNext;
+ }
+ return NULL;
+}
+
+void CDescription::AddObject( CScriptObject *pObj )
+{
+ CScriptObject *p;
+ p = pObjList;
+ if ( !p )
+ {
+ pObjList = pObj;
+ pObj->pNext = NULL;
+ return;
+ }
+
+ while ( p )
+ {
+ if ( !p->pNext )
+ {
+ p->pNext = pObj;
+ pObj->pNext = NULL;
+ return;
+ }
+ p = p->pNext;
+ }
+}
+
+bool CDescription::ReadFromBuffer( const char **pBuffer, bool bAllowNewObject )
+{
+ // Get the first token.
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ // Read VERSION #
+ if ( stricmp ( token, "VERSION" ) )
+ {
+ Msg( "Expecting 'VERSION', got '%s'", token );
+ return false;
+ }
+
+ // Parse in the version #
+ // Get the first token.
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ {
+ Msg( "Expecting version #" );
+ return false;
+ }
+
+ float fVer;
+ fVer = (float)atof( token );
+
+ if ( fVer != SCRIPT_VERSION )
+ {
+ Msg( "Version mismatch, expecting %f, got %f", SCRIPT_VERSION, fVer );
+ return false;
+ }
+
+ // Get the "DESCRIPTION"
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ // Read DESCRIPTION
+ if ( stricmp ( token, "DESCRIPTION" ) )
+ {
+ Msg( "Expecting 'DESCRIPTION', got '%s'", token );
+ return false;
+ }
+
+ // Parse in the description type
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ {
+ Msg( "Expecting '%s'", m_pszDescriptionType );
+ return false;
+ }
+
+ if ( stricmp ( token, m_pszDescriptionType ) )
+ {
+ Msg( "Expecting %s, got %s", m_pszDescriptionType, token );
+ return false;
+ }
+
+ // Parse the {
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ if ( strcmp( token, "{" ) )
+ {
+ Msg( "Expecting '{', got '%s'", token );
+ return false;
+ }
+
+ const char *pStart;
+ CScriptObject *pObj;
+ // Now read in the objects and link them in
+ while ( 1 )
+ {
+ pStart = *pBuffer;
+
+ // Get the first token.
+ *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
+ if ( strlen( token ) <= 0 )
+ return false;
+
+ // Read "cvar name" or } when done
+ if ( !stricmp ( token, "}" ) )
+ break;
+
+ // Unget the token
+ *pBuffer = pStart;
+
+ // Create a new object
+ bool mustAdd = bAllowNewObject;
+ pObj = FindObject( token );
+ if ( pObj )
+ {
+ pObj->ReadFromBuffer( &pStart, false );
+ mustAdd = false; // already in list
+ }
+ else
+ {
+ pObj = new CScriptObject();
+ if ( !pObj )
+ {
+ Msg( "Couldn't create script object" );
+ return false;
+ }
+
+ if ( !pObj->ReadFromBuffer( &pStart, true ) )
+ {
+ delete pObj;
+ return false;
+ }
+
+ // throw away the object if we're not adding it.
+ if ( !mustAdd )
+ {
+ delete pObj;
+ }
+ }
+
+ *pBuffer = pStart;
+
+ // Add to list
+ // Fixme, move to end of list first
+ if ( mustAdd )
+ {
+ AddObject( pObj );
+ }
+ }
+
+ return true;
+}
+
+bool CDescription::InitFromFile( const char *pszFileName, bool bAllowNewObject /*= true*/ )
+{
+
+ // Load file into memory
+ FileHandle_t file = g_pFullFileSystem->Open( pszFileName, "rb" );
+ if ( !file )
+ return false;
+
+ int len =g_pFullFileSystem->Size( file );
+
+ // read the file
+ byte *buffer = new unsigned char[ len ];
+ Assert( buffer );
+ g_pFullFileSystem->Read( buffer, len, file );
+ g_pFullFileSystem->Close( file );
+
+ const char *pBuffer = (const char*)buffer;
+
+ ReadFromBuffer( &pBuffer, bAllowNewObject );
+
+ delete[] buffer;
+
+ return true;
+}
+
+void CDescription::WriteToFile( FileHandle_t fp )
+{
+ CScriptObject *pObj;
+
+ WriteFileHeader( fp );
+
+ pObj = pObjList;
+ while ( pObj )
+ {
+ pObj->WriteToFile( fp );
+ pObj = pObj->pNext;
+ }
+}
+
+void CDescription::WriteToConfig( void )
+{
+ CScriptObject *pObj;
+
+ pObj = pObjList;
+ while ( pObj )
+ {
+ pObj->WriteToConfig();
+ pObj = pObj->pNext;
+ }
+}
+
+void CDescription::WriteToScriptFile( FileHandle_t fp )
+{
+ CScriptObject *pObj;
+
+ WriteScriptHeader( fp );
+
+ pObj = pObjList;
+ while ( pObj )
+ {
+ pObj->WriteToScriptFile( fp );
+ pObj = pObj->pNext;
+ }
+
+ g_pFullFileSystem->FPrintf( fp, "}\r\n" );
+}
+
+void CDescription::TransferCurrentValues( const char *pszConfigFile )
+{
+ char szValue[ 1024 ];
+
+ CScriptObject *pObj;
+
+ pObj = pObjList;
+ while ( pObj )
+ {
+
+ /*
+ TODO: if/when prefixed keys are implemented
+ const char *value;
+ if ( pObj->bSetInfo )
+ {
+ value = engine->LocalPlayerInfo_ValueForKey( pObj->cvarname ); // use LocalPlayerInfo because PlayerInfo strips keys prefixed with "_"
+ }
+ else
+ {
+ value = engine->pfnGetCvarString( pObj->cvarname );
+ }
+ */
+
+ UIConVarRef var( g_pVGui->GetVGUIEngine(), pObj->cvarname, true );
+ if ( !var.IsValid() )
+ {
+ if ( pObj->type != O_CATEGORY && pObj->type != O_BUTTON )
+ {
+ DevMsg( "Could not find '%s'\n", pObj->cvarname );
+ }
+ pObj = pObj->pNext;
+ continue;
+ }
+ const char *value = var.GetString();
+
+ if ( value && value[ 0 ] )
+ //if ( CFG_GetValue( pszConfigFile, pObj->cvarname, szValue ) )
+ {
+ Q_strncpy( szValue, value, sizeof( szValue ) );
+
+ // Fill in better default value
+ //
+ Q_strncpy( pObj->curValue, szValue, sizeof( pObj->curValue ) );
+ pObj->fcurValue = (float)atof( szValue );
+
+ Q_strncpy( pObj->defValue, szValue, sizeof( pObj->defValue ) );
+ pObj->fdefValue = (float)atof( szValue );
+ }
+
+ pObj = pObj->pNext;
+ }
+}
+
+void CDescription::setDescription( const char *pszDesc )
+{
+ m_pszDescriptionType = strdup( pszDesc );
+}
+
+void CDescription::setHint( const char *pszHint )
+{
+ m_pszHintText = strdup( pszHint );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor, load/save client settings object
+//-----------------------------------------------------------------------------
+CInfoDescription::CInfoDescription( void )
+ : CDescription( )
+{
+ setHint( "// NOTE: THIS FILE IS AUTOMATICALLY REGENERATED, \r\n\
+//DO NOT EDIT THIS HEADER, YOUR COMMENTS WILL BE LOST IF YOU DO\r\n\
+// User options script\r\n\
+//\r\n\
+// Format:\r\n\
+// Version [float]\r\n\
+// Options description followed by \r\n\
+// Options defaults\r\n\
+//\r\n\
+// Option description syntax:\r\n\
+//\r\n\
+// \"cvar\" { \"Prompt\" { type [ type info ] } { default } }\r\n\
+//\r\n\
+// type = \r\n\
+// BOOL (a yes/no toggle)\r\n\
+// STRING\r\n\
+// NUMBER\r\n\
+// LIST\r\n\
+//\r\n\
+// type info:\r\n\
+// BOOL no type info\r\n\
+// NUMBER min max range, use -1 -1 for no limits\r\n\
+// STRING no type info\r\n\
+// LIST "" delimited list of options value pairs\r\n\
+//\r\n\
+//\r\n\
+// default depends on type\r\n\
+// BOOL is \"0\" or \"1\"\r\n\
+// NUMBER is \"value\"\r\n\
+// STRING is \"value\"\r\n\
+// LIST is \"index\", where index \"0\" is the first element of the list\r\n\r\n\r\n" );
+
+ setDescription( "INFO_OPTIONS" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CInfoDescription::WriteScriptHeader( FileHandle_t fp )
+{
+ char am_pm[] = "AM";
+ tm newtime;
+ VCRHook_LocalTime( &newtime );
+
+ g_pFullFileSystem->FPrintf( fp, (char *)getHint() );
+
+// Write out the comment and Cvar Info:
+ g_pFullFileSystem->FPrintf( fp, "// Half-Life User Info Configuration Layout Script (stores last settings chosen, too)\r\n" );
+ g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", asctime( &newtime ), am_pm );
+ g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
+ g_pFullFileSystem->FPrintf( fp, "VERSION %.1f\r\n\r\n", SCRIPT_VERSION );
+ g_pFullFileSystem->FPrintf( fp, "DESCRIPTION INFO_OPTIONS\r\n{\r\n" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CInfoDescription::WriteFileHeader( FileHandle_t fp )
+{
+ char am_pm[] = "AM";
+ tm newtime;
+ VCRHook_LocalTime( &newtime );
+
+ g_pFullFileSystem->FPrintf( fp, "// Half-Life User Info Configuration Settings\r\n" );
+ g_pFullFileSystem->FPrintf( fp, "// DO NOT EDIT, GENERATED BY HALF-LIFE\r\n" );
+ g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", asctime( &newtime ), am_pm );
+ g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
+}
+
+//-----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/src/common/GameUI/scriptobject.h b/src/common/GameUI/scriptobject.h
new file mode 100644
index 00000000..1e3e3105
--- /dev/null
+++ b/src/common/GameUI/scriptobject.h
@@ -0,0 +1,156 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef SCRIPTOBJECT_H
+#define SCRIPTOBJECT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include
+
+class CPanelListPanel;
+
+#define SCRIPT_VERSION 1.0f
+
+typedef void * FileHandle_t;
+
+enum objtype_t
+{
+ O_BADTYPE,
+ O_BOOL,
+ O_NUMBER,
+ O_LIST,
+ O_STRING,
+ O_OBSOLETE,
+ O_SLIDER,
+ O_CATEGORY,
+ O_BUTTON,
+};
+
+typedef struct
+{
+ objtype_t type;
+ char szDescription[32];
+} objtypedesc_t;
+
+class CScriptListItem
+{
+public:
+ CScriptListItem();
+ CScriptListItem( char const *strItem, char const *strValue );
+
+ char szItemText[128];
+ char szValue[256];
+
+ CScriptListItem *pNext;
+};
+
+class CScriptObject : public vgui::Panel
+{
+public:
+ void AddItem( CScriptListItem *pItem );
+ void RemoveAndDeleteAllItems( void );
+ CScriptObject( void );
+ ~CScriptObject();
+
+ bool ReadFromBuffer( const char **pBuffer, bool isNewObject );
+ void WriteToConfig();
+ void WriteToFile( FileHandle_t fp );
+ void WriteToScriptFile( FileHandle_t fp );
+ void SetCurValue( char const *strValue );
+
+ objtype_t GetType( char *pszType );
+
+ objtype_t type;
+
+ char cvarname[64 ];
+ char prompt[ 256 ];
+ char tooltip[ 256 ];
+
+ CScriptListItem *pListItems;
+
+ float fMin, fMax;
+
+ char defValue[ 128 ]; // Default value string
+ float fdefValue; // Float version of default value.
+
+ char curValue[ 128 ];
+ float fcurValue;
+
+ bool bSetInfo; // Prepend "Setinfo" to keyvalue pair in config?
+ // Linked list of default list box items.
+
+ CScriptObject *pNext;
+};
+
+abstract_class CDescription
+{
+public:
+ CDescription( void );
+ virtual ~CDescription();
+
+ bool ReadFromBuffer( const char **pBuffer, bool bAllowNewObject );
+ bool InitFromFile( const char *pszFileName, bool bAllowNewObject = true );
+ void TransferCurrentValues( const char *pszConfigFile );
+
+ void AddObject( CScriptObject *pItem );
+ void WriteToConfig();
+ void WriteToFile( FileHandle_t fp );
+ void WriteToScriptFile( FileHandle_t fp );
+
+ virtual void WriteScriptHeader( FileHandle_t fp ) = 0; // Clients must implement this.
+ virtual void WriteFileHeader( FileHandle_t fp ) = 0; // Clients must implement this.
+
+ void setDescription( const char *pszDesc );
+ void setHint( const char *pszHint );
+
+ const char *GetDescription( void ) { return m_pszDescriptionType; };
+ const char *getHint( void ) { return m_pszHintText; } ;
+public:
+ CScriptObject *pObjList;
+ CScriptObject *FindObject( const char *pszObjectName );
+
+private:
+
+ char *m_pszHintText;
+ char *m_pszDescriptionType;
+};
+
+namespace vgui
+{
+ class Label;
+ class Panel;
+}
+
+class mpcontrol_t : public vgui::Panel
+{
+public:
+ mpcontrol_t( vgui::Panel *parent, char const *panelName );
+
+ virtual void OnSizeChanged( int wide, int tall ) OVERRIDE;
+
+ objtype_t type;
+ vgui::Panel *pControl;
+ vgui::Label *pPrompt;
+ CScriptObject *pScrObj;
+
+ mpcontrol_t *next;
+};
+
+class CInfoDescription : public CDescription
+{
+public:
+ CInfoDescription( void );
+
+ virtual void WriteScriptHeader( FileHandle_t fp ) OVERRIDE;
+ virtual void WriteFileHeader( FileHandle_t fp ) OVERRIDE;
+};
+
+void UTIL_StripInvalidCharacters( char *pszInput, int maxlen );
+
+#endif // SCRIPTOBJECT_H
diff --git a/src/common/ServerBrowser/IServerBrowser.h b/src/common/ServerBrowser/IServerBrowser.h
new file mode 100644
index 00000000..32d1b448
--- /dev/null
+++ b/src/common/ServerBrowser/IServerBrowser.h
@@ -0,0 +1,57 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef ISERVERBROWSER_H
+#define ISERVERBROWSER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "interface.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Interface to server browser module
+//-----------------------------------------------------------------------------
+abstract_class IServerBrowser
+{
+public:
+ // activates the server browser window, brings it to the foreground
+ virtual bool Activate() = 0;
+
+ // joins a game directly
+ virtual bool JoinGame( uint32 unGameIP, uint16 usGamePort, const char *pszConnectCode ) = 0;
+
+ // joins a specified game - game info dialog will only be opened if the server is fully or passworded
+ virtual bool JoinGame( uint64 ulSteamIDFriend, const char *pszConnectCode ) = 0;
+
+ // opens a game info dialog to watch the specified server; associated with the friend 'userName'
+ virtual bool OpenGameInfoDialog( uint64 ulSteamIDFriend, const char *pszConnectCode ) = 0;
+
+ // forces the game info dialog closed
+ virtual void CloseGameInfoDialog( uint64 ulSteamIDFriend ) = 0;
+
+ // closes all the game info dialogs
+ virtual void CloseAllGameInfoDialogs() = 0;
+
+ /// Given a map name, strips off some stuff and returns the "friendly" name of the map.
+ /// Returns the cleaned out map name into the caller's buffer, and returns the friendly
+ /// game type name.
+ virtual const char *GetMapFriendlyNameAndGameType( const char *pszMapName, char *szFriendlyMapName, int cchFriendlyName ) = 0;
+
+ // Enable filtering of workshop maps, requires the game/tool loading us to feed subscription data. This is a
+ // slightly ugly workaround to TF2 not yet having native workshop UI in quickplay, once that is in place this should
+ // either be stripped back out or expanded to be directly aware of the steam workshop without being managed.
+ virtual void SetWorkshopEnabled( bool bManaged ) = 0;
+ virtual void AddWorkshopSubscribedMap( const char *pszMapName ) = 0;
+ virtual void RemoveWorkshopSubscribedMap( const char *pszMapName ) = 0;
+};
+
+#define SERVERBROWSER_INTERFACE_VERSION "ServerBrowser005"
+
+
+
+#endif // ISERVERBROWSER_H
diff --git a/src/common/ServerBrowser/blacklisted_server_manager.cpp b/src/common/ServerBrowser/blacklisted_server_manager.cpp
new file mode 100644
index 00000000..95fcbfc9
--- /dev/null
+++ b/src/common/ServerBrowser/blacklisted_server_manager.cpp
@@ -0,0 +1,290 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+//#include "..\..\serverbrowser\pch_serverbrowser.h"
+
+#undef _snprintf // needed since matchmakingtypes.h inlines a bare _snprintf
+
+#include "convar.h"
+#include "KeyValues.h"
+#include "filesystem.h"
+#include "steam/steamclientpublic.h"
+#include "steam/matchmakingtypes.h"
+#include
+#include "blacklisted_server_manager.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CBlacklistedServerManager::CBlacklistedServerManager()
+{
+ m_iNextServerID = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Reset the list of blacklisted servers to empty.
+//-----------------------------------------------------------------------------
+void CBlacklistedServerManager::Reset( void )
+{
+ m_Blacklist.RemoveAll();
+ m_iNextServerID = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Appends all the servers inside the specified file to the blacklist.
+// Returns count of appended servers, zero for failure.
+//-----------------------------------------------------------------------------
+int CBlacklistedServerManager::LoadServersFromFile( const char *pszFilename, bool bResetTimes )
+{
+ KeyValues *pKV = new KeyValues( "serverblacklist" );
+ if ( !pKV->LoadFromFile( g_pFullFileSystem, pszFilename, "MOD" ) )
+ return 0;
+
+ int count = 0;
+
+ for ( KeyValues *pData = pKV->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
+ {
+ const char *pszName = pData->GetString( "name" );
+
+ uint32 ulDate = pData->GetInt( "date" );
+ if ( bResetTimes )
+ {
+ time_t today;
+ time( &today );
+ ulDate = today;
+ }
+
+ const char *pszNetAddr = pData->GetString( "addr" );
+ if ( pszNetAddr && pszNetAddr[0] && pszName && pszName[0] )
+ {
+ int iIdx = m_Blacklist.AddToTail();
+
+ m_Blacklist[iIdx].m_nServerID = m_iNextServerID++;
+ V_strncpy( m_Blacklist[iIdx].m_szServerName, pszName, sizeof( m_Blacklist[iIdx].m_szServerName ) );
+ m_Blacklist[iIdx].m_ulTimeBlacklistedAt = ulDate;
+ m_Blacklist[iIdx].m_NetAdr.SetFromString( pszNetAddr );
+
+ ++count;
+ }
+ }
+
+ pKV->deleteThis();
+
+ return count;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: save blacklist to disk
+//-----------------------------------------------------------------------------
+void CBlacklistedServerManager::SaveToFile( const char *pszFilename )
+{
+ KeyValues *pKV = new KeyValues( "serverblacklist" );
+
+ for ( int i = 0; i < m_Blacklist.Count(); i++ )
+ {
+ KeyValues *pSubKey = new KeyValues( "server" );
+ pSubKey->SetString( "name", m_Blacklist[i].m_szServerName );
+ pSubKey->SetInt( "date", m_Blacklist[i].m_ulTimeBlacklistedAt );
+ pSubKey->SetString( "addr", m_Blacklist[i].m_NetAdr.ToString() );
+ pKV->AddSubKey( pSubKey );
+ }
+
+ pKV->SaveToFile( g_pFullFileSystem, pszFilename, "MOD" );
+
+ pKV->deleteThis();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Add the given server to the blacklist. Return added server.
+//-----------------------------------------------------------------------------
+blacklisted_server_t *CBlacklistedServerManager::AddServer( gameserveritem_t &server )
+{
+ // Make sure we don't already have this IP in the list somewhere
+ netadr_t netAdr( server.m_NetAdr.GetIP(), server.m_NetAdr.GetConnectionPort() );
+
+ // Don't let them add reserved addresses to their blacklists
+ if ( netAdr.IsReservedAdr() )
+ return NULL;
+
+ int iIdx = m_Blacklist.AddToTail();
+ V_strncpy( m_Blacklist[iIdx].m_szServerName, server.GetName(), sizeof( m_Blacklist[iIdx].m_szServerName ) );
+
+ time_t today;
+ time( &today );
+ m_Blacklist[iIdx].m_ulTimeBlacklistedAt = today;
+ m_Blacklist[iIdx].m_NetAdr = netAdr;
+ m_Blacklist[iIdx].m_nServerID = m_iNextServerID++;
+
+ return &m_Blacklist[iIdx];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Add the given server to the blacklist. Return added server.
+//-----------------------------------------------------------------------------
+blacklisted_server_t *CBlacklistedServerManager::AddServer( const char *serverName, uint32 serverIP, int serverPort )
+{
+ netadr_t netAdr( serverIP, serverPort );
+
+ // Don't let them add reserved addresses to their blacklists
+ if ( netAdr.IsReservedAdr() )
+ return NULL;
+
+ int iIdx = m_Blacklist.AddToTail();
+
+ V_strncpy( m_Blacklist[iIdx].m_szServerName, serverName, sizeof( m_Blacklist[iIdx].m_szServerName ) );
+
+ time_t today;
+ time( &today );
+ m_Blacklist[iIdx].m_ulTimeBlacklistedAt = today;
+
+ m_Blacklist[iIdx].m_NetAdr = netAdr;
+ m_Blacklist[iIdx].m_nServerID = m_iNextServerID++;
+
+ return &m_Blacklist[iIdx];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Add the given server to the blacklist. Return added server.
+//-----------------------------------------------------------------------------
+blacklisted_server_t *CBlacklistedServerManager::AddServer( const char *serverName, const char *netAddressString, uint32 timestamp )
+{
+ netadr_t netAdr( netAddressString );
+
+ // Don't let them add reserved addresses to their blacklists
+ if ( netAdr.IsReservedAdr() )
+ return NULL;
+
+ int iIdx = m_Blacklist.AddToTail();
+
+ V_strncpy( m_Blacklist[iIdx].m_szServerName, serverName, sizeof( m_Blacklist[iIdx].m_szServerName ) );
+ m_Blacklist[iIdx].m_ulTimeBlacklistedAt = timestamp;
+ m_Blacklist[iIdx].m_NetAdr = netAdr;
+ m_Blacklist[iIdx].m_nServerID = m_iNextServerID++;
+
+ return &m_Blacklist[iIdx];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove server with matching 'server id' from list
+//-----------------------------------------------------------------------------
+void CBlacklistedServerManager::RemoveServer( int iServerID )
+{
+ for ( int i = 0; i < m_Blacklist.Count(); i++ )
+ {
+ if ( m_Blacklist[i].m_nServerID == iServerID )
+ {
+ m_Blacklist.Remove(i);
+ break;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Given a serverID, return its blacklist entry
+//-----------------------------------------------------------------------------
+blacklisted_server_t *CBlacklistedServerManager::GetServer( int iServerID )
+{
+ for ( int i = 0; i < m_Blacklist.Count(); i++ )
+ {
+ if ( m_Blacklist[i].m_nServerID == iServerID )
+ return &m_Blacklist[i];
+ }
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns true if given server is blacklisted
+//-----------------------------------------------------------------------------
+bool CBlacklistedServerManager::IsServerBlacklisted( const gameserveritem_t &server ) const
+{
+ return IsServerBlacklisted( server.m_NetAdr.GetIP(), server.m_NetAdr.GetConnectionPort(), server.GetName() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns true if given server is blacklisted
+//-----------------------------------------------------------------------------
+bool CBlacklistedServerManager::IsServerBlacklisted( uint32 serverIP, int serverPort, const char *serverName ) const
+{
+ netadr_t netAdr( serverIP, serverPort );
+
+ ConVarRef sb_showblacklists( "sb_showblacklists" );
+
+ for ( int i = 0; i < m_Blacklist.Count(); i++ )
+ {
+ if ( m_Blacklist[i].m_NetAdr.ip[3] == 0 )
+ {
+ if ( m_Blacklist[i].m_NetAdr.CompareClassCAdr( netAdr ) )
+ {
+ if ( sb_showblacklists.IsValid() && sb_showblacklists.GetBool() )
+ {
+ Msg( "Blacklisted '%s' (%s), due to rule '%s' (Class C).\n", serverName, netAdr.ToString(), m_Blacklist[i].m_NetAdr.ToString() );
+ }
+ return true;
+ }
+ }
+ else
+ {
+ if ( m_Blacklist[i].m_NetAdr.CompareAdr( netAdr, (m_Blacklist[i].m_NetAdr.GetPort() == 0) ) )
+ {
+ if ( sb_showblacklists.IsValid() && sb_showblacklists.GetBool() )
+ {
+ Msg( "Blacklisted '%s' (%s), due to rule '%s'.\n", serverName, netAdr.ToString(), m_Blacklist[i].m_NetAdr.ToString() );
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns true if the given server is allowed to be blacklisted at all
+//-----------------------------------------------------------------------------
+bool CBlacklistedServerManager::CanServerBeBlacklisted( gameserveritem_t &server ) const
+{
+ return CanServerBeBlacklisted( server.m_NetAdr.GetIP(), server.m_NetAdr.GetConnectionPort(), server.GetName() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns true if the given server is allowed to be blacklisted at all
+//-----------------------------------------------------------------------------
+bool CBlacklistedServerManager::CanServerBeBlacklisted( uint32 serverIP, int serverPort, const char *serverName ) const
+{
+ netadr_t netAdr( serverIP, serverPort );
+
+ if ( !netAdr.IsValid() )
+ return false;
+
+ // Don't let them add reserved addresses to their blacklists
+ if ( netAdr.IsReservedAdr() )
+ return false;
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns vector of blacklisted servers
+//-----------------------------------------------------------------------------
+const CUtlVector< blacklisted_server_t > &CBlacklistedServerManager::GetServerVector( void ) const
+{
+ return m_Blacklist;
+}
diff --git a/src/common/ServerBrowser/blacklisted_server_manager.h b/src/common/ServerBrowser/blacklisted_server_manager.h
new file mode 100644
index 00000000..cd8173fd
--- /dev/null
+++ b/src/common/ServerBrowser/blacklisted_server_manager.h
@@ -0,0 +1,74 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#ifndef BLACKLISTEDSERVERMANAGER_H
+#define BLACKLISTEDSERVERMANAGER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "platform.h"
+#include "netadr.h"
+#include "utlvector.h"
+
+#define BLACKLIST_DEFAULT_SAVE_FILE "cfg/server_blacklist.txt"
+
+class gameserveritem_t;
+
+struct blacklisted_server_t
+{
+ int m_nServerID;
+ char m_szServerName[64];
+ uint32 m_ulTimeBlacklistedAt;
+ netadr_t m_NetAdr;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Collection of blacklisted servers
+//-----------------------------------------------------------------------------
+class CBlacklistedServerManager
+{
+public:
+ CBlacklistedServerManager();
+
+ void Reset( void );
+
+ blacklisted_server_t *AddServer( gameserveritem_t &server );
+ blacklisted_server_t *AddServer( const char *serverName, uint32 serverIP, int serverPort );
+ blacklisted_server_t *AddServer( const char *serverName, const char *netAddressString, uint32 timestamp );
+
+ void RemoveServer( int iServerID ); // remove server with matching 'server id' from list
+
+ void SaveToFile( const char *filename );
+ int LoadServersFromFile( const char *pszFilename, bool bResetTimes ); // returns count of appended servers, zero for failure
+
+ blacklisted_server_t *GetServer( int iServerID ); // return server with matching 'server id'
+ int GetServerCount( void ) const;
+
+ const CUtlVector< blacklisted_server_t > &GetServerVector( void ) const;
+
+ bool IsServerBlacklisted( const gameserveritem_t &server ) const;
+ bool IsServerBlacklisted( uint32 serverIP, int serverPort, const char *serverName ) const;
+
+ bool CanServerBeBlacklisted( gameserveritem_t &server ) const;
+ bool CanServerBeBlacklisted( uint32 serverIP, int serverPort, const char *serverName ) const;
+
+private:
+ CUtlVector< blacklisted_server_t > m_Blacklist;
+ int m_iNextServerID; // for vgui use
+};
+
+inline int CBlacklistedServerManager::GetServerCount( void ) const
+{
+ return m_Blacklist.Count();
+}
+
+
+
+
+#endif // BLACKLISTEDSERVERMANAGER_H
diff --git a/src/common/compiledcaptionswap.cpp b/src/common/compiledcaptionswap.cpp
index 494cd698..de751b67 100644
--- a/src/common/compiledcaptionswap.cpp
+++ b/src/common/compiledcaptionswap.cpp
@@ -100,4 +100,4 @@ int UpdateOrCreateCaptionFile( const char *pSourceName, char *pTargetName, int m
{
return ::UpdateOrCreate( pSourceName, pTargetName, maxLen, "GAME", CaptionCreateCallback, bForce );
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/common/imageutils.cpp b/src/common/imageutils.cpp
new file mode 100644
index 00000000..6038ad5b
--- /dev/null
+++ b/src/common/imageutils.cpp
@@ -0,0 +1,2144 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// NOTE: To make use of this file, g_pFullFileSystem must be defined, or you can modify
+// this source to take an IFileSystem * as input.
+//
+//=======================================================================================//
+
+// @note Tom Bui: we need to use fopen below in the jpeg code, so we can't have this on...
+#ifdef PROTECTED_THINGS_ENABLE
+#if !defined( POSIX )
+#undef fopen
+#endif // POSIX
+#endif
+
+#if defined( WIN32 ) && !defined( _X360 )
+#include // SRC only!!
+#elif defined( POSIX )
+#include
+#include
+#ifdef OSX
+#include
+#endif
+#endif
+
+#include "imageutils.h"
+#include "filesystem.h"
+#include "utlbuffer.h"
+#include "bitmap/bitmap.h"
+#include "vtf/vtf.h"
+
+// clang3 on OSX folks the attribute into the prototype, causing a compile failure
+// filed radar bug 10397783
+#if ( __clang_major__ == 3 )
+#include
+extern void longjmp( jmp_buf, int ) __attribute__((noreturn));
+#endif
+
+
+#ifdef ENGINE_DLL
+ #include "common.h"
+#elif CLIENT_DLL
+ // @note Tom Bui: instead of forcing the project to include EngineInterface.h...
+ #include "cdll_int.h"
+ // engine interface singleton accessors
+ extern IVEngineClient *engine;
+ extern class IGameUIFuncs *gameuifuncs;
+ extern class IEngineSound *enginesound;
+ extern class IXboxSystem *xboxsystem;
+ extern class IAchievementMgr *achievementmgr;
+ extern class CSteamAPIContext *steamapicontext;
+#elif REPLAY_DLL
+ #include "replay/ienginereplay.h"
+ extern IEngineReplay *g_pEngine;
+#elif ENGINE_DLL
+ #include "EngineInterface.h"
+#else
+ #include "cdll_int.h"
+ extern IVEngineClient *engine;
+#endif
+
+// use the JPEGLIB_USE_STDIO define so that we can read in jpeg's from outside the game directory tree.
+#define JPEGLIB_USE_STDIO
+#include "jpeglib/jpeglib.h"
+#undef JPEGLIB_USE_STDIO
+
+#include "../thirdparty/libspng/spng/spng.h"
+
+#include
+
+#include "bitmap/tgawriter.h"
+#include "ivtex.h"
+#ifdef WIN32
+#include
+#endif
+#ifdef OSX
+#include
+#endif
+
+#ifndef WIN32
+#define DeleteFile(s) remove(s)
+#endif
+
+#if defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#endif
+
+
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+struct ValveJpegErrorHandler_t
+{
+ // The default manager
+ struct jpeg_error_mgr m_Base;
+ // For handling any errors
+ jmp_buf m_ErrorContext;
+};
+
+#define JPEG_OUTPUT_BUF_SIZE 4096
+
+struct JPEGDestinationManager_t
+{
+ struct jpeg_destination_mgr pub; // public fields
+
+ CUtlBuffer *pBuffer; // target/final buffer
+ byte *buffer; // start of temp buffer
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: We'll override the default error handler so we can deal with errors without having to exit the engine
+//-----------------------------------------------------------------------------
+static void ValveJpegErrorHandler( j_common_ptr cinfo )
+{
+ ValveJpegErrorHandler_t *pError = reinterpret_cast< ValveJpegErrorHandler_t * >( cinfo->err );
+
+ char buffer[ JMSG_LENGTH_MAX ];
+
+ /* Create the message */
+ ( *cinfo->err->format_message )( cinfo, buffer );
+
+ Warning( "%s\n", buffer );
+
+ // Bail
+ longjmp( pError->m_ErrorContext, 1 );
+}
+
+
+// convert the JPEG file given to a TGA file at the given output path.
+ConversionErrorType ImgUtl_ConvertJPEGToTGA( const char *jpegpath, const char *tgaPath, bool bRequirePowerOfTwo )
+{
+#if !defined( _X360 )
+
+ //
+ // !FIXME! This really probably should use ImgUtl_ReadJPEGAsRGBA, to avoid duplicated code.
+ //
+
+ struct jpeg_decompress_struct jpegInfo;
+ struct ValveJpegErrorHandler_t jerr;
+ JSAMPROW row_pointer[1];
+ int row_stride;
+ int cur_row = 0;
+
+ // image attributes
+ int image_height;
+ int image_width;
+
+ // open the jpeg image file.
+ FILE *infile = fopen(jpegpath, "rb");
+ if (infile == NULL)
+ {
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ // setup error to print to stderr.
+ jpegInfo.err = jpeg_std_error(&jerr.m_Base);
+
+ jpegInfo.err->error_exit = &ValveJpegErrorHandler;
+
+ // create the decompress struct.
+ jpeg_create_decompress(&jpegInfo);
+
+ if ( setjmp( jerr.m_ErrorContext ) )
+ {
+ // Get here if there is any error
+ jpeg_destroy_decompress( &jpegInfo );
+
+ fclose(infile);
+
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ jpeg_stdio_src(&jpegInfo, infile);
+
+ // read in the jpeg header and make sure that's all good.
+ if (jpeg_read_header(&jpegInfo, TRUE) != JPEG_HEADER_OK)
+ {
+ fclose(infile);
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ // start the decompress with the jpeg engine.
+ if ( !jpeg_start_decompress(&jpegInfo) )
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose(infile);
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ // Check for valid width and height (ie. power of 2 and print out an error and exit if not).
+ if ( ( bRequirePowerOfTwo && ( !IsPowerOfTwo(jpegInfo.image_height) || !IsPowerOfTwo(jpegInfo.image_width) ) )
+ || jpegInfo.output_components != 3 )
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose( infile );
+ return CE_SOURCE_FILE_SIZE_NOT_SUPPORTED;
+ }
+
+ // now that we've started the decompress with the jpeg lib, we have the attributes of the
+ // image ready to be read out of the decompress struct.
+ row_stride = jpegInfo.output_width * jpegInfo.output_components;
+ image_height = jpegInfo.image_height;
+ image_width = jpegInfo.image_width;
+ int mem_required = jpegInfo.image_height * jpegInfo.image_width * jpegInfo.output_components;
+
+ // allocate the memory to read the image data into.
+ unsigned char *buf = (unsigned char *)malloc(mem_required);
+ if (buf == NULL)
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose(infile);
+ return CE_MEMORY_ERROR;
+ }
+
+ // read in all the scan lines of the image into our image data buffer.
+ bool working = true;
+ while (working && (jpegInfo.output_scanline < jpegInfo.output_height))
+ {
+ row_pointer[0] = &(buf[cur_row * row_stride]);
+ if ( !jpeg_read_scanlines(&jpegInfo, row_pointer, 1) )
+ {
+ working = false;
+ }
+ ++cur_row;
+ }
+
+ if (!working)
+ {
+ free(buf);
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose(infile);
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ jpeg_finish_decompress(&jpegInfo);
+
+ fclose(infile);
+
+ // ok, at this point we have read in the JPEG image to our buffer, now we need to write it out as a TGA file.
+ CUtlBuffer outBuf;
+ bool bRetVal = TGAWriter::WriteToBuffer( buf, outBuf, image_width, image_height, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 );
+ if ( bRetVal )
+ {
+ if ( !g_pFullFileSystem->WriteFile( tgaPath, NULL, outBuf ) )
+ {
+ bRetVal = false;
+ }
+ }
+
+ free(buf);
+ return bRetVal ? CE_SUCCESS : CE_ERROR_WRITING_OUTPUT_FILE;
+
+#else
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+#endif
+}
+
+// convert the bmp file given to a TGA file at the given destination path.
+ConversionErrorType ImgUtl_ConvertBMPToTGA(const char *bmpPath, const char *tgaPath)
+{
+ if ( !IsPC() )
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+
+#ifdef WIN32
+
+ int nWidth, nHeight;
+ ConversionErrorType result;
+ unsigned char *pBufRGBA = ImgUtl_ReadBMPAsRGBA( bmpPath, nWidth, nHeight, result );
+ if ( result != CE_SUCCESS)
+ {
+ Assert( !pBufRGBA );
+ free( pBufRGBA );
+ return result;
+ }
+ Assert( pBufRGBA );
+
+ // write out the TGA file using the RGB data buffer.
+ CUtlBuffer outBuf;
+ bool retval = TGAWriter::WriteToBuffer(pBufRGBA, outBuf, nWidth, nHeight, IMAGE_FORMAT_RGBA8888, IMAGE_FORMAT_RGB888);
+ free( pBufRGBA );
+
+ if ( retval )
+ {
+ if ( !g_pFullFileSystem->WriteFile( tgaPath, NULL, outBuf ) )
+ {
+ retval = false;
+ }
+ }
+
+ return retval ? CE_SUCCESS : CE_ERROR_WRITING_OUTPUT_FILE;
+
+#else // WIN32
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+#endif
+}
+
+unsigned char *ImgUtl_ReadVTFAsRGBA( const char *vtfPath, int &width, int &height, ConversionErrorType &errcode )
+{
+ // Just load the whole file into a memory buffer
+ CUtlBuffer bufFileContents;
+ if ( !g_pFullFileSystem->ReadFile( vtfPath, NULL, bufFileContents ) )
+ {
+ errcode = CE_CANT_OPEN_SOURCE_FILE;
+ return NULL;
+ }
+
+ IVTFTexture *pVTFTexture = CreateVTFTexture();
+ if ( !pVTFTexture->Unserialize( bufFileContents ) )
+ {
+ DestroyVTFTexture( pVTFTexture );
+ errcode = CE_ERROR_PARSING_SOURCE;
+ return NULL;
+ }
+
+ width = pVTFTexture->Width();
+ height = pVTFTexture->Height();
+ pVTFTexture->ConvertImageFormat( IMAGE_FORMAT_RGBA8888, false );
+
+ int nMemSize = ImageLoader::GetMemRequired( width, height, 1, IMAGE_FORMAT_RGBA8888, false );
+ unsigned char *pMemImage = (unsigned char *)malloc(nMemSize);
+ if ( pMemImage == NULL )
+ {
+ DestroyVTFTexture( pVTFTexture );
+ errcode = CE_MEMORY_ERROR;
+ return NULL;
+ }
+ Q_memcpy( pMemImage, pVTFTexture->ImageData(), nMemSize );
+
+ DestroyVTFTexture( pVTFTexture );
+
+ errcode = CE_SUCCESS;
+ return pMemImage;
+}
+
+// read a TGA header from the current point in the file stream.
+static void ImgUtl_ReadTGAHeader(FILE *infile, TGAHeader &header)
+{
+ if (infile == NULL)
+ {
+ return;
+ }
+
+ fread(&header.identsize, sizeof(header.identsize), 1, infile);
+ fread(&header.colourmaptype, sizeof(header.colourmaptype), 1, infile);
+ fread(&header.imagetype, sizeof(header.imagetype), 1, infile);
+ fread(&header.colourmapstart, sizeof(header.colourmapstart), 1, infile);
+ fread(&header.colourmaplength, sizeof(header.colourmaplength), 1, infile);
+ fread(&header.colourmapbits, sizeof(header.colourmapbits), 1, infile);
+ fread(&header.xstart, sizeof(header.xstart), 1, infile);
+ fread(&header.ystart, sizeof(header.ystart), 1, infile);
+ fread(&header.width, sizeof(header.width), 1, infile);
+ fread(&header.height, sizeof(header.height), 1, infile);
+ fread(&header.bits, sizeof(header.bits), 1, infile);
+ fread(&header.descriptor, sizeof(header.descriptor), 1, infile);
+}
+
+// write a TGA header to the current point in the file stream.
+static void WriteTGAHeader(FILE *outfile, TGAHeader &header)
+{
+ if (outfile == NULL)
+ {
+ return;
+ }
+
+ fwrite(&header.identsize, sizeof(header.identsize), 1, outfile);
+ fwrite(&header.colourmaptype, sizeof(header.colourmaptype), 1, outfile);
+ fwrite(&header.imagetype, sizeof(header.imagetype), 1, outfile);
+ fwrite(&header.colourmapstart, sizeof(header.colourmapstart), 1, outfile);
+ fwrite(&header.colourmaplength, sizeof(header.colourmaplength), 1, outfile);
+ fwrite(&header.colourmapbits, sizeof(header.colourmapbits), 1, outfile);
+ fwrite(&header.xstart, sizeof(header.xstart), 1, outfile);
+ fwrite(&header.ystart, sizeof(header.ystart), 1, outfile);
+ fwrite(&header.width, sizeof(header.width), 1, outfile);
+ fwrite(&header.height, sizeof(header.height), 1, outfile);
+ fwrite(&header.bits, sizeof(header.bits), 1, outfile);
+ fwrite(&header.descriptor, sizeof(header.descriptor), 1, outfile);
+}
+
+// reads in a TGA file and converts it to 32 bit RGBA color values in a memory buffer.
+unsigned char * ImgUtl_ReadTGAAsRGBA(const char *tgaPath, int &width, int &height, ConversionErrorType &errcode, TGAHeader &tgaHeader )
+{
+ FILE *tgaFile = fopen(tgaPath, "rb");
+ if (tgaFile == NULL)
+ {
+ errcode = CE_CANT_OPEN_SOURCE_FILE;
+ return NULL;
+ }
+
+ // read header for TGA file.
+ ImgUtl_ReadTGAHeader(tgaFile, tgaHeader);
+
+ if (
+ ( tgaHeader.imagetype != 2 ) // image type 2 is uncompressed RGB, other types not supported.
+ || ( tgaHeader.descriptor & 0x10 ) // Origin on righthand side (flipped horizontally from common sense) --- nobody ever uses this
+ || ( tgaHeader.bits != 24 && tgaHeader.bits != 32 ) // Must be 24- ot 32-bit
+ )
+ {
+ fclose(tgaFile);
+
+ errcode = CE_SOURCE_FILE_TGA_FORMAT_NOT_SUPPORTED;
+ return NULL;
+ }
+
+ int tgaDataSize = tgaHeader.width * tgaHeader.height * tgaHeader.bits / 8;
+ unsigned char *tgaData = (unsigned char *)malloc(tgaDataSize);
+ if (tgaData == NULL)
+ {
+ fclose(tgaFile);
+
+ errcode = CE_MEMORY_ERROR;
+ return NULL;
+ }
+
+ fread(tgaData, 1, tgaDataSize, tgaFile);
+
+ fclose(tgaFile);
+
+ width = tgaHeader.width;
+ height = tgaHeader.height;
+ int numPixels = tgaHeader.width * tgaHeader.height;
+
+ if (tgaHeader.bits == 24)
+ {
+ // image needs to be converted to a 32-bit image.
+
+ unsigned char *retBuf = (unsigned char *)malloc(numPixels * 4);
+ if (retBuf == NULL)
+ {
+ free(tgaData);
+
+ errcode = CE_MEMORY_ERROR;
+ return NULL;
+ }
+
+ // convert from BGR to RGBA color format.
+ for (int index = 0; index < numPixels; ++index)
+ {
+ retBuf[index * 4] = tgaData[index * 3 + 2];
+ retBuf[index * 4 + 1] = tgaData[index * 3 + 1];
+ retBuf[index * 4 + 2] = tgaData[index * 3];
+ retBuf[index * 4 + 3] = 0xff;
+ }
+
+ free(tgaData);
+ tgaData = retBuf;
+ tgaHeader.bits = 32;
+ }
+ else if (tgaHeader.bits == 32)
+ {
+ // Swap blue and red to convert BGR -> RGB
+ for (int index = 0; index < numPixels; ++index)
+ {
+ V_swap( tgaData[index*4], tgaData[index*4 + 2] );
+ }
+ }
+
+ // Flip image vertically if necessary
+ if ( !( tgaHeader.descriptor & 0x20 ) )
+ {
+ int y0 = 0;
+ int y1 = height-1;
+ int iStride = width*4;
+ while ( y0 < y1 )
+ {
+ unsigned char *ptr0 = tgaData + y0*iStride;
+ unsigned char *ptr1 = tgaData + y1*iStride;
+ for ( int i = 0 ; i < iStride ; ++i )
+ {
+ V_swap( ptr0[i], ptr1[i] );
+ }
+ ++y0;
+ --y1;
+ }
+ tgaHeader.descriptor |= 0x20;
+ }
+
+ errcode = CE_SUCCESS;
+ return tgaData;
+}
+
+unsigned char *ImgUtl_ReadJPEGAsRGBA( const char *jpegPath, int &width, int &height, ConversionErrorType &errcode )
+{
+#if !defined( _X360 )
+ struct jpeg_decompress_struct jpegInfo;
+ struct ValveJpegErrorHandler_t jerr;
+ JSAMPROW row_pointer[1];
+ int row_stride;
+ int cur_row = 0;
+
+ // image attributes
+ int image_height;
+ int image_width;
+
+ // open the jpeg image file.
+ FILE *infile = fopen(jpegPath, "rb");
+ if (infile == NULL)
+ {
+ errcode = CE_CANT_OPEN_SOURCE_FILE;
+ return NULL;
+ }
+
+ //CJpegSourceMgr src;
+ //FileHandle_t fileHandle = g_pFullFileSystem->Open( jpegPath, "rb" );
+ //if ( fileHandle == FILESYSTEM_INVALID_HANDLE )
+ //{
+ // errcode = CE_CANT_OPEN_SOURCE_FILE;
+ // return NULL;
+ //}
+ //if ( !src.Init( g_pFullFileSystem, fileHandle ) ) {
+ // errcode = CE_CANT_OPEN_SOURCE_FILE;
+ // g_pFullFileSystem->Close( fileHandle );
+ // return NULL;
+ //}
+
+ // setup error to print to stderr.
+ memset( &jpegInfo, 0, sizeof( jpegInfo ) );
+ jpegInfo.err = jpeg_std_error(&jerr.m_Base);
+
+ jpegInfo.err->error_exit = &ValveJpegErrorHandler;
+
+ // create the decompress struct.
+ jpeg_create_decompress(&jpegInfo);
+
+ if ( setjmp( jerr.m_ErrorContext ) )
+ {
+ // Get here if there is any error
+ jpeg_destroy_decompress( &jpegInfo );
+
+ fclose( infile );
+ //g_pFullFileSystem->Close( fileHandle );
+
+ errcode = CE_ERROR_PARSING_SOURCE;
+ return NULL;
+ }
+
+ jpeg_stdio_src(&jpegInfo, infile);
+ //jpegInfo.src = &src;
+
+ // read in the jpeg header and make sure that's all good.
+ if (jpeg_read_header(&jpegInfo, TRUE) != JPEG_HEADER_OK)
+ {
+ fclose( infile );
+ //g_pFullFileSystem->Close( fileHandle );
+ errcode = CE_ERROR_PARSING_SOURCE;
+ return NULL;
+ }
+
+ // start the decompress with the jpeg engine.
+ if ( !jpeg_start_decompress(&jpegInfo) )
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose( infile );
+ //g_pFullFileSystem->Close( fileHandle );
+ errcode = CE_ERROR_PARSING_SOURCE;
+ return NULL;
+ }
+
+ // We only support 24-bit JPEG's
+ if ( jpegInfo.out_color_space != JCS_RGB || jpegInfo.output_components != 3 )
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose( infile );
+ //g_pFullFileSystem->Close( fileHandle );
+ errcode = CE_SOURCE_FILE_SIZE_NOT_SUPPORTED;
+ return NULL;
+ }
+
+ // now that we've started the decompress with the jpeg lib, we have the attributes of the
+ // image ready to be read out of the decompress struct.
+ row_stride = jpegInfo.output_width * 4;
+ image_height = jpegInfo.image_height;
+ image_width = jpegInfo.image_width;
+ int mem_required = jpegInfo.image_height * row_stride;
+
+ // allocate the memory to read the image data into.
+ unsigned char *buf = (unsigned char *)malloc(mem_required);
+ if (buf == NULL)
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ fclose( infile );
+ //g_pFullFileSystem->Close( fileHandle );
+ errcode = CE_MEMORY_ERROR;
+ return NULL;
+ }
+
+ // read in all the scan lines of the image into our image data buffer.
+ bool working = true;
+ while (working && (jpegInfo.output_scanline < jpegInfo.output_height))
+ {
+ unsigned char *pRow = &(buf[cur_row * row_stride]);
+ row_pointer[0] = pRow;
+ if ( !jpeg_read_scanlines(&jpegInfo, row_pointer, 1) )
+ {
+ working = false;
+ }
+
+ // Expand the row RGB -> RGBA
+ for ( int x = image_width-1 ; x >= 0 ; --x )
+ {
+ pRow[x*4+3] = 0xff;
+ pRow[x*4+2] = pRow[x*3+2];
+ pRow[x*4+1] = pRow[x*3+1];
+ pRow[x*4] = pRow[x*3];
+ }
+
+ ++cur_row;
+ }
+
+ // Clean up
+ fclose( infile );
+ //g_pFullFileSystem->Close( fileHandle );
+ jpeg_destroy_decompress(&jpegInfo);
+
+ // Check success status
+ if (!working)
+ {
+ free(buf);
+ errcode = CE_ERROR_PARSING_SOURCE;
+ return NULL;
+ }
+
+ // OK!
+ width = image_width;
+ height = image_height;
+ errcode = CE_SUCCESS;
+ return buf;
+
+#else
+ errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ return NULL;
+#endif
+}
+
+
+unsigned char *ImgUtl_ReadPNGAsRGBA( const char *pngPath, int &width, int &height, ConversionErrorType &errcode )
+{
+#if !defined( _X360 )
+
+ // Just load the whole file into a memory buffer
+ CUtlBuffer bufFileContents;
+ if ( !g_pFullFileSystem->ReadFile( pngPath, NULL, bufFileContents ) )
+ {
+ errcode = CE_CANT_OPEN_SOURCE_FILE;
+ return NULL;
+ }
+
+ // Load it
+ return ImgUtl_ReadPNGAsRGBAFromBuffer( bufFileContents, width, height, errcode );
+
+#else
+ errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ return NULL;
+#endif
+}
+
+unsigned char *ImgUtl_ReadPNGAsRGBAFromBuffer( CUtlBuffer &buffer, int &width, int &height, ConversionErrorType &errcode )
+{
+ errcode = CE_MEMORY_ERROR;
+ spng_ctx* ctx = spng_ctx_new( 0 );
+ if ( ctx == nullptr )
+ return nullptr;
+
+ RunCodeAtScopeExit(
+ spng_ctx_free( ctx );
+ );
+
+ if ( spng_set_png_buffer( ctx, buffer.Base(), buffer.TellPut() ) )
+ return nullptr;
+
+ errcode = CE_ERROR_PARSING_SOURCE;
+
+ struct spng_ihdr ihdr;
+ if ( spng_get_ihdr( ctx, &ihdr ) )
+ return nullptr;
+
+ size_t size;
+ if ( spng_decoded_image_size( ctx, SPNG_FMT_RGBA8, &size ) )
+ return nullptr;
+
+ unsigned char *pResultData = (unsigned char*)MemAlloc_Alloc( size );
+ if ( spng_decode_image( ctx, pResultData, size, SPNG_FMT_RGBA8, SPNG_DECODE_TRNS ) )
+ {
+ MemAlloc_Free( pResultData );
+ return nullptr;
+ }
+
+ // OK!
+ width = ihdr.width;
+ height = ihdr.height;
+ errcode = CE_SUCCESS;
+ return pResultData;
+}
+
+unsigned char *ImgUtl_ReadBMPAsRGBA( const char *bmpPath, int &width, int &height, ConversionErrorType &errcode )
+{
+#ifdef WIN32
+ // Load up bitmap
+ HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, bmpPath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE | LR_DEFAULTSIZE);
+
+ // Handle failure
+ if ( hBitmap == NULL)
+ {
+
+ // !KLUDGE! Try to detect what went wrong
+ FILE *fp = fopen( bmpPath, "rb" );
+ if (fp == NULL)
+ {
+ errcode = CE_CANT_OPEN_SOURCE_FILE;
+ }
+ else
+ {
+ errcode = CE_ERROR_PARSING_SOURCE;
+ }
+ return NULL;
+ }
+
+ BITMAP bitmap;
+
+ GetObject(hBitmap, sizeof(bitmap), &bitmap);
+
+ BITMAPINFO *bitmapInfo;
+
+ bool bUseColorTable = false;
+ if (bitmap.bmBitsPixel == 24 || bitmap.bmBitsPixel == 32)
+ {
+ bitmapInfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO));
+ }
+ else if (bitmap.bmBitsPixel == 8 || bitmap.bmBitsPixel == 4 || bitmap.bmBitsPixel == 1)
+ {
+ int colorsUsed = 1 << bitmap.bmBitsPixel;
+ bitmapInfo = (BITMAPINFO *)malloc(colorsUsed * sizeof(RGBQUAD) + sizeof(BITMAPINFO));
+ bUseColorTable = true;
+ }
+ else
+ {
+ DeleteObject(hBitmap);
+ errcode = CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED;
+ return NULL;
+ }
+
+ memset(bitmapInfo, 0, sizeof(BITMAPINFO));
+ bitmapInfo->bmiHeader.biSize = sizeof(bitmapInfo->bmiHeader);
+ if (bUseColorTable)
+ {
+ bitmapInfo->bmiHeader.biBitCount = bitmap.bmBitsPixel; // need to specify the bits per pixel so GDI will generate a color table for us.
+ }
+
+ HDC dc = CreateCompatibleDC(NULL);
+
+ int retcode = GetDIBits(dc, hBitmap, 0, bitmap.bmHeight, NULL, bitmapInfo, DIB_RGB_COLORS);
+
+ DeleteDC(dc);
+
+ if (retcode == 0)
+ {
+ // error getting the bitmap info for some reason.
+ free(bitmapInfo);
+ errcode = CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED;
+ return NULL;
+ }
+
+ int nDestStride = 4 * bitmap.bmWidth;
+ int mem_required = nDestStride * bitmap.bmHeight; // mem required for copying the data out into RGBA format.
+
+ unsigned char *buf = (unsigned char *)malloc(mem_required);
+ if (buf == NULL)
+ {
+ free(bitmapInfo);
+ errcode = CE_MEMORY_ERROR;
+ return NULL;
+ }
+
+ if (bitmapInfo->bmiHeader.biBitCount == 32)
+ {
+ for (int y = 0; y < bitmap.bmHeight; ++y)
+ {
+ unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down
+ const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes);
+
+ for (int x = 0; x < bitmap.bmWidth; ++x)
+ {
+
+ // Swap BGR -> RGB while copying data
+ pDest[0] = pSrc[2]; // R
+ pDest[1] = pSrc[1]; // G
+ pDest[2] = pSrc[0]; // B
+ pDest[3] = pSrc[3]; // A
+
+ pSrc += 4;
+ pDest += 4;
+ }
+ }
+ }
+ else if (bitmapInfo->bmiHeader.biBitCount == 24)
+ {
+ for (int y = 0; y < bitmap.bmHeight; ++y)
+ {
+ unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down
+ const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes);
+
+ for (int x = 0; x < bitmap.bmWidth; ++x)
+ {
+
+ // Swap BGR -> RGB while copying data
+ pDest[0] = pSrc[2]; // R
+ pDest[1] = pSrc[1]; // G
+ pDest[2] = pSrc[0]; // B
+ pDest[3] = 0xff; // A
+
+ pSrc += 3;
+ pDest += 4;
+ }
+ }
+ }
+ else if (bitmapInfo->bmiHeader.biBitCount == 8)
+ {
+ // 8-bit 256 color bitmap.
+ for (int y = 0; y < bitmap.bmHeight; ++y)
+ {
+ unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down
+ const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes);
+
+ for (int x = 0; x < bitmap.bmWidth; ++x)
+ {
+
+ // compute the color map entry for this pixel
+ int colorTableEntry = *pSrc;
+
+ // get the color for this color map entry.
+ RGBQUAD *rgbQuad = &(bitmapInfo->bmiColors[colorTableEntry]);
+
+ // copy the color values for this pixel to the destination buffer.
+ pDest[0] = rgbQuad->rgbRed;
+ pDest[1] = rgbQuad->rgbGreen;
+ pDest[2] = rgbQuad->rgbBlue;
+ pDest[3] = 0xff;
+
+ ++pSrc;
+ pDest += 4;
+ }
+ }
+ }
+ else if (bitmapInfo->bmiHeader.biBitCount == 4)
+ {
+ // 4-bit 16 color bitmap.
+ for (int y = 0; y < bitmap.bmHeight; ++y)
+ {
+ unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down
+ const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes);
+
+ // Two pixels at a time
+ for (int x = 0; x < bitmap.bmWidth; x += 2)
+ {
+
+ // get the color table entry for this pixel
+ int colorTableEntry = (0xf0 & *pSrc) >> 4;
+
+ // get the color values for this pixel's color table entry.
+ RGBQUAD *rgbQuad = &(bitmapInfo->bmiColors[colorTableEntry]);
+
+ // copy the pixel's color values to the destination buffer.
+ pDest[0] = pSrc[2]; // R
+ pDest[1] = pSrc[1]; // G
+ pDest[2] = pSrc[0]; // B
+ pDest[3] = 0xff; // A
+
+ // make sure we haven't reached the end of the row.
+ if ((x + 1) > bitmap.bmWidth)
+ {
+ break;
+ }
+
+ pDest += 4;
+
+ // get the color table entry for this pixel.
+ colorTableEntry = 0x0f & *pSrc;
+
+ // get the color values for this pixel's color table entry.
+ rgbQuad = &(bitmapInfo->bmiColors[colorTableEntry]);
+
+ // copy the pixel's color values to the destination buffer.
+ pDest[0] = pSrc[2]; // R
+ pDest[1] = pSrc[1]; // G
+ pDest[2] = pSrc[0]; // B
+ pDest[3] = 0xff; // A
+
+ ++pSrc;
+ pDest += 4;
+ }
+ }
+ }
+ else if (bitmapInfo->bmiHeader.biBitCount == 1)
+ {
+ // 1-bit monochrome bitmap.
+ for (int y = 0; y < bitmap.bmHeight; ++y)
+ {
+ unsigned char *pDest = buf + nDestStride * ( ( bitmap.bmHeight - 1 ) - y ); // BMPs are stored upside down
+ const unsigned char *pSrc = (unsigned char *)(bitmap.bmBits) + (y * bitmap.bmWidthBytes);
+
+ // Eight pixels at a time
+ int x = 0;
+ while (x < bitmap.bmWidth)
+ {
+
+ RGBQUAD *rgbQuad = NULL;
+ int bitMask = 0x80;
+
+ // go through all 8 bits in this byte to get all 8 pixel colors.
+ do
+ {
+ // get the value of the bit for this pixel.
+ int bit = *pSrc & bitMask;
+
+ // bit will either be 0 or non-zero since there are only two colors.
+ if (bit == 0)
+ {
+ rgbQuad = &(bitmapInfo->bmiColors[0]);
+ }
+ else
+ {
+ rgbQuad = &(bitmapInfo->bmiColors[1]);
+ }
+
+ // copy this pixel's color values into the destination buffer.
+ pDest[0] = pSrc[2]; // R
+ pDest[1] = pSrc[1]; // G
+ pDest[2] = pSrc[0]; // B
+ pDest[3] = 0xff; // A
+ pDest += 4;
+
+ // go to the next pixel.
+ ++x;
+ bitMask = bitMask >> 1;
+ } while ((x < bitmap.bmWidth) && (bitMask > 0));
+
+ ++pSrc;
+ }
+ }
+ }
+ else
+ {
+ free(bitmapInfo);
+ free(buf);
+ DeleteObject(hBitmap);
+ errcode = CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED;
+ return NULL;
+ }
+
+ free(bitmapInfo);
+ DeleteObject(hBitmap);
+
+ // OK!
+ width = bitmap.bmWidth;
+ height = bitmap.bmHeight;
+ errcode = CE_SUCCESS;
+ return buf;
+#else
+ errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ return NULL;
+#endif
+}
+
+unsigned char *ImgUtl_ReadImageAsRGBA( const char *path, int &width, int &height, ConversionErrorType &errcode )
+{
+
+ // Split out the file extension
+ const char *pExt = V_GetFileExtension( path );
+ if ( pExt )
+ {
+ if ( !Q_stricmp(pExt, "vtf") )
+ {
+ return ImgUtl_ReadVTFAsRGBA( path, width, height, errcode );
+ }
+ if ( !Q_stricmp(pExt, "bmp") )
+ {
+ return ImgUtl_ReadBMPAsRGBA( path, width, height, errcode );
+ }
+ if ( !Q_stricmp(pExt, "jpg") || !Q_stricmp(pExt, "jpeg") )
+ {
+ return ImgUtl_ReadJPEGAsRGBA( path, width, height, errcode );
+ }
+ if ( !Q_stricmp(pExt, "png") )
+ {
+ return ImgUtl_ReadPNGAsRGBA( path, width, height, errcode );
+ }
+ if ( !Q_stricmp(pExt, "tga") )
+ {
+ TGAHeader header;
+ return ImgUtl_ReadTGAAsRGBA( path, width, height, errcode, header );
+ }
+ }
+
+ errcode = CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ return NULL;
+}
+
+// resizes the file specified by tgaPath so that it has dimensions that are
+// powers-of-two and is equal to or smaller than (nMaxWidth)x(nMaxHeight).
+// also converts from 24-bit RGB to 32-bit RGB (with 8-bit alpha)
+ConversionErrorType ImgUtl_ConvertTGA(const char *tgaPath, int nMaxWidth/*=-1*/, int nMaxHeight/*=-1*/)
+{
+ int tgaWidth = 0, tgaHeight = 0;
+ ConversionErrorType errcode;
+ TGAHeader tgaHeader;
+ unsigned char *srcBuffer = ImgUtl_ReadTGAAsRGBA(tgaPath, tgaWidth, tgaHeight, errcode, tgaHeader);
+
+ if (srcBuffer == NULL)
+ {
+ return errcode;
+ }
+
+ int paddedImageWidth, paddedImageHeight;
+
+ if ((tgaWidth <= 0) || (tgaHeight <= 0))
+ {
+ free(srcBuffer);
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ // get the nearest power of two that is greater than the width of the image.
+ paddedImageWidth = tgaWidth;
+ if (!IsPowerOfTwo(paddedImageWidth))
+ {
+ // width is not a power of two, calculate the next highest power of two value.
+ int i = 1;
+ while (paddedImageWidth > 1)
+ {
+ paddedImageWidth = paddedImageWidth >> 1;
+ ++i;
+ }
+
+ paddedImageWidth = paddedImageWidth << i;
+ }
+
+ // make sure the width is less than or equal to nMaxWidth
+ if (nMaxWidth != -1 && paddedImageWidth > nMaxWidth)
+ {
+ paddedImageWidth = nMaxWidth;
+ }
+
+ // get the nearest power of two that is greater than the height of the image
+ paddedImageHeight = tgaHeight;
+ if (!IsPowerOfTwo(paddedImageHeight))
+ {
+ // height is not a power of two, calculate the next highest power of two value.
+ int i = 1;
+ while (paddedImageHeight > 1)
+ {
+ paddedImageHeight = paddedImageHeight >> 1;
+ ++i;
+ }
+
+ paddedImageHeight = paddedImageHeight << i;
+ }
+
+ // make sure the height is less than or equal to nMaxHeight
+ if (nMaxHeight != -1 && paddedImageHeight > nMaxHeight)
+ {
+ paddedImageHeight = nMaxHeight;
+ }
+
+ // compute the amount of stretching that needs to be done to both width and height to get the image to fit.
+ float widthRatio = (float)paddedImageWidth / tgaWidth;
+ float heightRatio = (float)paddedImageHeight / tgaHeight;
+
+ int finalWidth;
+ int finalHeight;
+
+ // compute the final dimensions of the stretched image.
+ if (widthRatio < heightRatio)
+ {
+ finalWidth = paddedImageWidth;
+ finalHeight = (int)(tgaHeight * widthRatio + 0.5f);
+ // i.e. for 1x1 size pixels in the resized image we will take color from sourceRatio x sourceRatio sized pixels in the source image.
+ }
+ else if (heightRatio < widthRatio)
+ {
+ finalHeight = paddedImageHeight;
+ finalWidth = (int)(tgaWidth * heightRatio + 0.5f);
+ }
+ else
+ {
+ finalHeight = paddedImageHeight;
+ finalWidth = paddedImageWidth;
+ }
+
+ unsigned char *resizeBuffer = (unsigned char *)malloc(finalWidth * finalHeight * 4);
+
+ // do the actual stretching
+ ImgUtl_StretchRGBAImage(srcBuffer, tgaWidth, tgaHeight, resizeBuffer, finalWidth, finalHeight);
+
+ free(srcBuffer); // don't need this anymore.
+
+ ///////////////////////////////////////////////////////////////////////
+ ///// need to pad the image so both dimensions are power of two's /////
+ ///////////////////////////////////////////////////////////////////////
+ unsigned char *finalBuffer = (unsigned char *)malloc(paddedImageWidth * paddedImageHeight * 4);
+ ImgUtl_PadRGBAImage(resizeBuffer, finalWidth, finalHeight, finalBuffer, paddedImageWidth, paddedImageHeight);
+
+ FILE *outfile = fopen(tgaPath, "wb");
+ if (outfile == NULL)
+ {
+ free(resizeBuffer);
+ free(finalBuffer);
+
+ return CE_ERROR_WRITING_OUTPUT_FILE;
+ }
+
+ tgaHeader.width = paddedImageWidth;
+ tgaHeader.height = paddedImageHeight;
+
+ WriteTGAHeader(outfile, tgaHeader);
+
+ // Write the image data --- remember that TGA uses BGRA data
+ int numPixels = paddedImageWidth * paddedImageHeight;
+ for (int i = 0 ; i < numPixels ; ++i )
+ {
+ fputc( finalBuffer[i*4 + 2], outfile ); // B
+ fputc( finalBuffer[i*4 + 1], outfile ); // G
+ fputc( finalBuffer[i*4 ], outfile ); // R
+ fputc( finalBuffer[i*4 + 3], outfile ); // A
+ }
+
+ fclose(outfile);
+
+ free(resizeBuffer);
+ free(finalBuffer);
+
+ return CE_SUCCESS;
+}
+
+// resize by stretching (or compressing) an RGBA image pointed to by srcBuf into the buffer pointed to by destBuf.
+// the buffers are assumed to be sized appropriately to accomidate RGBA images of the given widths and heights.
+ConversionErrorType ImgUtl_StretchRGBAImage(const unsigned char *srcBuf, const int srcWidth, const int srcHeight,
+ unsigned char *destBuf, const int destWidth, const int destHeight)
+{
+ if ((srcBuf == NULL) || (destBuf == NULL))
+ {
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ int destRow,destColumn;
+
+ float ratioX = (float)srcWidth / (float)destWidth;
+ float ratioY = (float)srcHeight / (float)destHeight;
+
+ // loop through all the pixels in the destination image.
+ for (destRow = 0; destRow < destHeight; ++destRow)
+ {
+ for (destColumn = 0; destColumn < destWidth; ++destColumn)
+ {
+ // calculate the center of the pixel in the source image.
+ float srcCenterX = ratioX * (destColumn + 0.5f);
+ float srcCenterY = ratioY * (destRow + 0.5f);
+
+ // calculate the starting and ending coords for this destination pixel in the source image.
+ float srcStartX = srcCenterX - (ratioX / 2.0f);
+ if (srcStartX < 0.0f)
+ {
+ srcStartX = 0.0f; // this should never happen, but just in case.
+ }
+
+ float srcStartY = srcCenterY - (ratioY / 2.0f);
+ if (srcStartY < 0.0f)
+ {
+ srcStartY = 0.0f; // this should never happen, but just in case.
+ }
+
+ float srcEndX = srcCenterX + (ratioX / 2.0f);
+ if (srcEndX > srcWidth)
+ {
+ srcEndX = srcWidth; // this should never happen, but just in case.
+ }
+
+ float srcEndY = srcCenterY + (ratioY / 2.0f);
+ if (srcEndY > srcHeight)
+ {
+ srcEndY = srcHeight; // this should never happen, but just in case.
+ }
+
+ // Calculate the percentage of each source pixels' contribution to the destination pixel color.
+
+ float srcCurrentX; // initialized at the start of the y loop.
+ float srcCurrentY = srcStartY;
+
+ float destRed = 0.0f;
+ float destGreen = 0.0f;
+ float destBlue = 0.0f;
+ float destAlpha = 0.0f;
+
+ //// loop for the parts of the source image that will contribute color to the destination pixel.
+ while (srcCurrentY < srcEndY)
+ {
+ float srcCurrentEndY = (float)((int)srcCurrentY + 1);
+ if (srcCurrentEndY > srcEndY)
+ {
+ srcCurrentEndY = srcEndY;
+ }
+
+ float srcCurrentHeight = srcCurrentEndY - srcCurrentY;
+
+ srcCurrentX = srcStartX;
+
+ while (srcCurrentX < srcEndX)
+ {
+ float srcCurrentEndX = (float)((int)srcCurrentX + 1);
+ if (srcCurrentEndX > srcEndX)
+ {
+ srcCurrentEndX = srcEndX;
+ }
+ float srcCurrentWidth = srcCurrentEndX - srcCurrentX;
+
+ // compute the percentage of the destination pixel's color this source pixel will contribute.
+ float srcColorPercentage = (srcCurrentWidth / ratioX) * (srcCurrentHeight / ratioY);
+
+ int srcCurrentPixelX = (int)srcCurrentX;
+ int srcCurrentPixelY = (int)srcCurrentY;
+
+ // get the color values for this source pixel.
+ unsigned char srcCurrentRed = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4)];
+ unsigned char srcCurrentGreen = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4) + 1];
+ unsigned char srcCurrentBlue = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4) + 2];
+ unsigned char srcCurrentAlpha = srcBuf[(srcCurrentPixelY * srcWidth * 4) + (srcCurrentPixelX * 4) + 3];
+
+ // add the color contribution from this source pixel to the destination pixel.
+ destRed += srcCurrentRed * srcColorPercentage;
+ destGreen += srcCurrentGreen * srcColorPercentage;
+ destBlue += srcCurrentBlue * srcColorPercentage;
+ destAlpha += srcCurrentAlpha * srcColorPercentage;
+
+ srcCurrentX = srcCurrentEndX;
+ }
+
+ srcCurrentY = srcCurrentEndY;
+ }
+
+ // assign the computed color to the destination pixel, round to the nearest value. Make sure the value doesn't exceed 255.
+ destBuf[(destRow * destWidth * 4) + (destColumn * 4)] = min((int)(destRed + 0.5f), 255);
+ destBuf[(destRow * destWidth * 4) + (destColumn * 4) + 1] = min((int)(destGreen + 0.5f), 255);
+ destBuf[(destRow * destWidth * 4) + (destColumn * 4) + 2] = min((int)(destBlue + 0.5f), 255);
+ destBuf[(destRow * destWidth * 4) + (destColumn * 4) + 3] = min((int)(destAlpha + 0.5f), 255);
+ } // column loop
+ } // row loop
+
+ return CE_SUCCESS;
+}
+
+ConversionErrorType ImgUtl_PadRGBAImage(const unsigned char *srcBuf, const int srcWidth, const int srcHeight,
+ unsigned char *destBuf, const int destWidth, const int destHeight)
+{
+ if ((srcBuf == NULL) || (destBuf == NULL))
+ {
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ memset(destBuf, 0, destWidth * destHeight * 4);
+
+ if ((destWidth < srcWidth) || (destHeight < srcHeight))
+ {
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ if ((srcWidth == destWidth) && (srcHeight == destHeight))
+ {
+ // no padding is needed, just copy the buffer straight over and call it done.
+ memcpy(destBuf, srcBuf, destWidth * destHeight * 4);
+ return CE_SUCCESS;
+ }
+
+ if (destWidth == srcWidth)
+ {
+ // only the top and bottom of the image need padding.
+ // do this separately since we can do this more efficiently than the other cases.
+ int numRowsToPad = (destHeight - srcHeight) / 2;
+ memcpy(destBuf + (numRowsToPad * destWidth * 4), srcBuf, srcWidth * srcHeight * 4);
+ }
+ else
+ {
+ int numColumnsToPad = (destWidth - srcWidth) / 2;
+ int numRowsToPad = (destHeight - srcHeight) / 2;
+ int lastRow = numRowsToPad + srcHeight;
+ int row;
+ for (row = numRowsToPad; row < lastRow; ++row)
+ {
+ unsigned char * destOffset = destBuf + (row * destWidth * 4) + (numColumnsToPad * 4);
+ const unsigned char * srcOffset = srcBuf + ((row - numRowsToPad) * srcWidth * 4);
+ memcpy(destOffset, srcOffset, srcWidth * 4);
+ }
+ }
+
+ return CE_SUCCESS;
+}
+
+// convert TGA file at the given location to a VTF file of the same root name at the same location.
+ConversionErrorType ImgUtl_ConvertTGAToVTF(const char *tgaPath, int nMaxWidth/*=-1*/, int nMaxHeight/*=-1*/ )
+{
+ FILE *infile = fopen(tgaPath, "rb");
+ if (infile == NULL)
+ {
+ Msg( "Failed to open TGA: %s\n", tgaPath);
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ // read out the header of the image.
+ TGAHeader header;
+ ImgUtl_ReadTGAHeader(infile, header);
+
+ // check to make sure that the TGA has the proper dimensions and size.
+ if (!IsPowerOfTwo(header.width) || !IsPowerOfTwo(header.height))
+ {
+ fclose(infile);
+ Msg( "Failed to open TGA - size dimensions (%d, %d) not power of 2: %s\n", header.width, header.height, tgaPath);
+ return CE_SOURCE_FILE_SIZE_NOT_SUPPORTED;
+ }
+
+ // check to make sure that the TGA isn't too big, if we care.
+ if ( ( nMaxWidth != -1 && header.width > nMaxWidth ) || ( nMaxHeight != -1 && header.height > nMaxHeight ) )
+ {
+ fclose(infile);
+ Msg( "Failed to open TGA - dimensions too large (%d, %d) (max: %d, %d): %s\n", header.width, header.height, nMaxWidth, nMaxHeight, tgaPath);
+ return CE_SOURCE_FILE_SIZE_NOT_SUPPORTED;
+ }
+
+ int imageMemoryFootprint = header.width * header.height * header.bits / 8;
+
+ CUtlBuffer inbuf(0, imageMemoryFootprint);
+
+ // read in the image
+ int nBytesRead = (int)fread(inbuf.Base(), imageMemoryFootprint, 1, infile);
+
+ fclose(infile);
+ inbuf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead );
+
+ // load vtex_dll.dll and get the interface to it.
+ CSysModule *vtexmod = Sys_LoadModule("vtex_dll");
+ if (vtexmod == NULL)
+ {
+ Msg( "Failed to open TGA conversion module vtex_dll: %s\n", tgaPath);
+ return CE_ERROR_LOADING_DLL;
+ }
+
+ CreateInterfaceFn factory = Sys_GetFactory(vtexmod);
+ if (factory == NULL)
+ {
+ Sys_UnloadModule(vtexmod);
+ Msg( "Failed to open TGA conversion module vtex_dll Factory: %s\n", tgaPath);
+ return CE_ERROR_LOADING_DLL;
+ }
+
+ IVTex *vtex = (IVTex *)factory(IVTEX_VERSION_STRING, NULL);
+ if (vtex == NULL)
+ {
+ Sys_UnloadModule(vtexmod);
+ Msg( "Failed to open TGA conversion module vtex_dll Factory (is null): %s\n", tgaPath);
+ return CE_ERROR_LOADING_DLL;
+ }
+
+ char *vtfParams[4];
+
+ // the 0th entry is skipped cause normally thats the program name.
+ vtfParams[0] = "";
+ vtfParams[1] = "-quiet";
+ vtfParams[2] = "-dontusegamedir";
+ vtfParams[3] = (char *)tgaPath;
+
+ // call vtex to do the conversion.
+ vtex->VTex(4, vtfParams); // how do we know this works?
+
+ Sys_UnloadModule(vtexmod);
+
+ return CE_SUCCESS;
+}
+
+static void DoCopyFile( const char *source, const char *destination )
+{
+#if defined( WIN32 )
+ CopyFile( source, destination, true );
+#elif defined( OSX )
+ copyfile( source, destination, NULL, COPYFILE_ALL );
+#elif defined( ENGINE_DLL )
+ ::COM_CopyFile( source, destination );
+#elif REPLAY_DLL
+ g_pEngine->CopyFile( source, destination );
+#else
+ engine->CopyLocalFile( source, destination );
+#endif
+}
+
+static void DoDeleteFile( const char *filename )
+{
+#ifdef WIN32
+ DeleteFile( filename );
+#else
+ unlink( filename );
+#endif
+}
+
+ConversionErrorType ImgUtl_ConvertToVTFAndDumpVMT( const char *pInPath, const char *pMaterialsSubDir, int nMaxWidth/*=-1*/, int nMaxHeight/*=-1*/ )
+{
+#ifndef _XBOX
+ if ((pInPath == NULL) || (pInPath[0] == 0))
+ {
+ return CE_ERROR_PARSING_SOURCE;
+ }
+
+ ConversionErrorType nErrorCode = CE_SUCCESS;
+
+ // get the extension of the file we're to convert
+ char extension[MAX_PATH];
+ const char *constchar = pInPath + strlen(pInPath);
+ while ((constchar > pInPath) && (*(constchar-1) != '.'))
+ {
+ --constchar;
+ }
+ Q_strncpy(extension, constchar, MAX_PATH);
+
+ bool deleteIntermediateTGA = false;
+ bool deleteIntermediateVTF = false;
+ bool convertTGAToVTF = true;
+ char tgaPath[MAX_PATH*2];
+ char *c;
+ bool failed = false;
+
+ Q_strncpy(tgaPath, pInPath, sizeof(tgaPath));
+
+ // Construct a TGA version if necessary
+ if (stricmp(extension, "tga"))
+ {
+ // It is not a TGA file, so create a temporary file name for the TGA you have to create
+
+ c = tgaPath + strlen(tgaPath);
+ while ((c > tgaPath) && (*(c-1) != '\\') && (*(c-1) != '/'))
+ {
+ --c;
+ }
+ *c = 0;
+
+ char origpath[MAX_PATH*2];
+ Q_strncpy(origpath, tgaPath, sizeof(origpath));
+
+ // Look for an empty temp file - find the first one that doesn't exist.
+ int index = 0;
+ do {
+ Q_snprintf(tgaPath, sizeof(tgaPath), "%stemp%d.tga", origpath, index);
+ ++index;
+ } while (_access(tgaPath, 0) != -1);
+
+
+ // Convert the other formats to TGA
+
+ // jpeg files
+ //
+ if (!stricmp(extension, "jpg") || !stricmp(extension, "jpeg"))
+ {
+ // convert from the jpeg file format to the TGA file format
+ nErrorCode = ImgUtl_ConvertJPEGToTGA(pInPath, tgaPath, false);
+ if (nErrorCode == CE_SUCCESS)
+ {
+ deleteIntermediateTGA = true;
+ }
+ else
+ {
+ failed = true;
+ }
+ }
+ // bmp files
+ //
+ else if (!stricmp(extension, "bmp"))
+ {
+ // convert from the bmp file format to the TGA file format
+ nErrorCode = ImgUtl_ConvertBMPToTGA(pInPath, tgaPath);
+
+ if (nErrorCode == CE_SUCCESS)
+ {
+ deleteIntermediateTGA = true;
+ }
+ else
+ {
+ failed = true;
+ }
+ }
+ // vtf files
+ //
+ else if (!stricmp(extension, "vtf"))
+ {
+ // if the file is already in the vtf format there's no need to convert it.
+ convertTGAToVTF = false;
+
+ }
+ }
+
+ // if we now have a TGA file, convert it to VTF
+ if (convertTGAToVTF && !failed)
+ {
+ nErrorCode = ImgUtl_ConvertTGA( tgaPath, nMaxWidth, nMaxHeight ); // resize TGA so that it has power-of-two dimensions with a max size of (nMaxWidth)x(nMaxHeight).
+ if (nErrorCode != CE_SUCCESS)
+ {
+ failed = true;
+ }
+
+ if (!failed)
+ {
+ char tempPath[MAX_PATH*2];
+ Q_strncpy(tempPath, tgaPath, sizeof(tempPath));
+
+ nErrorCode = ImgUtl_ConvertTGAToVTF( tempPath, nMaxWidth, nMaxHeight );
+ if (nErrorCode == CE_SUCCESS)
+ {
+ deleteIntermediateVTF = true;
+ }
+ else
+ {
+ Msg( "Failed to convert TGA to VTF: %s\n", tempPath);
+ failed = true;
+ }
+ }
+ }
+
+ // At this point everything should be a VTF file
+
+ char finalPath[MAX_PATH*2];
+ finalPath[0] = 0;
+ char vtfPath[MAX_PATH*2];
+ vtfPath[0] = 0;
+
+
+ // If we haven't failed so far, create a VMT to go with this VTF
+ if (!failed)
+ {
+
+ // If I had to convert from another filetype (i.e. the original was NOT a .vtf)
+ if ( convertTGAToVTF )
+ {
+
+ Q_strncpy(vtfPath, tgaPath, sizeof(vtfPath));
+
+ // rename the tga file to be a vtf file.
+ c = vtfPath + strlen(vtfPath);
+ while ((c > vtfPath) && (*(c-1) != '.'))
+ {
+ --c;
+ }
+ *c = 0;
+ Q_strncat(vtfPath, "vtf", sizeof(vtfPath), COPY_ALL_CHARACTERS);
+
+ }
+ else
+ {
+ // We were handed a vtf file originally, so use it.
+ Q_strncpy(vtfPath, pInPath, sizeof(vtfPath));
+ }
+
+ // get the vtfFilename from the path.
+ const char *vtfFilename = pInPath + strlen(pInPath);
+ while ((vtfFilename > pInPath) && (*(vtfFilename-1) != '\\') && (*(vtfFilename-1) != '/'))
+ {
+ --vtfFilename;
+ }
+
+ // Create a safe version of pOutDir with corrected slashes
+ char szOutDir[MAX_PATH*2];
+ V_strcpy_safe( szOutDir, IsPosix() ? "/materials/" : "\\materials\\" );
+ if ( pMaterialsSubDir[0] == '\\' || pMaterialsSubDir[0] == '/' )
+ pMaterialsSubDir = pMaterialsSubDir + 1;
+ V_strcat_safe(szOutDir, pMaterialsSubDir, sizeof(szOutDir) );
+ Q_StripTrailingSlash( szOutDir );
+ Q_AppendSlash( szOutDir, sizeof(szOutDir) );
+ Q_FixSlashes( szOutDir, CORRECT_PATH_SEPARATOR );
+
+#ifdef ENGINE_DLL
+ Q_strncpy(finalPath, com_gamedir, sizeof(finalPath));
+#elif REPLAY_DLL
+ Q_strncpy(finalPath, g_pEngine->GetGameDir(), sizeof(finalPath));
+#else
+ Q_strncpy(finalPath, engine->GetGameDirectory(), sizeof(finalPath));
+#endif
+ Q_strncat(finalPath, szOutDir, sizeof(finalPath), COPY_ALL_CHARACTERS);
+ Q_strncat(finalPath, vtfFilename, sizeof(finalPath), COPY_ALL_CHARACTERS);
+
+ c = finalPath + strlen(finalPath);
+ while ((c > finalPath) && (*(c-1) != '.'))
+ {
+ --c;
+ }
+ *c = 0;
+ Q_strncat(finalPath,"vtf", sizeof(finalPath), COPY_ALL_CHARACTERS);
+
+ // make sure the directory exists before we try to copy the file.
+ g_pFullFileSystem->CreateDirHierarchy(szOutDir + 1, "GAME");
+ //g_pFullFileSystem->CreateDirHierarchy("materials/VGUI/logos/", "GAME");
+
+ // write out the spray VMT file.
+ if ( strcmp(vtfPath, finalPath) ) // If they're not already the same
+ {
+ nErrorCode = ImgUtl_WriteGenericVMT(finalPath, pMaterialsSubDir);
+ if (nErrorCode != CE_SUCCESS)
+ {
+ failed = true;
+ }
+
+ if (!failed)
+ {
+ // copy vtf file to the final location, only if we're not already in vtf
+
+ DoCopyFile( vtfPath, finalPath );
+ }
+ }
+ }
+
+ // delete the intermediate VTF file if one was made.
+ if (deleteIntermediateVTF)
+ {
+ DoDeleteFile( vtfPath );
+
+ // the TGA->VTF conversion process generates a .txt file if one wasn't already there.
+ // in this case, delete the .txt file.
+ c = vtfPath + strlen(vtfPath);
+ while ((c > vtfPath) && (*(c-1) != '.'))
+ {
+ --c;
+ }
+ Q_strncpy(c, "txt", (int)(sizeof(vtfPath)-(c-vtfPath)));
+
+ DoDeleteFile( vtfPath );
+ }
+
+ // delete the intermediate TGA file if one was made.
+ if (deleteIntermediateTGA)
+ {
+ DoDeleteFile( tgaPath );
+ }
+
+ return nErrorCode;
+#endif
+}
+
+ConversionErrorType ImgUtl_WriteGenericVMT( const char *vtfPath, const char *pMaterialsSubDir )
+{
+ if (vtfPath == NULL || pMaterialsSubDir == NULL )
+ {
+ return CE_ERROR_WRITING_OUTPUT_FILE;
+ }
+
+ // make the vmt filename
+ char vmtPath[MAX_PATH*4];
+ Q_strncpy(vmtPath, vtfPath, sizeof(vmtPath));
+ char *c = vmtPath + strlen(vmtPath);
+ while ((c > vmtPath) && (*(c-1) != '.'))
+ {
+ --c;
+ }
+ Q_strncpy(c, "vmt", (int)(sizeof(vmtPath) - (c - vmtPath)));
+
+ // get the root filename for the vtf file
+ char filename[MAX_PATH];
+ while ((c > vmtPath) && (*(c-1) != '/') && (*(c-1) != '\\'))
+ {
+ --c;
+ }
+
+ int i = 0;
+ while ((*c != 0) && (*c != '.'))
+ {
+ filename[i++] = *(c++);
+ }
+ filename[i] = 0;
+
+ // create the vmt file.
+ FILE *vmtFile = fopen(vmtPath, "w");
+ if (vmtFile == NULL)
+ {
+ return CE_ERROR_WRITING_OUTPUT_FILE;
+ }
+
+ // make a copy of the subdir and remove any trailing slash
+ char szMaterialsSubDir[ MAX_PATH*2 ];
+ V_strcpy_safe( szMaterialsSubDir, pMaterialsSubDir );
+ V_StripTrailingSlash( szMaterialsSubDir );
+
+ // fix slashes
+ V_FixSlashes( szMaterialsSubDir );
+
+ // write the contents of the file.
+ fprintf(vmtFile, "\"UnlitGeneric\"\n{\n\t\"$basetexture\" \"%s%c%s\"\n\t\"$translucent\" \"1\"\n\t\"$ignorez\" \"1\"\n\t\"$vertexcolor\" \"1\"\n\t\"$vertexalpha\" \"1\"\n}\n", szMaterialsSubDir, CORRECT_PATH_SEPARATOR, filename);
+
+ fclose(vmtFile);
+
+ return CE_SUCCESS;
+}
+
+ConversionErrorType ImgUtl_WriteRGBAAsPNGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, bool bIncludesAlpha )
+{
+ spng_ctx* enc = spng_ctx_new( SPNG_CTX_ENCODER );
+ if ( enc == nullptr ) {
+ return CE_MEMORY_ERROR;
+ }
+
+ RunCodeAtScopeExit(
+ spng_ctx_free( enc );
+ );
+
+ int nPixelByteSize = ( bIncludesAlpha ) ? 4 : 3;
+
+ struct spng_ihdr ihdr;
+ memset( &ihdr, 0, sizeof( ihdr ) );
+ ihdr.width = nWidth;
+ ihdr.height = nHeight;
+ ihdr.bit_depth = 8;
+ ihdr.color_type = SPNG_COLOR_TYPE_TRUECOLOR;
+ if ( bIncludesAlpha )
+ {
+ ihdr.color_type = SPNG_COLOR_TYPE_TRUECOLOR_ALPHA;
+ }
+
+
+ ihdr.compression_method = 0;
+ ihdr.filter_method = SPNG_FILTER_NONE;
+ ihdr.interlace_method = SPNG_INTERLACE_NONE;
+
+ spng_set_ihdr( enc, &ihdr );
+ spng_set_option( enc, SPNG_ENCODE_TO_BUFFER, 1 );
+
+ if ( spng_encode_image( enc, pRGBAData, ( nWidth * nHeight * nPixelByteSize ), SPNG_FMT_PNG, SPNG_ENCODE_FINALIZE ) )
+ {
+ return CE_ERROR_WRITING_OUTPUT_FILE;
+ }
+
+ int err;
+ size_t png_buf_sz;
+ void* png_buf = spng_get_png_buffer( enc, &png_buf_sz, &err );
+ if ( err != 0 )
+ {
+ return CE_ERROR_WRITING_OUTPUT_FILE;
+ }
+
+ bufOutData.Put( png_buf, int( png_buf_sz ) );
+
+ MemAlloc_Free( png_buf );
+
+ return CE_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Initialize destination --- called by jpeg_start_compress
+// before any data is actually written.
+//-----------------------------------------------------------------------------
+METHODDEF(void) init_destination (j_compress_ptr cinfo)
+{
+ JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t *) cinfo->dest;
+
+ // Allocate the output buffer --- it will be released when done with image
+ dest->buffer = (byte *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ JPEG_OUTPUT_BUF_SIZE * sizeof(byte));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Empty the output buffer --- called whenever buffer fills up.
+// Input : boolean -
+//-----------------------------------------------------------------------------
+METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
+{
+ JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t * ) cinfo->dest;
+
+ CUtlBuffer *buf = dest->pBuffer;
+
+ // Add some data
+ buf->Put( dest->buffer, JPEG_OUTPUT_BUF_SIZE );
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Terminate destination --- called by jpeg_finish_compress
+// after all data has been written. Usually needs to flush buffer.
+//
+// NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+// application must deal with any cleanup that should happen even
+// for error exit.
+//-----------------------------------------------------------------------------
+METHODDEF(void) term_destination (j_compress_ptr cinfo)
+{
+ JPEGDestinationManager_t *dest = (JPEGDestinationManager_t *) cinfo->dest;
+ long long int datacount = ( long long int )JPEG_OUTPUT_BUF_SIZE - (long long int)dest->pub.free_in_buffer;
+
+ CUtlBuffer *buf = dest->pBuffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0)
+ {
+ buf->Put( dest->buffer, (int)Min(datacount, (long long int)INT_MAX) );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set up functions for writing data to a CUtlBuffer instead of FILE *
+//-----------------------------------------------------------------------------
+GLOBAL(void) jpeg_UtlBuffer_dest (j_compress_ptr cinfo, CUtlBuffer *pBuffer )
+{
+ JPEGDestinationManager_t *dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(JPEGDestinationManager_t));
+ }
+
+ dest = ( JPEGDestinationManager_t * ) cinfo->dest;
+
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->pBuffer = pBuffer;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Write three channel RGB data to a JPEG file
+//-----------------------------------------------------------------------------
+bool ImgUtl_WriteRGBToJPEG( unsigned char *pSrcBuf, unsigned int nSrcWidth, unsigned int nSrcHeight, const char *lpszFilename )
+{
+ CUtlBuffer dstBuf;
+
+ JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
+ int row_stride; // physical row width in image buffer
+
+ // stderr handler
+ struct jpeg_error_mgr jerr;
+
+ // compression data structure
+ struct jpeg_compress_struct cinfo;
+
+ row_stride = nSrcWidth * 3; // JSAMPLEs per row in image_buffer
+
+ // point at stderr
+ cinfo.err = jpeg_std_error(&jerr);
+
+ // create compressor
+ jpeg_create_compress(&cinfo);
+
+ // Hook CUtlBuffer to compression
+ jpeg_UtlBuffer_dest(&cinfo, &dstBuf );
+
+ // image width and height, in pixels
+ cinfo.image_width = nSrcWidth;
+ cinfo.image_height = nSrcHeight;
+ // RGB is 3 component
+ cinfo.input_components = 3;
+ // # of color components per pixel
+ cinfo.in_color_space = JCS_RGB;
+
+ // Apply settings
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, 100, TRUE );
+
+ // Start compressor
+ jpeg_start_compress(&cinfo, TRUE);
+
+ // Write scanlines
+ while ( cinfo.next_scanline < cinfo.image_height )
+ {
+ row_pointer[ 0 ] = &pSrcBuf[ cinfo.next_scanline * row_stride ];
+ jpeg_write_scanlines( &cinfo, row_pointer, 1 );
+ }
+
+ // Finalize image
+ jpeg_finish_compress(&cinfo);
+
+ // Cleanup
+ jpeg_destroy_compress(&cinfo);
+
+ return CE_SUCCESS;
+}
+
+ConversionErrorType ImgUtl_WriteRGBAAsJPEGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, int nStride )
+{
+#if !defined( _X360 )
+
+ JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
+ int row_stride; // physical row width in image buffer
+
+ // stderr handler
+ struct jpeg_error_mgr jerr;
+
+ // compression data structure
+ struct jpeg_compress_struct cinfo;
+
+ row_stride = nWidth * 4;
+
+ // point at stderr
+ cinfo.err = jpeg_std_error(&jerr);
+
+ // create compressor
+ jpeg_create_compress(&cinfo);
+
+ // Hook CUtlBuffer to compression
+ jpeg_UtlBuffer_dest(&cinfo, &bufOutData );
+
+ // image width and height, in pixels
+ cinfo.image_width = nWidth;
+ cinfo.image_height = nHeight;
+ // RGB is 3 component
+ cinfo.input_components = 3;
+ // # of color components per pixel
+ cinfo.in_color_space = JCS_RGB;
+
+ // Apply settings
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, 100, TRUE );
+
+ // Start compressor
+ jpeg_start_compress(&cinfo, TRUE);
+
+ // Write scanlines
+ unsigned char *pDstRow = (unsigned char *)malloc( sizeof(unsigned char) * nWidth * 4 );
+ while ( cinfo.next_scanline < cinfo.image_height )
+ {
+ const unsigned char *pSrcRow = &(pRGBAData[cinfo.next_scanline * row_stride]);
+ // convert row from RGBA to RGB
+ for ( int x = nWidth-1 ; x >= 0 ; --x )
+ {
+ pDstRow[x*3+2] = pSrcRow[x*4+2];
+ pDstRow[x*3+1] = pSrcRow[x*4+1];
+ pDstRow[x*3] = pSrcRow[x*4];
+ }
+ row_pointer[ 0 ] = pDstRow;
+ jpeg_write_scanlines( &cinfo, row_pointer, 1 );
+ }
+
+ // Finalize image
+ jpeg_finish_compress(&cinfo);
+
+ // Cleanup
+ jpeg_destroy_compress(&cinfo);
+
+ free( pDstRow );
+
+ return CE_SUCCESS;
+#else
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+#endif
+}
+
+ConversionErrorType ImgUtl_LoadBitmap( const char *pszFilename, Bitmap_t &bitmap )
+{
+ bitmap.Clear();
+ ConversionErrorType nErrorCode;
+ int width, height;
+ unsigned char *buffer = ImgUtl_ReadImageAsRGBA( pszFilename, width, height, nErrorCode );
+ if ( nErrorCode != CE_SUCCESS )
+ {
+ return nErrorCode;
+ }
+
+ // Install the buffer into the bitmap, and transfer ownership
+ bitmap.SetBuffer( width, height, IMAGE_FORMAT_RGBA8888, buffer, true, width*4 );
+ return CE_SUCCESS;
+}
+
+static ConversionErrorType ImgUtl_LoadJPEGBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap )
+{
+ // @todo implement
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+}
+
+static ConversionErrorType ImgUtl_SaveJPEGBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap )
+{
+ if ( !bitmap.IsValid() )
+ {
+ Assert( bitmap.IsValid() );
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ // Sorry, only RGBA8888 supported right now
+ if ( bitmap.Format() != IMAGE_FORMAT_RGBA8888 )
+ {
+ Assert( bitmap.Format() == IMAGE_FORMAT_RGBA8888 );
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ }
+
+ // Do it
+ ConversionErrorType result = ImgUtl_WriteRGBAAsJPEGToBuffer(
+ bitmap.GetBits(),
+ bitmap.Width(),
+ bitmap.Height(),
+ fileData,
+ bitmap.Stride()
+ );
+ return result;
+}
+
+ConversionErrorType ImgUtl_LoadBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap, ImageFileFormat eImageFileFormat )
+{
+ switch ( eImageFileFormat )
+ {
+ case kImageFileFormat_PNG:
+ return ImgUtl_LoadPNGBitmapFromBuffer( fileData, bitmap );
+ case kImageFileFormat_JPG:
+ return ImgUtl_LoadJPEGBitmapFromBuffer( fileData, bitmap );
+ }
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+}
+
+ConversionErrorType ImgUtl_SaveBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap, ImageFileFormat eImageFileFormat )
+{
+ switch ( eImageFileFormat )
+ {
+ case kImageFileFormat_PNG:
+ return ImgUtl_SavePNGBitmapToBuffer( fileData, bitmap );
+ case kImageFileFormat_JPG:
+ return ImgUtl_SaveJPEGBitmapToBuffer( fileData, bitmap );
+ }
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+}
+
+ConversionErrorType ImgUtl_LoadPNGBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap )
+{
+ bitmap.Clear();
+ ConversionErrorType nErrorCode;
+ int width, height;
+ unsigned char *buffer = ImgUtl_ReadPNGAsRGBAFromBuffer( fileData, width, height, nErrorCode );
+ if ( nErrorCode != CE_SUCCESS )
+ {
+ return nErrorCode;
+ }
+
+ // Install the buffer into the bitmap, and transfer ownership
+ bitmap.SetBuffer( width, height, IMAGE_FORMAT_RGBA8888, buffer, true, width*4 );
+ return CE_SUCCESS;
+}
+
+ConversionErrorType ImgUtl_GetPNGSize( CUtlBuffer &fileData, uint32_t &uWidth, uint32_t &uHeight )
+{
+ ConversionErrorType errcode = CE_MEMORY_ERROR;
+ spng_ctx* ctx = spng_ctx_new( 0 );
+ if ( ctx == nullptr )
+ return errcode;
+
+ RunCodeAtScopeExit(
+ spng_ctx_free( ctx );
+ );
+
+ if ( spng_set_png_buffer( ctx, fileData.Base(), fileData.TellPut() ) )
+ return errcode;
+
+ errcode = CE_ERROR_PARSING_SOURCE;
+
+ struct spng_ihdr ihdr;
+ if ( spng_get_ihdr( ctx, &ihdr ) )
+ return errcode;
+
+ uWidth = ihdr.width;
+ uHeight = ihdr.height;
+ errcode = CE_SUCCESS;
+
+ return errcode;
+}
+
+ConversionErrorType ImgUtl_SavePNGBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap )
+{
+ if ( !bitmap.IsValid() )
+ {
+ Assert( bitmap.IsValid() );
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ // Sorry, only RGBA8888 supported right now
+ if ( bitmap.Format() != IMAGE_FORMAT_RGBA8888 )
+ {
+ Assert( bitmap.Format() == IMAGE_FORMAT_RGBA8888 );
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ }
+
+ // Do it
+ ConversionErrorType result = ImgUtl_WriteRGBAAsPNGToBuffer(
+ bitmap.GetBits(),
+ bitmap.Width(),
+ bitmap.Height(),
+ fileData,
+ bitmap.Stride()
+ );
+ return result;
+}
+
+ConversionErrorType ImgUtl_ResizeBitmap( Bitmap_t &destBitmap, int nWidth, int nHeight, const Bitmap_t *pImgSource )
+{
+
+ // Check for resizing in place, then save off data into a temp
+ Bitmap_t temp;
+ if ( pImgSource == NULL || pImgSource == &destBitmap )
+ {
+ temp.MakeLogicalCopyOf( destBitmap, destBitmap.GetOwnsBuffer() );
+ pImgSource = &temp;
+ }
+
+ // No source image?
+ if ( !pImgSource->IsValid() )
+ {
+ Assert( pImgSource->IsValid() );
+ return CE_CANT_OPEN_SOURCE_FILE;
+ }
+
+ // Sorry, we're using an existing rescaling routine that
+ // only withs for RGBA images with assumed stride
+ if (
+ pImgSource->Format() != IMAGE_FORMAT_RGBA8888
+ || pImgSource->Stride() != pImgSource->Width()*4
+ ) {
+ Assert( pImgSource->Format() == IMAGE_FORMAT_RGBA8888 );
+ Assert( pImgSource->Stride() == pImgSource->Width()*4 );
+ return CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED;
+ }
+
+ // Allocate buffer
+ destBitmap.Init( nWidth, nHeight, IMAGE_FORMAT_RGBA8888 );
+
+ // Something wrong?
+ if ( !destBitmap.IsValid() )
+ {
+ Assert( destBitmap.IsValid() );
+ return CE_MEMORY_ERROR;
+ }
+
+ // Do it
+ return ImgUtl_StretchRGBAImage(
+ pImgSource->GetBits(), pImgSource->Width(), pImgSource->Height(),
+ destBitmap.GetBits(), destBitmap.Width(), destBitmap.Height()
+ );
+}
diff --git a/src/common/imageutils.h b/src/common/imageutils.h
new file mode 100644
index 00000000..45be0429
--- /dev/null
+++ b/src/common/imageutils.h
@@ -0,0 +1,102 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//=======================================================================================//
+
+#ifndef IMAGECONVERSION_H
+#define IMAGECONVERSION_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/basetypes.h"
+
+class CUtlBuffer;
+struct Bitmap_t;
+
+enum ConversionErrorType
+{
+ CE_SUCCESS,
+ CE_MEMORY_ERROR,
+ CE_CANT_OPEN_SOURCE_FILE,
+ CE_ERROR_PARSING_SOURCE,
+ CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED,
+ CE_SOURCE_FILE_TGA_FORMAT_NOT_SUPPORTED,
+ CE_SOURCE_FILE_BMP_FORMAT_NOT_SUPPORTED,
+ CE_SOURCE_FILE_SIZE_NOT_SUPPORTED,
+ CE_ERROR_WRITING_OUTPUT_FILE,
+ CE_ERROR_LOADING_DLL
+};
+
+enum ImageFileFormat
+{
+ kImageFileFormat_PNG,
+ kImageFileFormat_JPG,
+};
+
+struct TGAHeader {
+ byte identsize; // size of ID field that follows 18 byte header (0 usually)
+ byte colourmaptype; // type of colour map 0=none, 1=has palette
+ byte imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
+
+ short colourmapstart; // first colour map entry in palette
+ short colourmaplength; // number of colours in palette
+ byte colourmapbits; // number of bits per palette entry 15,16,24,32
+
+ short xstart; // image x origin
+ short ystart; // image y origin
+ short width; // image width in pixels
+ short height; // image height in pixels
+ byte bits; // image bits per pixel 8,16,24,32
+ byte descriptor; // image descriptor bits (vh flip bits)
+};
+
+ConversionErrorType ImgUtl_ConvertJPEGToTGA( const char *jpgPath, const char *tgaPath, bool bRequirePowerOfTwoSize = true );
+ConversionErrorType ImgUtl_ConvertBMPToTGA( const char *bmpPath, const char *tgaPath );
+ConversionErrorType ImgUtl_ConvertTGA( const char *tgaPath, int nMaxWidth = -1, int nMaxHeight = -1 );
+unsigned char *ImgUtl_ReadVTFAsRGBA( const char *vtfPath, int &width, int &height, ConversionErrorType &errcode );
+unsigned char *ImgUtl_ReadTGAAsRGBA( const char *tgaPath, int &width, int &height, ConversionErrorType &errcode, TGAHeader &tgaHeader );
+unsigned char *ImgUtl_ReadJPEGAsRGBA( const char *jpegPath, int &width, int &height, ConversionErrorType &errcode );
+unsigned char *ImgUtl_ReadBMPAsRGBA( const char *bmpPath, int &width, int &height, ConversionErrorType &errcode );
+unsigned char *ImgUtl_ReadPNGAsRGBA( const char *bmpPath, int &width, int &height, ConversionErrorType &errcode );
+unsigned char *ImgUtl_ReadPNGAsRGBAFromBuffer( CUtlBuffer &buffer, int &width, int &height, ConversionErrorType &errcode );
+unsigned char *ImgUtl_ReadImageAsRGBA( const char *path, int &width, int &height, ConversionErrorType &errcode );
+ConversionErrorType ImgUtl_StretchRGBAImage( const unsigned char *srcBuf, const int srcWidth, const int srcHeight, unsigned char *destBuf, const int destWidth, const int destHeight );
+ConversionErrorType ImgUtl_PadRGBAImage( const unsigned char *srcBuf, const int srcWidth, const int srcHeight, unsigned char *destBuf, const int destWidth, const int destHeight );
+ConversionErrorType ImgUtl_ConvertTGAToVTF( const char *tgaPath, int nMaxWidth = -1, int nMaxHeight = -1 );
+ConversionErrorType ImgUtl_WriteGenericVMT( const char *vtfPath, const char *pMaterialsSubDir );
+ConversionErrorType ImgUtl_WriteRGBAAsPNGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, bool bIncludesAlpha = true );
+ConversionErrorType ImgUtl_WriteRGBAAsJPEGToBuffer( const unsigned char *pRGBAData, int nWidth, int nHeight, CUtlBuffer &bufOutData, int nStride = 0 );
+
+//
+// Converts pInPath (which can be a TGA, BMP, or JPG file) to a VTF in pMaterialsSubDir, where
+// pMaterialsSubDir is a directory located relative to the game/materials directory. If the
+// output directory doesn't exist, it will be created. Dumps a generic VMT in pMaterialsSubDir
+// as well.
+//
+ConversionErrorType ImgUtl_ConvertToVTFAndDumpVMT( const char *pInPath, const char *pMaterialsSubDir,
+ int nMaxWidth = -1, int nMaxHeight = -1 );
+
+
+/// Load from image file. We use the file extension to
+/// decide what file format to use
+ConversionErrorType ImgUtl_LoadBitmap( const char *pszFilename, Bitmap_t &bitmap );
+
+/// Load an image direct from memory buffer
+ConversionErrorType ImgUtl_LoadBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap, ImageFileFormat eImageFileFormat );
+
+/// Save a bitmap to memory buffer
+ConversionErrorType ImgUtl_SaveBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap, ImageFileFormat eImageFileFormat );
+
+/// Load a PNG direct from memory buffer
+ConversionErrorType ImgUtl_LoadPNGBitmapFromBuffer( CUtlBuffer &fileData, Bitmap_t &bitmap );
+
+/// Get the size of a PNG from a buffer
+ConversionErrorType ImgUtl_GetPNGSize( CUtlBuffer &fileData, uint32_t &uWidth, uint32_t &uHeight );
+
+/// Save a bitmap in PNG format to memory buffer
+ConversionErrorType ImgUtl_SavePNGBitmapToBuffer( CUtlBuffer &fileData, const Bitmap_t &bitmap );
+
+/// Resize a bitmap. This currently only works for RGBA images!
+ConversionErrorType ImgUtl_ResizeBitmap( Bitmap_t &destBitmap, int nWidth, int nHeight, const Bitmap_t *pImgSource = NULL );
+
+#endif // IMAGECONVERSION_H
diff --git a/src/common/language.cpp b/src/common/language.cpp
index 33877f60..df6c2e39 100644
--- a/src/common/language.cpp
+++ b/src/common/language.cpp
@@ -30,33 +30,34 @@ struct Language_t
static const Language_t s_LanguageNames[] =
{
- { "None", "none", "None", "none", k_Lang_None, 0 },
- { "English", "english", "#GameUI_Language_English", "en_US", k_Lang_English, 1033 },
- { "German", "german", "#GameUI_Language_German", "de_DE", k_Lang_German, 1031 } ,
- { "French", "french", "#GameUI_Language_French", "fr_FR", k_Lang_French, 1036 } ,
- { "Italian", "italian", "#GameUI_Language_Italian", "it_IT", k_Lang_Italian, 1040 } ,
- { "Korean", "koreana", "#GameUI_Language_Korean", "ko_KR", k_Lang_Korean, 1042 } ,
- { "Spanish", "spanish", "#GameUI_Language_Spanish", "es_ES", k_Lang_Spanish, 1034 },
- { "Simplified_Chinese", "schinese", "#GameUI_Language_Simplified_Chinese", "zh_CN", k_Lang_Simplified_Chinese, 2052 },
- { "Traditional_Chinese", "tchinese", "#GameUI_Language_Traditional_Chinese", "zh_TW", k_Lang_Traditional_Chinese, 1028 },
- { "Russian", "russian", "#GameUI_Language_Russian", "ru_RU", k_Lang_Russian, 1049 } ,
- { "Thai", "thai", "#GameUI_Language_Thai", "th_TH", k_Lang_Thai, 1054 } ,
- { "Japanese", "japanese", "#GameUI_Language_Japanese", "ja_JP", k_Lang_Japanese, 1041 } ,
- { "Portuguese", "portuguese", "#GameUI_Language_Portuguese", "pt_PT", k_Lang_Portuguese, 2070 } ,
- { "Polish", "polish", "#GameUI_Language_Polish", "pl_PL", k_Lang_Polish, 1045 } ,
- { "Danish", "danish", "#GameUI_Language_Danish", "da_DK", k_Lang_Danish, 1030 } ,
- { "Dutch", "dutch", "#GameUI_Language_Dutch", "nl_NL", k_Lang_Dutch, 1043 } ,
- { "Finnish", "finnish", "#GameUI_Language_Finnish", "fi_FI", k_Lang_Finnish, 1035 } ,
- { "Norwegian", "norwegian", "#GameUI_Language_Norwegian", "no_NO", k_Lang_Norwegian, 1044 } ,
- { "Swedish", "swedish", "#GameUI_Language_Swedish", "sv_SE", k_Lang_Swedish, 1053 } ,
- { "Romanian", "romanian", "#GameUI_Language_Romanian", "ro_RO", k_Lang_Romanian, 1048 } ,
- { "Turkish", "turkish", "#GameUI_Language_Turkish", "tr_TR", k_Lang_Turkish, 1055 } ,
- { "Hungarian", "hungarian", "#GameUI_Language_Hungarian", "hu_HU", k_Lang_Hungarian, 1038 } ,
- { "Czech", "czech", "#GameUI_Language_Czech", "cs_CZ", k_Lang_Czech, 1029 } ,
- { "Brazilian", "brazilian", "#GameUI_Language_Brazilian", "pt_BR", k_Lang_Brazilian, 1046 } ,
- { "Bulgarian", "bulgarian", "#GameUI_Language_Bulgarian", "bg_BG", k_Lang_Bulgarian, 1026 } ,
- { "Greek", "greek", "#GameUI_Language_Greek", "el_GR", k_Lang_Greek, 1032 },
- { "Ukrainian", "ukrainian", "#GameUI_Language_Ukrainian", "uk_UA", k_Lang_Ukrainian, 1058 },
+ { "None", "none", "None", "none", k_Lang_None, 0 },
+ { "English", "english", "#GameUI_Language_English", "en_US", k_Lang_English, 1033 },
+ { "German", "german", "#GameUI_Language_German", "de_DE", k_Lang_German, 1031 },
+ { "French", "french", "#GameUI_Language_French", "fr_FR", k_Lang_French, 1036 },
+ { "Italian", "italian", "#GameUI_Language_Italian", "it_IT", k_Lang_Italian, 1040 },
+ { "Korean", "koreana", "#GameUI_Language_Korean", "ko_KR", k_Lang_Korean, 1042 },
+ { "Spanish", "spanish", "#GameUI_Language_Spanish", "es_ES", k_Lang_Spanish, 1034 },
+ { "Simplified_Chinese", "schinese", "#GameUI_Language_Simplified_Chinese", "zh_CN", k_Lang_Simplified_Chinese, 2052 },
+ { "Traditional_Chinese", "tchinese", "#GameUI_Language_Traditional_Chinese", "zh_TW", k_Lang_Traditional_Chinese, 1028 },
+ { "Russian", "russian", "#GameUI_Language_Russian", "ru_RU", k_Lang_Russian, 1049 },
+ { "Thai", "thai", "#GameUI_Language_Thai", "th_TH", k_Lang_Thai, 1054 },
+ { "Japanese", "japanese", "#GameUI_Language_Japanese", "ja_JP", k_Lang_Japanese, 1041 },
+ { "Portuguese", "portuguese", "#GameUI_Language_Portuguese", "pt_PT", k_Lang_Portuguese, 2070 },
+ { "Polish", "polish", "#GameUI_Language_Polish", "pl_PL", k_Lang_Polish, 1045 },
+ { "Danish", "danish", "#GameUI_Language_Danish", "da_DK", k_Lang_Danish, 1030 },
+ { "Dutch", "dutch", "#GameUI_Language_Dutch", "nl_NL", k_Lang_Dutch, 1043 },
+ { "Finnish", "finnish", "#GameUI_Language_Finnish", "fi_FI", k_Lang_Finnish, 1035 },
+ { "Norwegian", "norwegian", "#GameUI_Language_Norwegian", "no_NO", k_Lang_Norwegian, 1044 },
+ { "Swedish", "swedish", "#GameUI_Language_Swedish", "sv_SE", k_Lang_Swedish, 1053 },
+ { "Romanian", "romanian", "#GameUI_Language_Romanian", "ro_RO", k_Lang_Romanian, 1048 },
+ { "Turkish", "turkish", "#GameUI_Language_Turkish", "tr_TR", k_Lang_Turkish, 1055 },
+ { "Hungarian", "hungarian", "#GameUI_Language_Hungarian", "hu_HU", k_Lang_Hungarian, 1038 },
+ { "Czech", "czech", "#GameUI_Language_Czech", "cs_CZ", k_Lang_Czech, 1029 },
+ { "Brazilian", "brazilian", "#GameUI_Language_Brazilian", "pt_BR", k_Lang_Brazilian, 1046 },
+ { "Bulgarian", "bulgarian", "#GameUI_Language_Bulgarian", "bg_BG", k_Lang_Bulgarian, 1026 },
+ { "Greek", "greek", "#GameUI_Language_Greek", "el_GR", k_Lang_Greek, 1032 },
+ { "Ukrainian", "ukrainian", "#GameUI_Language_Ukrainian", "uk_UA", k_Lang_Ukrainian, 1058 },
+ { "Latam_Spanish", "latam", "#GameUI_Language_Latam_Spanish", "es_419", k_Lang_Latam_Spanish, 1034 },
};
//-----------------------------------------------------------------------------
diff --git a/src/common/language.h b/src/common/language.h
index b16c492f..9c55cb6f 100644
--- a/src/common/language.h
+++ b/src/common/language.h
@@ -41,6 +41,7 @@ enum ELanguage
k_Lang_Bulgarian,
k_Lang_Greek,
k_Lang_Ukrainian,
+ k_Lang_Latam_Spanish,
k_Lang_MAX
};
diff --git a/src/common/lzma/lzma.h b/src/common/lzma/lzma.h
index 01bd1ef9..9696c6fd 100644
--- a/src/common/lzma/lzma.h
+++ b/src/common/lzma/lzma.h
@@ -32,6 +32,14 @@ unsigned char *pInput,
unsigned int inputSize,
unsigned int *pOutputSize );
+//-----------------------------------------------------------------------------
+// Above, but returns null if compression would not yield a size improvement
+//-----------------------------------------------------------------------------
+unsigned char *LZMA_OpportunisticCompress(
+unsigned char *pInput,
+unsigned int inputSize,
+unsigned int *pOutputSize );
+
//-----------------------------------------------------------------------------
// Decoding glue. Returns TRUE if succesful.
//-----------------------------------------------------------------------------
diff --git a/src/common/movieobjects/timeutils.cpp b/src/common/movieobjects/timeutils.cpp
new file mode 100644
index 00000000..e232617f
--- /dev/null
+++ b/src/common/movieobjects/timeutils.cpp
@@ -0,0 +1,200 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#include "movieobjects/timeutils.h"
+
+#include "tier0/dbg.h"
+#include "mathlib/mathlib.h"
+
+#include
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+// DmeFramerate_t
+//
+// exact (rational) representation of common framerates - any integral or ntsc framerate
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+DmeFramerate_t::DmeFramerate_t( float fps )
+{
+ SetFramerate( fps );
+}
+
+DmeFramerate_t::DmeFramerate_t( int fps /*= 0*/ ) :
+ m_num( fps ), m_den( 10000 )
+{
+}
+
+DmeFramerate_t::DmeFramerate_t( int nNumerator, int nDenominator ) :
+ m_num( nNumerator ), m_den( nDenominator * 10000 )
+{
+}
+
+void DmeFramerate_t::SetFramerate( float flFrameRate )
+{
+ if ( IsIntegralValue( flFrameRate ) )
+ {
+ SetFramerate( RoundFloatToInt( flFrameRate ) );
+ }
+ else if ( IsIntegralValue( flFrameRate * 1001.0f / 1000.0f ) ) // 1001 is the ntsc divisor (30*1000/1001 = 29.97, etc)
+ {
+ SetFramerateNTSC( RoundFloatToInt( flFrameRate * 1001.0f / 1000.0f ) );
+ }
+ else
+ {
+ Assert( 0 );
+ SetFramerate( RoundFloatToInt( flFrameRate ) );
+ }
+}
+
+void DmeFramerate_t::SetFramerate( int fps )
+{
+ m_num = fps;
+ m_den = 10000;
+}
+
+// other (uncommon) options besides 30(29.97 - ntsc video) are 24 (23.976 - ntsc film) and 60 (59.94 - ntsc progressive)
+void DmeFramerate_t::SetFramerateNTSC( int multiplier /*= 30*/ )
+{
+ // ntsc = 30 fps * 1000 / 1001
+ // = ( 30 / 10000 fptms ) * 1000 / 1001
+ // = 30 / 10010
+ m_num = multiplier;
+ m_den = 10010;
+}
+
+float DmeFramerate_t::GetFramesPerSecond() const
+{
+ return 10000.0f * m_num / float( m_den );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+// DmeTime_t
+//
+// representing time as integral tenths of a millisecond (tms)
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+DmeTime_t::DmeTime_t( int frame, DmeFramerate_t framerate )
+{
+ int64 num = int64( framerate.m_num );
+ int64 prod = frame * int64( framerate.m_den );
+ // add signed offset to force integer truncation (towards 0) to give us truncation towards -inf
+ if ( frame < 0 )
+ {
+ prod -= num - 1;
+ }
+ m_tms = int( prod / num ); // round tms towards 0
+}
+
+
+// float operators - comment these out to find potentially incorrect uses of DmeTime_t
+
+DmeTime_t DmeTime_t::operator*=( float f )
+{
+ m_tms = int( floor( m_tms * f + 0.5f ) );
+ return *this;
+}
+
+DmeTime_t DmeTime_t::operator/=( float f )
+{
+ m_tms = int( floor( m_tms / f + 0.5f ) );
+ return *this;
+}
+
+
+// helper methods
+
+void DmeTime_t::Clamp( DmeTime_t lo, DmeTime_t hi )
+{
+ m_tms = clamp( m_tms, lo.m_tms, hi.m_tms );
+}
+
+bool DmeTime_t::IsInRange( DmeTime_t lo, DmeTime_t hi ) const
+{
+ return m_tms >= lo.m_tms && m_tms < hi.m_tms;
+}
+
+
+// helper functions
+
+float GetFractionOfTimeBetween( DmeTime_t t, DmeTime_t start, DmeTime_t end, bool bClamp /*= false*/ )
+{
+ return GetFractionOfTime( t - start, end - start, bClamp );
+}
+
+float GetFractionOfTime( DmeTime_t t, DmeTime_t duration, bool bClamp /*= false*/ )
+{
+ if ( duration == DMETIME_ZERO )
+ return 0.0f;
+
+ if ( bClamp )
+ {
+ t.Clamp( DMETIME_ZERO, duration );
+ }
+ return t.m_tms / float( duration.m_tms );
+}
+
+int FrameForTime( DmeTime_t t, DmeFramerate_t framerate )
+{
+ return t.CurrentFrame( framerate );
+}
+
+
+// framerate-dependent conversions to/from frames
+
+int DmeTime_t::CurrentFrame( DmeFramerate_t framerate, bool bRoundDown ) const
+{
+ int64 den = int64( framerate.m_den );
+ int64 num = int64( framerate.m_num );
+ int64 prod = int64( m_tms ) * num;
+
+ // times within this range are considered on a frame: (frame*den/num - 1, frame*den/num]
+ // this follows from the truncation towards -inf behavior of the frame,framerate constructor above
+ // the following logic is there to ensure the above rule,
+ // while working around the truncation towards 0 behavior of integer divide
+ if ( m_tms < 0 )
+ {
+ if ( bRoundDown )
+ prod -= den - num;
+ }
+ else
+ {
+ if ( bRoundDown )
+ prod += num - 1;
+ else
+ prod += den - 1;
+ }
+ return int( prod / den );
+}
+
+DmeTime_t DmeTime_t::TimeAtCurrentFrame( DmeFramerate_t framerate, bool bRoundDown ) const
+{
+ int frame = CurrentFrame( framerate, bRoundDown );
+ return DmeTime_t( frame, framerate );
+}
+DmeTime_t DmeTime_t::TimeAtNextFrame( DmeFramerate_t framerate ) const
+{
+ // since we always round towards -inf, go to next frame whether we're on a frame or not
+ int frame = CurrentFrame( framerate, true );
+ return DmeTime_t( frame + 1, framerate );
+}
+DmeTime_t DmeTime_t::TimeAtPrevFrame( DmeFramerate_t framerate ) const
+{
+ int frame = CurrentFrame( framerate, false );
+ return DmeTime_t( frame - 1, framerate ); // we're exactly on a frame
+}
+
+
+int DmeTime_t::RoundSecondsToTMS( float sec )
+{
+ return floor( 10000.0f * sec + 0.5f ); // round at half-tms boundary
+}
+
+int DmeTime_t::RoundSecondsToTMS( double sec )
+{
+ return floor( 10000.0 * sec + 0.5 ); // round at half-tms boundary
+}
diff --git a/src/common/protoutils.cpp b/src/common/protoutils.cpp
new file mode 100644
index 00000000..2373b051
--- /dev/null
+++ b/src/common/protoutils.cpp
@@ -0,0 +1,31 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#include "cbase.h"
+#include "protoutils.h"
+
+#include "google/protobuf/message.h"
+
+//-----------------------------------------------------------------------------
+bool ValveProtoUtils::MessageHasExactFields( const google::protobuf::Message &msg,
+ std::initializer_list fields )
+{
+ auto &desc = *msg.GetDescriptor();
+ return ValveProtoUtils::MessageHasExactFields( desc, std::move( fields ) );
+}
+
+//-----------------------------------------------------------------------------
+bool ValveProtoUtils::MessageHasExactFields( const google::protobuf::Descriptor &msgDesc,
+ std::initializer_list fields )
+{
+ int nFields = msgDesc.field_count();
+ if ( nFields != (int)fields.size() )
+ { return false; }
+
+ for ( int field : fields )
+ {
+ if ( msgDesc.FindFieldByNumber( field ) == nullptr )
+ { return false; }
+ }
+
+ return true;
+}
diff --git a/src/common/protoutils.h b/src/common/protoutils.h
new file mode 100644
index 00000000..1779fa7f
--- /dev/null
+++ b/src/common/protoutils.h
@@ -0,0 +1,19 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#ifndef VALVE_PROTO_UTILS_H
+#define VALVE_PROTO_UTILS_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include
+
+namespace google { namespace protobuf { class Message; class Descriptor; }; };
+
+namespace ValveProtoUtils {
+ // Allows you to assert a message messages this field list for code that should be checked upon message changes
+ bool MessageHasExactFields( const google::protobuf::Descriptor &desc, std::initializer_list fields );
+ bool MessageHasExactFields( const google::protobuf::Message &msg, std::initializer_list fields );
+};
+
+#endif // VALVE_PROTO_UTILS_H
diff --git a/src/common/replay/basereplayserializeable.h b/src/common/replay/basereplayserializeable.h
index 7414ab5e..1b2c920b 100644
--- a/src/common/replay/basereplayserializeable.h
+++ b/src/common/replay/basereplayserializeable.h
@@ -40,4 +40,4 @@ private:
//----------------------------------------------------------------------------------------
-#endif // REPLAYSERIALIIZEABLE_H
\ No newline at end of file
+#endif // REPLAYSERIALIIZEABLE_H
diff --git a/src/common/replay/iclientreplay.h b/src/common/replay/iclientreplay.h
index 1d4b53d8..4cdf09af 100644
--- a/src/common/replay/iclientreplay.h
+++ b/src/common/replay/iclientreplay.h
@@ -61,4 +61,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // ICLIENTREPLAY_H
\ No newline at end of file
+#endif // ICLIENTREPLAY_H
diff --git a/src/common/replay/ienginereplay.h b/src/common/replay/ienginereplay.h
index 98de9495..8258ddc7 100644
--- a/src/common/replay/ienginereplay.h
+++ b/src/common/replay/ienginereplay.h
@@ -113,4 +113,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IENGINEREPLAY_H
\ No newline at end of file
+#endif // IENGINEREPLAY_H
diff --git a/src/common/replay/iqueryablereplayitem.h b/src/common/replay/iqueryablereplayitem.h
index 6e3d3f3e..3a70b83f 100644
--- a/src/common/replay/iqueryablereplayitem.h
+++ b/src/common/replay/iqueryablereplayitem.h
@@ -43,4 +43,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IQUERYABLEREPLAYITEM_H
\ No newline at end of file
+#endif // IQUERYABLEREPLAYITEM_H
diff --git a/src/common/replay/irecordingsessionmanager.h b/src/common/replay/irecordingsessionmanager.h
index 23cdf650..dfca90dc 100644
--- a/src/common/replay/irecordingsessionmanager.h
+++ b/src/common/replay/irecordingsessionmanager.h
@@ -30,4 +30,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IRECORDINGSESSIONMANAGER_H
\ No newline at end of file
+#endif // IRECORDINGSESSIONMANAGER_H
diff --git a/src/common/replay/ireplaydemoplayer.h b/src/common/replay/ireplaydemoplayer.h
index 1a8a1d5a..a9925fbb 100644
--- a/src/common/replay/ireplaydemoplayer.h
+++ b/src/common/replay/ireplaydemoplayer.h
@@ -39,4 +39,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYDEMOPLAYER_H
\ No newline at end of file
+#endif // IREPLAYDEMOPLAYER_H
diff --git a/src/common/replay/ireplayerrorsystem.h b/src/common/replay/ireplayerrorsystem.h
index cc39b7e1..96d5430f 100644
--- a/src/common/replay/ireplayerrorsystem.h
+++ b/src/common/replay/ireplayerrorsystem.h
@@ -30,4 +30,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYERRORSYSYTEM_H
\ No newline at end of file
+#endif // IREPLAYERRORSYSYTEM_H
diff --git a/src/common/replay/ireplayfactory.h b/src/common/replay/ireplayfactory.h
index 0aad205a..97a14af3 100644
--- a/src/common/replay/ireplayfactory.h
+++ b/src/common/replay/ireplayfactory.h
@@ -28,4 +28,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYFACTORY_H
\ No newline at end of file
+#endif // IREPLAYFACTORY_H
diff --git a/src/common/replay/ireplaymovie.h b/src/common/replay/ireplaymovie.h
index 2a2caee3..245637ec 100644
--- a/src/common/replay/ireplaymovie.h
+++ b/src/common/replay/ireplaymovie.h
@@ -39,4 +39,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYMOVIE_H
\ No newline at end of file
+#endif // IREPLAYMOVIE_H
diff --git a/src/common/replay/ireplaymoviemanager.h b/src/common/replay/ireplaymoviemanager.h
index 40f605f0..21c6e7dc 100644
--- a/src/common/replay/ireplaymoviemanager.h
+++ b/src/common/replay/ireplaymoviemanager.h
@@ -53,4 +53,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYMOVIEMANAGER_H
\ No newline at end of file
+#endif // IREPLAYMOVIEMANAGER_H
diff --git a/src/common/replay/ireplayrenderqueue.h b/src/common/replay/ireplayrenderqueue.h
index 320d90e4..b3a799ea 100644
--- a/src/common/replay/ireplayrenderqueue.h
+++ b/src/common/replay/ireplayrenderqueue.h
@@ -29,4 +29,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYRENDERQUEUE_H
\ No newline at end of file
+#endif // IREPLAYRENDERQUEUE_H
diff --git a/src/common/replay/ireplayscreenshotsystem.h b/src/common/replay/ireplayscreenshotsystem.h
index 82166a45..e587f300 100644
--- a/src/common/replay/ireplayscreenshotsystem.h
+++ b/src/common/replay/ireplayscreenshotsystem.h
@@ -31,4 +31,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYSCREENSHOTSYSTEM_H
\ No newline at end of file
+#endif // IREPLAYSCREENSHOTSYSTEM_H
diff --git a/src/common/replay/ireplayserializeable.h b/src/common/replay/ireplayserializeable.h
index cc94628d..97aa0626 100644
--- a/src/common/replay/ireplayserializeable.h
+++ b/src/common/replay/ireplayserializeable.h
@@ -45,4 +45,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYSERIALIIZEABLE_H
\ No newline at end of file
+#endif // IREPLAYSERIALIIZEABLE_H
diff --git a/src/common/replay/ireplaysessionrecorder.h b/src/common/replay/ireplaysessionrecorder.h
index 6c5f905d..50c8a6a9 100644
--- a/src/common/replay/ireplaysessionrecorder.h
+++ b/src/common/replay/ireplaysessionrecorder.h
@@ -24,4 +24,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYSESSIONRECORDER_H
\ No newline at end of file
+#endif // IREPLAYSESSIONRECORDER_H
diff --git a/src/common/replay/ireplaysystem.h b/src/common/replay/ireplaysystem.h
index 0f468839..b4ba0f0f 100644
--- a/src/common/replay/ireplaysystem.h
+++ b/src/common/replay/ireplaysystem.h
@@ -57,4 +57,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // IREPLAYSYSTEM_H
\ No newline at end of file
+#endif // IREPLAYSYSTEM_H
diff --git a/src/common/replay/iserverengine.h b/src/common/replay/iserverengine.h
index f4cd3299..79e91102 100644
--- a/src/common/replay/iserverengine.h
+++ b/src/common/replay/iserverengine.h
@@ -24,4 +24,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // ISERVERENGINE_H
\ No newline at end of file
+#endif // ISERVERENGINE_H
diff --git a/src/common/replay/iserverreplay.h b/src/common/replay/iserverreplay.h
index 3ab5c7f0..16a73d39 100644
--- a/src/common/replay/iserverreplay.h
+++ b/src/common/replay/iserverreplay.h
@@ -34,4 +34,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // ISERVERREPLAY_H
\ No newline at end of file
+#endif // ISERVERREPLAY_H
diff --git a/src/common/replay/performance.h b/src/common/replay/performance.h
index a38e1163..0563baae 100644
--- a/src/common/replay/performance.h
+++ b/src/common/replay/performance.h
@@ -60,4 +60,4 @@ private:
//----------------------------------------------------------------------------------------
-#endif // REPLAYPERFORMANCE_H
\ No newline at end of file
+#endif // REPLAYPERFORMANCE_H
diff --git a/src/common/replay/replay.h b/src/common/replay/replay.h
index a0d1cb33..092e3192 100644
--- a/src/common/replay/replay.h
+++ b/src/common/replay/replay.h
@@ -143,4 +143,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // REPLAY_H
\ No newline at end of file
+#endif // REPLAY_H
diff --git a/src/common/replay/replayhandle.h b/src/common/replay/replayhandle.h
index 2dd84148..950d8d96 100644
--- a/src/common/replay/replayhandle.h
+++ b/src/common/replay/replayhandle.h
@@ -22,4 +22,4 @@ typedef uint32 ReplayHandle_t;
//----------------------------------------------------------------------------------------
-#endif // REPLAYHANDLE_H
\ No newline at end of file
+#endif // REPLAYHANDLE_H
diff --git a/src/common/replay/replaylib.h b/src/common/replay/replaylib.h
index 9f309807..dad3c0b6 100644
--- a/src/common/replay/replaylib.h
+++ b/src/common/replay/replaylib.h
@@ -18,4 +18,4 @@ bool ReplayLib_Init( const char *pGameDir, IClientReplayContext *pClientReplayCo
//----------------------------------------------------------------------------------------
-#endif // REPLAYLIB_H
\ No newline at end of file
+#endif // REPLAYLIB_H
diff --git a/src/common/replay/replaytime.h b/src/common/replay/replaytime.h
index eb1c3295..4e2d6a33 100644
--- a/src/common/replay/replaytime.h
+++ b/src/common/replay/replaytime.h
@@ -54,4 +54,4 @@ public:
//----------------------------------------------------------------------------------------
-#endif // REPLAYTIME_H
\ No newline at end of file
+#endif // REPLAYTIME_H
diff --git a/src/common/replay/shared_defs.h b/src/common/replay/shared_defs.h
index fa4b0b78..9c20b727 100644
--- a/src/common/replay/shared_defs.h
+++ b/src/common/replay/shared_defs.h
@@ -37,7 +37,7 @@
//----------------------------------------------------------------------------------------
-#define BUILD_CURL ( defined( WIN32 ) && !defined( _X360 ) ) || defined( POSIX )
+#define BUILD_CURL ( defined( WIN32 ) && _MSC_VER < 1900 && !defined( _X360 ) ) || defined( POSIX )
//----------------------------------------------------------------------------------------
diff --git a/src/common/simplebitstring.cpp b/src/common/simplebitstring.cpp
new file mode 100644
index 00000000..ed1c044c
--- /dev/null
+++ b/src/common/simplebitstring.cpp
@@ -0,0 +1,234 @@
+
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+//*****************************************************************************
+//
+// Contents:
+//
+// CSimpleBitString
+//
+// Authors: chrisn
+//
+// Target restrictions:
+//
+// Tool restrictions:
+//
+// Things to do:
+//
+//*****************************************************************************
+
+
+//*****************************************************************************
+//
+// Include files required to build and use this module.
+//
+//*****************************************************************************
+
+// Precompiled header (must come first - includes project common headers)
+//#include "stdafx.h"
+#include "tier0/platform.h"
+#include "tier1/utlvector.h"
+#include "simplebitstring.h"
+
+
+
+//*****************************************************************************
+//
+// Class definitions:
+//
+//*****************************************************************************
+
+//
+// class CSimpleBitString::iterator
+//
+
+
+//-----------------------------------------------------------------------------
+//
+// Function:
+//
+//-----------------------------------------------------------------------------
+void CSimpleBitString::AppendBits( uint64 u64Data, uint32 NumSignificantLowBitsOfData )
+{
+ Assert
+ (
+ NumSignificantLowBitsOfData <= 64
+ );
+
+ while ( NumSignificantLowBitsOfData > 0 )
+ {
+ // Clear top bits of data
+ if ( NumSignificantLowBitsOfData < 64 )
+ u64Data &= ( (1ULL << NumSignificantLowBitsOfData) - 1 ); // will fail for 64 bits
+
+ uint32 Idx = m_uNumBits / 8;
+ uint32 NumUsedBitsInLastByte = m_uNumBits % 8;
+
+ uint32 NumAvailableBitsInLastByte = 8 - NumUsedBitsInLastByte;
+
+ uint32 NumBitsToPutInThisByte
+ = min( NumAvailableBitsInLastByte, NumSignificantLowBitsOfData );
+
+ uint8 BitsForThisByte
+ = ( u64Data >> (NumSignificantLowBitsOfData - NumBitsToPutInThisByte) )
+ & ( (1ULL << NumBitsToPutInThisByte) - 1 );
+
+ m_vecU8[Idx] |= ( BitsForThisByte
+ << ( NumAvailableBitsInLastByte - NumBitsToPutInThisByte ) );
+
+ m_uNumBits += NumBitsToPutInThisByte;
+
+ NumAvailableBitsInLastByte -= NumBitsToPutInThisByte;
+ if ( NumAvailableBitsInLastByte == 0 )
+ {
+ m_vecU8[ m_vecU8.AddToTail() ] = 0x00;
+ }
+
+ // We've used the top N bits of data
+ NumSignificantLowBitsOfData -= NumBitsToPutInThisByte;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Function:
+//
+//-----------------------------------------------------------------------------
+void CSimpleBitString::AppendBits( const uint8 * pData, uint32 NumBitsOfData )
+{
+ Assert( pData );
+
+ uint32 NumBytes = NumBitsOfData / 8;
+ for ( uint32 i = 0; i < NumBytes; ++i )
+ {
+ AppendBits( *(pData++), 8 );
+ }
+ uint32 NumTailBits = NumBitsOfData % 8;
+ AppendBits( (*pData) >> (8U - NumTailBits), NumTailBits );
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Function:
+//
+//-----------------------------------------------------------------------------
+void CSimpleBitString::ReversiblyObfusticateBitsFromStart( uint NumBits, const uint8 * pObfusticationData, size_t uSizeOfObfusticationData )
+{
+ Assert( pObfusticationData );
+
+ if ( NumBits > m_uNumBits
+ || NumBits > uSizeOfObfusticationData * 8
+ )
+ {
+ AssertMsg( false, "ReversiblyObfusticateBitsFromStart(): Bad NumBits" );
+ return; // bugbug taylor bool return
+ }
+
+ uint8 * pBits = & m_vecU8[0];
+
+ uint NumBytes = NumBits / 8;
+ for ( uint i = 0; i < NumBytes; ++i )
+ {
+ *(pBits++) ^= *(pObfusticationData++);
+ }
+ uint NumTailBits = NumBits % 8;
+ if ( NumTailBits > 0 )
+ {
+ *pBits ^= ( *(pObfusticationData++) & (((1U << NumTailBits) - 1) << (8U - NumTailBits) ) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Function:
+//
+//-----------------------------------------------------------------------------
+uint8 CSimpleBitString::GetByteChecksumFromStart( uint NumBits ) const
+{
+ if ( NumBits > m_uNumBits )
+ {
+ AssertMsg( false, "GenerateByteChecksumFromStart(): Bad NumBits" );
+ return 0;
+ }
+
+ uint8 u8Checksum = 0;
+ const uint8 * pBits = & m_vecU8[0];
+
+ uint NumBytes = NumBits / 8;
+ for ( uint i = 0; i < NumBytes; ++i )
+ {
+ u8Checksum += *(pBits++);
+ }
+ uint NumTailBits = NumBits % 8;
+ if ( NumTailBits > 0 )
+ {
+ u8Checksum += ( *(pBits) & (((1U << NumTailBits) - 1) << (8U - NumTailBits) ) );
+ }
+
+ return u8Checksum;
+}
+
+
+
+//
+// class CSimpleBitString::iterator
+//
+uint32 CSimpleBitString::iterator::GetNextBits( uint32 NumBitsToGet )
+{
+ Assert
+ (
+ NumBitsToGet <= 32
+ );
+
+ return static_cast( GetNextBits64( NumBitsToGet ) );
+}
+
+uint64 CSimpleBitString::iterator::GetNextBits64( uint32 NumBitsToGet )
+{
+ Assert
+ (
+ NumBitsToGet <= 64
+ );
+
+ if ( m_uNextBitIdx + NumBitsToGet > m_rSimpleBitString.m_uNumBits )
+ {
+ AssertMsg( false, "Not enough bits in CSimpleBitString" );
+ return 0;
+ }
+
+ uint64 u64Data = 0;
+
+ while ( NumBitsToGet > 0 )
+ {
+ uint32 Idx = m_uNextBitIdx / 8;
+ Assert( Idx < (uint32)m_rSimpleBitString.m_vecU8.Count() );
+
+ uint32 NumConsumedBitsInThisByte = m_uNextBitIdx % 8;
+ uint32 NumAvailableBitsInThisByte = 8 - NumConsumedBitsInThisByte;
+
+ uint32 NumBitsToGetFromThisByte
+ = min( NumAvailableBitsInThisByte, NumBitsToGet );
+
+ uint8 BitsFromThisByte
+ = ( m_rSimpleBitString.m_vecU8[Idx] >> (NumAvailableBitsInThisByte - NumBitsToGetFromThisByte) )
+ & ( (1UL << NumBitsToGetFromThisByte) - 1 );
+
+ u64Data <<= NumBitsToGetFromThisByte;
+ u64Data |= BitsFromThisByte;
+
+ m_uNextBitIdx += NumBitsToGetFromThisByte;
+ NumBitsToGet -= NumBitsToGetFromThisByte;
+ }
+
+ return u64Data;
+}
+
diff --git a/src/common/simplebitstring.h b/src/common/simplebitstring.h
new file mode 100644
index 00000000..7d42d67c
--- /dev/null
+++ b/src/common/simplebitstring.h
@@ -0,0 +1,159 @@
+
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+//*****************************************************************************
+//
+// Contents:
+//
+// CSimpleBitString
+//
+// Authors:
+//
+// Target restrictions:
+//
+// Tool restrictions:
+//
+// Things to do:
+//
+//
+//
+//*****************************************************************************
+
+#ifndef INCLUDED_COMMON_SIMPLEBITSTRING_H
+#define INCLUDED_COMMON_SIMPLEBITSTRING_H
+
+#if defined(_MSC_VER) && (_MSC_VER > 1000)
+#pragma once
+#endif
+
+
+//*****************************************************************************
+//
+// Include files required by this header.
+//
+// Note: Do NOT place any 'using' directives or declarations in header files -
+// put them at the top of the source files that require them.
+// Use fully-qualified names in header files.
+//
+//*****************************************************************************
+
+// All precompiled headers (Stable.h) include this first to give use a common
+// place for including order-dependent library headers (things that need to go first).
+
+
+
+
+
+class CSimpleBitString
+{
+public:
+ explicit CSimpleBitString( uint32 ReserveNumBits = 0 )
+ :
+ m_uNumBits( 0 ),
+ m_vecU8()
+ {
+ m_vecU8.EnsureCapacity( (ReserveNumBits / 8) + 1 );
+ m_vecU8[ m_vecU8.AddToTail() ] = 0x00; // always need 1 byte
+ }
+
+ void clear()
+ {
+ m_uNumBits = 0;
+ m_vecU8.RemoveAll();
+ m_vecU8[ m_vecU8.AddToTail() ] = 0x00; // always need 1 byte
+ }
+
+ void AppendBits( uint64 data, uint32 NumSignificantLowBitsOfData );
+ void AppendBits( const uint8 * pData, uint32 NumBitsOfData );
+
+ void ReversiblyObfusticateBitsFromStart( uint32 NumBits, const uint8 * pObfusticationData, size_t uSizeOfObfusticationData );
+ uint8 GetByteChecksumFromStart( uint32 NumBits ) const;
+
+ uint GetCurrNumBits() const
+ {
+ return m_uNumBits;
+ }
+
+ const uint8 * data() const
+ {
+ return & m_vecU8[0];
+ }
+
+ size_t size() const
+ {
+ return m_vecU8.Count();
+ }
+
+private:
+ uint32 m_uNumBits;
+ CUtlVector m_vecU8;
+
+public:
+
+ // Iterator class for retrieving bits
+ class iterator
+ {
+ public:
+ explicit iterator( const CSimpleBitString & bs )
+ :
+ m_rSimpleBitString( bs ),
+ m_uNextBitIdx( 0 )
+ {
+ }
+
+ void ResetToStart()
+ {
+ m_uNextBitIdx = 0;
+ }
+
+ uint32 GetNumConsumedBits() const
+ {
+ return m_uNextBitIdx;
+ }
+
+ uint32 GetNumRemainingBits() const
+ {
+ return m_rSimpleBitString.m_uNumBits - m_uNextBitIdx;
+ }
+
+ uint32 GetNextBits( uint32 NumBitsToGet );
+ uint64 GetNextBits64( uint32 NumBitsToGet );
+
+ void SkipNextBits( uint32 NumBitsToSkip )
+ {
+ if ( m_uNextBitIdx + NumBitsToSkip > m_rSimpleBitString.m_uNumBits )
+ {
+ AssertMsg( false, "Not enough bits in CSimpleBitString" );
+ NumBitsToSkip = 0;
+ }
+
+ m_uNextBitIdx += NumBitsToSkip;
+ }
+
+ bool operator ==( const iterator & other ) const
+ {
+ return (& m_rSimpleBitString == & other.m_rSimpleBitString)
+ && m_uNextBitIdx == other.m_uNextBitIdx;
+ }
+
+ void DoAssertClassInvariant() const;
+
+ private:
+ const CSimpleBitString & m_rSimpleBitString; //lint !e1725 reference
+ uint32 m_uNextBitIdx;
+ };
+
+ friend class iterator;
+
+};
+
+
+
+
+
+#endif
diff --git a/src/common/SteamCommon.h b/src/common/steamcommon.h
similarity index 100%
rename from src/common/SteamCommon.h
rename to src/common/steamcommon.h
diff --git a/src/common/steamid.cpp b/src/common/steamid.cpp
new file mode 100644
index 00000000..0df52bc9
--- /dev/null
+++ b/src/common/steamid.cpp
@@ -0,0 +1,740 @@
+//========= Copyright � 1996-2004, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+
+#if defined( STEAM ) || defined( HL1 )
+#include "stdafx.h"
+#else
+#include
+#include "dbg.h"
+#include "steamcommon.h"
+#include "steam/steamclientpublic.h"
+#include "strtools.h"
+#endif
+
+#ifdef HL1
+#include "steamcommon.h"
+#include "steam/steamclientpublic.h"
+#endif
+
+#ifndef UINT64_MAX
+#define UINT64_MAX ((uint64)-1)
+#endif
+
+static const char *DecimalToUint64( const char *pchStr, uint64 unLimit,
+ uint64 *punVal )
+{
+ const char *pchStart = pchStr;
+ uint64 unVal = 0;
+
+ while ( *pchStr >= '0' && *pchStr <= '9' )
+ {
+ uint64 unNext = unVal * 10;
+
+ if ( unNext < unVal )
+ {
+ // 64-bit overflow.
+ return NULL;
+ }
+
+ unVal = unNext + (uint64)( *pchStr - '0' );
+ if ( unVal > unLimit )
+ {
+ // Limit overflow.
+ return NULL;
+ }
+
+ pchStr++;
+ }
+ if ( pchStr == pchStart )
+ {
+ // No number at all.
+ return NULL;
+ }
+
+ *punVal = unVal;
+ return pchStr;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+// Input : pchSteamID - text representation of a Steam ID
+//-----------------------------------------------------------------------------
+CSteamID::CSteamID( const char *pchSteamID, EUniverse eDefaultUniverse /* = k_EUniverseInvalid */ )
+{
+ SetFromString( pchSteamID, eDefaultUniverse );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Initializes a steam ID from a string
+// Input : pchSteamID - text representation of a Steam ID
+//-----------------------------------------------------------------------------
+void CSteamID::SetFromString( const char *pchSteamID, EUniverse eDefaultUniverse )
+{
+ uint nAccountID = 0;
+ uint nInstance = 1;
+ EUniverse eUniverse = eDefaultUniverse;
+ EAccountType eAccountType = k_EAccountTypeIndividual;
+#ifdef DBGFLAG_ASSERT
+ // TF Merge -- Assert is debug-only and we have unused variable warnings on :-/
+ const char *pchSteamIDString = pchSteamID;
+#endif
+ CSteamID StrictID;
+
+ StrictID.SetFromStringStrict( pchSteamID, eDefaultUniverse );
+
+ if ( *pchSteamID == '[' )
+ pchSteamID++;
+
+ // BUGBUG Rich use the Q_ functions
+ if ( *pchSteamID == 'A' || *pchSteamID == 'a' )
+ {
+ // This is test only
+ if ( *pchSteamID == 'A' )
+ eAccountType = k_EAccountTypeAnonGameServer;
+ else
+ {
+ eAccountType = k_EAccountTypeAnonUser;
+ nInstance = 0;
+ }
+ pchSteamID++; // skip the A
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+
+ if ( strchr( pchSteamID, '(' ) )
+ sscanf( strchr( pchSteamID, '(' ), "(%u)", &nInstance );
+ const char *pchColon = strchr( pchSteamID, ':' );
+ if ( pchColon && *pchColon != 0 && strchr( pchColon+1, ':' ))
+ {
+ sscanf( pchSteamID, "%u:%u:%u", (uint*)&eUniverse, &nAccountID, &nInstance );
+ }
+ else if ( pchColon )
+ {
+ sscanf( pchSteamID, "%u:%u", (uint*)&eUniverse, &nAccountID );
+ }
+ else
+ {
+ sscanf( pchSteamID, "%u", &nAccountID );
+ }
+
+ if ( nAccountID == 0 )
+ {
+ // i dont care what number you entered
+ CreateBlankAnonLogon(eUniverse);
+ }
+ else
+ {
+ InstancedSet( nAccountID, nInstance, eUniverse, eAccountType );
+ }
+ // Catch cases where we're allowing sloppy input that we
+ // might not want to allow.
+ AssertMsg1( this->operator==( StrictID ), "Steam ID does not pass strict parsing: '%s'", pchSteamIDString );
+ return;
+ }
+ else if (*pchSteamID == 'G')
+ {
+ pchSteamID++; // skip the G
+ eAccountType = k_EAccountTypeGameServer;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'C')
+ {
+ pchSteamID++; // skip the C
+ eAccountType = k_EAccountTypeContentServer;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'g')
+ {
+ pchSteamID++; // skip the g
+ eAccountType = k_EAccountTypeClan;
+ nInstance = 0;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'c')
+ {
+ pchSteamID++; // skip the c
+ eAccountType = k_EAccountTypeChat;
+ nInstance = k_EChatInstanceFlagClan;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'L')
+ {
+ pchSteamID++; // skip the c
+ eAccountType = k_EAccountTypeChat;
+ nInstance = k_EChatInstanceFlagLobby;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'T')
+ {
+ pchSteamID++; // skip the T
+ eAccountType = k_EAccountTypeChat;
+ nInstance = 0; // Anon chat
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'U')
+ {
+ pchSteamID++; // skip the U
+ eAccountType = k_EAccountTypeIndividual;
+ nInstance = 1;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+ else if (*pchSteamID == 'i')
+ {
+ pchSteamID++; // skip the i
+ eAccountType = k_EAccountTypeInvalid;
+ nInstance = 1;
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+
+ if ( strchr( pchSteamID, ':' ) )
+ {
+ if (*pchSteamID == '[')
+ pchSteamID++; // skip the optional [
+ sscanf( pchSteamID, "%u:%u", (uint*)&eUniverse, &nAccountID );
+ if ( eUniverse == k_EUniverseInvalid )
+ eUniverse = eDefaultUniverse;
+ }
+ else
+ {
+ uint64 unVal64 = 0;
+
+ sscanf( pchSteamID, "%llu", &unVal64 );
+ if ( unVal64 > UINT32_MAX )
+ {
+ // Assume a full 64-bit Steam ID.
+ SetFromUint64( unVal64 );
+ // Catch cases where we're allowing sloppy input that we
+ // might not want to allow.
+ AssertMsg1( this->operator==( StrictID ), "Steam ID does not pass strict parsing: '%s'", pchSteamIDString );
+ return;
+ }
+ else
+ {
+ nAccountID = (uint)unVal64;
+ }
+ }
+
+ Assert( (eUniverse > k_EUniverseInvalid) && (eUniverse < k_EUniverseMax) );
+
+ InstancedSet( nAccountID, nInstance, eUniverse, eAccountType );
+
+ // Catch cases where we're allowing sloppy input that we
+ // might not want to allow.
+ AssertMsg1( this->operator==( StrictID ), "Steam ID does not pass strict parsing: '%s'", pchSteamIDString );
+}
+
+// SetFromString allows many partially-correct strings, constraining how
+// we might be able to change things in the future.
+// SetFromStringStrict requires the exact string forms that we support
+// and is preferred when the caller knows it's safe to be strict.
+// Returns whether the string parsed correctly. The ID may
+// still be invalid even if the string parsed correctly.
+// If the string didn't parse correctly the ID will always be invalid.
+bool CSteamID::SetFromStringStrict( const char *pchSteamID, EUniverse eDefaultUniverse )
+{
+ uint nAccountID = 0;
+ uint nInstance = 1;
+ uint unMaxVal = 2;
+ EUniverse eUniverse = eDefaultUniverse;
+ EAccountType eAccountType = k_EAccountTypeIndividual;
+ char chPrefix;
+ bool bBracket = false;
+ bool bValid = true;
+ uint64 unVal[3];
+ const char *pchEnd;
+
+ // Start invalid.
+ Clear();
+
+ if ( !pchSteamID )
+ {
+ return false;
+ }
+
+ if ( *pchSteamID == '[' )
+ {
+ pchSteamID++;
+ bBracket = true;
+ }
+
+ chPrefix = *pchSteamID;
+ switch( chPrefix )
+ {
+ case 'A':
+ // This is test only
+ eAccountType = k_EAccountTypeAnonGameServer;
+ unMaxVal = 3;
+ break;
+
+ case 'a':
+ // This is test only
+ eAccountType = k_EAccountTypeAnonUser;
+ nInstance = 0;
+ unMaxVal = 3;
+ break;
+
+ case 'G':
+ eAccountType = k_EAccountTypeGameServer;
+ break;
+
+ case 'C':
+ eAccountType = k_EAccountTypeContentServer;
+ break;
+
+ case 'g':
+ eAccountType = k_EAccountTypeClan;
+ nInstance = 0;
+ break;
+
+ case 'c':
+ eAccountType = k_EAccountTypeChat;
+ nInstance = k_EChatInstanceFlagClan;
+ break;
+
+ case 'L':
+ eAccountType = k_EAccountTypeChat;
+ nInstance = k_EChatInstanceFlagLobby;
+ break;
+
+ case 'T':
+ eAccountType = k_EAccountTypeChat;
+ nInstance = 0; // Anon chat
+ break;
+
+ case 'U':
+ eAccountType = k_EAccountTypeIndividual;
+ nInstance = 1;
+ break;
+
+ case 'i':
+ eAccountType = k_EAccountTypeInvalid;
+ nInstance = 1;
+ break;
+
+ default:
+ // We're reserving other leading characters so
+ // this should only be the plain-digits case.
+ if (chPrefix < '0' || chPrefix > '9')
+ {
+ bValid = false;
+ }
+ chPrefix = 0;
+ break;
+ }
+
+ if ( chPrefix )
+ {
+ pchSteamID++; // skip the prefix
+ if (*pchSteamID == '-' || *pchSteamID == ':')
+ pchSteamID++; // skip the optional - or :
+ }
+
+ uint unIdx = 0;
+
+ for (;;)
+ {
+ pchEnd = DecimalToUint64( pchSteamID, UINT64_MAX, &unVal[unIdx] );
+ if ( !pchEnd )
+ {
+ bValid = false;
+ break;
+ }
+
+ unIdx++;
+
+ // For 'A' we can have a trailing instance, which must
+ // be the end of the string.
+ if ( *pchEnd == '(' &&
+ chPrefix == 'A' )
+ {
+ if ( unIdx > 2 )
+ {
+ // Two instance IDs provided.
+ bValid = false;
+ }
+
+ pchEnd = DecimalToUint64( pchEnd + 1, k_unSteamAccountInstanceMask, &unVal[2] );
+ if ( !pchEnd ||
+ *pchEnd != ')' )
+ {
+ bValid = false;
+ break;
+ }
+ else
+ {
+ nInstance = (uint)unVal[2];
+
+ pchEnd++;
+ if ( *pchEnd == ':' )
+ {
+ // Not expecting more values.
+ bValid = false;
+ break;
+ }
+ }
+ }
+
+ if ( *pchEnd != ':' )
+ {
+ if ( bBracket )
+ {
+ if ( *pchEnd != ']' ||
+ *(pchEnd + 1) != 0 )
+ {
+ bValid = false;
+ }
+ }
+ else if ( *pchEnd != 0 )
+ {
+ bValid = false;
+ }
+
+ break;
+ }
+
+ if ( unIdx >= unMaxVal )
+ {
+ bValid = false;
+ break;
+ }
+
+ pchSteamID = pchEnd + 1;
+ }
+
+ if ( unIdx > 2 )
+ {
+ if ( unVal[2] <= k_unSteamAccountInstanceMask )
+ {
+ nInstance = (uint)unVal[2];
+ }
+ else
+ {
+ bValid = false;
+ }
+ }
+ if ( unIdx > 1 )
+ {
+ if ( unVal[0] >= k_EUniverseInvalid &&
+ unVal[0] < k_EUniverseMax )
+ {
+ eUniverse = (EUniverse)unVal[0];
+ if ( eUniverse == k_EUniverseInvalid )
+ eUniverse = eDefaultUniverse;
+ }
+ else
+ {
+ bValid = false;
+ }
+
+ if ( unVal[1] <= k_unSteamAccountIDMask )
+ {
+ nAccountID = (uint)unVal[1];
+ }
+ else
+ {
+ bValid = false;
+ }
+ }
+ else if ( unIdx > 0 )
+ {
+ if ( unVal[0] <= k_unSteamAccountIDMask )
+ {
+ nAccountID = (uint)unVal[0];
+ }
+ else if ( !chPrefix )
+ {
+ if ( bValid )
+ {
+ SetFromUint64( unVal[0] );
+ }
+ return bValid;
+ }
+ else
+ {
+ bValid = false;
+ }
+ }
+ else
+ {
+ bValid = false;
+ }
+
+ if ( bValid )
+ {
+ if ( chPrefix == 'A' )
+ {
+ if ( nAccountID == 0 )
+ {
+ // i dont care what number you entered
+ CreateBlankAnonLogon(eUniverse);
+ return bValid;
+ }
+ }
+
+ InstancedSet( nAccountID, nInstance, eUniverse, eAccountType );
+ }
+
+ return bValid;
+}
+
+
+#if defined( INCLUDED_STEAM2_USERID_STRUCTS )
+//-----------------------------------------------------------------------------
+// Purpose: Initializes a steam ID from a Steam2 ID string
+// Input: pchSteam2ID - Steam2 ID (as a string #:#:#) to convert
+// eUniverse - universe this ID belongs to
+// Output: true if successful, false otherwise
+//-----------------------------------------------------------------------------
+bool SteamIDFromSteam2String( const char *pchSteam2ID, EUniverse eUniverse, CSteamID *pSteamIDOut )
+{
+ Assert( pchSteam2ID );
+
+ // Convert the Steam2 ID string to a Steam2 ID structure
+ TSteamGlobalUserID steam2ID;
+ steam2ID.m_SteamInstanceID = 0;
+ steam2ID.m_SteamLocalUserID.Split.High32bits = 0;
+ steam2ID.m_SteamLocalUserID.Split.Low32bits = 0;
+
+ const char *pchTSteam2ID = pchSteam2ID;
+
+ // Customer support is fond of entering steam IDs in the following form: STEAM_n:x:y
+ const char *pchOptionalLeadString = "STEAM_";
+ if ( V_strnicmp( pchSteam2ID, pchOptionalLeadString, V_strlen( pchOptionalLeadString ) ) == 0 )
+ pchTSteam2ID = pchSteam2ID + V_strlen( pchOptionalLeadString );
+
+ char cExtraCharCheck = 0;
+
+ int cFieldConverted = sscanf( pchTSteam2ID, "%hu:%u:%u%c", &steam2ID.m_SteamInstanceID,
+ &steam2ID.m_SteamLocalUserID.Split.High32bits, &steam2ID.m_SteamLocalUserID.Split.Low32bits, &cExtraCharCheck );
+
+ // Validate the conversion ... a special case is steam2 instance ID 1 which is reserved for special DoD handling
+ if ( cExtraCharCheck != 0 || cFieldConverted == EOF || cFieldConverted < 2 || ( cFieldConverted < 3 && steam2ID.m_SteamInstanceID != 1 ) )
+ return false;
+
+ // Now convert to steam ID from the Steam2 ID structure
+ *pSteamIDOut = SteamIDFromSteam2UserID( &steam2ID, eUniverse );
+ return true;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose: Renders the steam ID to a buffer. NOTE: for convenience of calling
+// code, this code returns a pointer to a static buffer and is NOT thread-safe.
+// Output: buffer with rendered Steam ID
+//-----------------------------------------------------------------------------
+const char * CSteamID::Render() const
+{
+ // longest length of returned string is k_cBufLen
+ // [A:%u:%u:%u]
+ // %u == 10 * 3 + 6 == 36, plus terminator == 37
+ const int k_cBufLen = 37;
+
+ const int k_cBufs = 4; // # of static bufs to use (so people can compose output with multiple calls to Render() )
+ static char rgchBuf[k_cBufs][k_cBufLen];
+ static int nBuf = 0;
+ char * pchBuf = rgchBuf[nBuf]; // get pointer to current static buf
+ nBuf ++; // use next buffer for next call to this method
+ nBuf %= k_cBufs;
+
+ if ( k_EAccountTypeAnonGameServer == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[A:%u:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID, m_steamid.m_comp.m_unAccountInstance );
+ }
+ else if ( k_EAccountTypeGameServer == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[G:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( k_EAccountTypeMultiseat == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[M:%u:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID, m_steamid.m_comp.m_unAccountInstance );
+ }
+ else if ( k_EAccountTypePending == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[P:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( k_EAccountTypeContentServer == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[C:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( k_EAccountTypeClan == m_steamid.m_comp.m_EAccountType )
+ {
+ // 'g' for "group"
+ V_snprintf( pchBuf, k_cBufLen, "[g:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( k_EAccountTypeChat == m_steamid.m_comp.m_EAccountType )
+ {
+ if ( m_steamid.m_comp.m_unAccountInstance & k_EChatInstanceFlagClan )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[c:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( m_steamid.m_comp.m_unAccountInstance & k_EChatInstanceFlagLobby )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[L:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else // Anon chat
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[T:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ }
+ else if ( k_EAccountTypeInvalid == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[I:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( k_EAccountTypeIndividual == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[U:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else if ( k_EAccountTypeAnonUser == m_steamid.m_comp.m_EAccountType )
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[a:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ else
+ {
+ V_snprintf( pchBuf, k_cBufLen, "[i:%u:%u]", m_steamid.m_comp.m_EUniverse, m_steamid.m_comp.m_unAccountID );
+ }
+ return pchBuf;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Renders the passed-in steam ID to a buffer. NOTE: for convenience of calling
+// code, this code returns a pointer to a static buffer and is NOT thread-safe.
+// Input: 64-bit representation of Steam ID to render
+// Output: buffer with rendered Steam ID
+//-----------------------------------------------------------------------------
+const char * CSteamID::Render( uint64 ulSteamID )
+{
+ CSteamID steamID( ulSteamID );
+ return steamID.Render();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: some steamIDs are for internal use only
+// This is really debug code, but we run with asserts on in retail, so ...
+//-----------------------------------------------------------------------------
+bool CSteamID::BValidExternalSteamID() const
+{
+ if ( m_steamid.m_comp.m_EAccountType == k_EAccountTypePending )
+ return false;
+ if ( m_steamid.m_comp.m_EAccountType != k_EAccountTypeAnonGameServer && m_steamid.m_comp.m_EAccountType != k_EAccountTypeContentServer && m_steamid.m_comp.m_EAccountType != k_EAccountTypeAnonUser )
+ {
+ if ( m_steamid.m_comp.m_unAccountID == 0 && m_steamid.m_comp.m_unAccountInstance == 0 )
+ return false;
+ }
+ return true;
+}
+
+#ifdef STEAM
+//-----------------------------------------------------------------------------
+// Purpose: Returns the matching chat steamID, with the default instance of 0
+// Input: SteamID, either a Clan or a Chat type
+// Output: SteamID with account type changed to chat, and the Clan flag set.
+// If account type was not chat to start with, instance will be set to 0
+//-----------------------------------------------------------------------------
+CSteamID ChatIDFromSteamID( const CSteamID &steamID )
+{
+ if ( steamID.GetEAccountType() == k_EAccountTypeChat )
+ return steamID;
+
+ return ChatIDFromClanID( steamID );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the matching chat steamID, with the default instance of 0
+// Input: SteamID, either a Clan type or a Chat type w/ the Clan flag set
+// Output: SteamID with account type changed to clan.
+// If account type was not clan to start with, instance will be set to 0
+//-----------------------------------------------------------------------------
+CSteamID ClanIDFromSteamID( const CSteamID &steamID )
+{
+ if ( steamID.GetEAccountType() == k_EAccountTypeClan )
+ return steamID;
+
+ return ClanIDFromChatID( steamID );
+}
+
+
+// Asserts steamID type before conversion
+CSteamID ChatIDFromClanID( const CSteamID &steamIDClan )
+{
+ Assert( steamIDClan.GetEAccountType() == k_EAccountTypeClan );
+
+ return CSteamID( steamIDClan.GetAccountID(), k_EChatInstanceFlagClan, steamIDClan.GetEUniverse(), k_EAccountTypeChat );
+}
+
+
+// Asserts steamID type before conversion
+CSteamID ClanIDFromChatID( const CSteamID &steamIDChat )
+{
+ Assert( steamIDChat.GetEAccountType() == k_EAccountTypeChat );
+ Assert( k_EChatInstanceFlagClan & steamIDChat.GetUnAccountInstance() );
+
+ return CSteamID( steamIDChat.GetAccountID(), 0, steamIDChat.GetEUniverse(), k_EAccountTypeClan );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: CGameID "hidden" functions
+// move these somewhere else maybe
+//-----------------------------------------------------------------------------
+CGameID::CGameID( const char *pchGameID )
+{
+ m_ulGameID = 0;
+
+ sscanf( pchGameID, "%llu", &m_ulGameID );
+
+ switch ( m_gameID.m_nType )
+ {
+ case k_EGameIDTypeApp:
+ case k_EGameIDTypeGameMod:
+ case k_EGameIDTypeShortcut:
+ case k_EGameIDTypeP2P:
+ break;
+ default:
+ AssertMsg( false, "Unknown GameID type" );
+ m_ulGameID = 0;
+ break;
+ }
+}
+
+
+// renders this Game ID to string
+const char * CGameID::Render() const
+{
+ // longest buffer is log10(2**64) == 20 + 1 == 21
+ const int k_cBufLen = 21;
+
+ const int k_cBufs = 4; // # of static bufs to use (so people can compose output with multiple calls to Render() )
+ static char rgchBuf[k_cBufs][k_cBufLen];
+ static int nBuf = 0;
+ char * pchBuf = rgchBuf[nBuf]; // get pointer to current static buf
+ nBuf ++; // use next buffer for next call to this method
+ nBuf %= k_cBufs;
+
+ V_snprintf( pchBuf, k_cBufLen, "%llu", m_ulGameID );
+
+ return pchBuf;
+}
+
+// static method to render a uint64 representation of a Game ID to a string
+const char * CGameID::Render( uint64 ulGameID )
+{
+ CGameID nGameID( ulGameID );
+ return nGameID.Render();
+}
+#endif
diff --git a/src/common/studiobyteswap.cpp b/src/common/studiobyteswap.cpp
index 7b2c992e..c31d098b 100644
--- a/src/common/studiobyteswap.cpp
+++ b/src/common/studiobyteswap.cpp
@@ -16,10 +16,10 @@
#undef ALIGN4
#undef ALIGN16
#undef ALIGN32
-#define ALIGN4( a ) a = (byte *)((int)((byte *)a + 3) & ~ 3)
-#define ALIGN16( a ) a = (byte *)((int)((byte *)a + 15) & ~ 15)
-#define ALIGN32( a ) a = (byte *)((int)((byte *)a + 31) & ~ 31)
-#define ALIGN64( a ) a = (byte *)((int)((byte *)a + 63) & ~ 63)
+#define ALIGN4( a ) a = (byte *)((intp)((byte *)a + 3) & ~ 3)
+#define ALIGN16( a ) a = (byte *)((intp)((byte *)a + 15) & ~ 15)
+#define ALIGN32( a ) a = (byte *)((intp)((byte *)a + 31) & ~ 31)
+#define ALIGN64( a ) a = (byte *)((intp)((byte *)a + 63) & ~ 63)
// Fixup macros create variables that may not be referenced
#pragma warning( push )
@@ -860,9 +860,9 @@ void ByteswapAnimData( mstudioanimdesc_t *pAnimDesc, int section, byte *&pDataSr
if ( pAnimation->flags & STUDIO_ANIM_ANIMPOS )
{
- int offset = (byte*)pAnimation->pPosV() - (byte*)pAnimation;
- pDataSrc = (byte*)pAnimationSrc + offset;
- pDataDest = (byte*)pAnimationDest + offset;
+ int offsetAnim = (byte*)pAnimation->pPosV() - (byte*)pAnimation;
+ pDataSrc = (byte*)pAnimationSrc + offsetAnim;
+ pDataDest = (byte*)pAnimationDest + offsetAnim;
mstudioanim_valueptr_t *posvptr = (mstudioanim_valueptr_t*)pDataSrc;
WriteObjects( &pDataDest, &pDataSrc );
@@ -994,7 +994,7 @@ int ByteswapIKRules( studiohdr_t *&pHdrSrc, int numikrules, int numFrames, byte
if ( pIKRule->szattachmentindex )
{
SET_INDEX_POINTERS( pData, pIKRule, szattachmentindex )
- int size = strlen( (char*)pDataSrc ) + 1;
+ int size = V_strlen( (char*)pDataSrc ) + 1;
WriteBuffer( pDataDest, pDataSrc, size );
}
}
@@ -1073,10 +1073,10 @@ int ByteswapANIFile( studiohdr_t* pHdr, void *pDestBase, const void *pSrcBase, c
{
int numsections = pAnimDesc->numframes / pAnimDesc->sectionframes + 2;
- for ( int i = 0; i < numsections; ++i )
+ for ( int iSec = 0; iSec < numsections; ++iSec )
{
- int block = pAnimDesc->pSection( i )->animblock;
- int index = pAnimDesc->pSection( i )->animindex;
+ int block = pAnimDesc->pSection( iSec )->animblock;
+ int index = pAnimDesc->pSection( iSec )->animindex;
if ( block != 0 )
{
@@ -1093,7 +1093,7 @@ int ByteswapANIFile( studiohdr_t* pHdr, void *pDestBase, const void *pSrcBase, c
byte *pDataSrc = pBlockBaseSrc + index;
byte *pDataDest = pBlockBaseDest + index;
- ByteswapAnimData( pAnimDesc, i, pDataSrc, pDataDest );
+ ByteswapAnimData( pAnimDesc, iSec, pDataSrc, pDataDest );
}
}
}
@@ -1228,8 +1228,8 @@ int ByteswapANI( studiohdr_t* pHdr, void *pDestBase, const void *pSrcBase, const
V_memcpy( pNewDest, pDestBase, pAnimBlock->datastart );
pNewDest += pAnimBlock->datastart;
- int padding = AlignValue( (unsigned int)pNewDest - (unsigned int)pNewDestBase, 2048 );
- padding -= (unsigned int)pNewDest - (unsigned int)pNewDestBase;
+ int padding = AlignValue( (uintp)pNewDest - (uintp)pNewDestBase, 2048 );
+ padding -= (uintp)pNewDest - (uintp)pNewDestBase;
pNewDest += padding;
// iterate and compress anim blocks
@@ -1240,7 +1240,7 @@ int ByteswapANI( studiohdr_t* pHdr, void *pDestBase, const void *pSrcBase, const
void *pInput = (byte *)pDestBase + pAnimBlock->datastart;
int inputSize = pAnimBlock->dataend - pAnimBlock->datastart;
- pAnimBlock->datastart = (unsigned int)pNewDest - (unsigned int)pNewDestBase;
+ pAnimBlock->datastart = (uintp)pNewDest - (uintp)pNewDestBase;
void *pOutput;
int outputSize;
@@ -1257,11 +1257,11 @@ int ByteswapANI( studiohdr_t* pHdr, void *pDestBase, const void *pSrcBase, const
pNewDest += inputSize;
}
- padding = AlignValue( (unsigned int)pNewDest - (unsigned int)pNewDestBase, 2048 );
- padding -= (unsigned int)pNewDest - (unsigned int)pNewDestBase;
+ padding = AlignValue( (uintp)pNewDest - (uintp)pNewDestBase, 2048 );
+ padding -= (uintp)pNewDest - (uintp)pNewDestBase;
pNewDest += padding;
- pAnimBlock->dataend = (unsigned int)pNewDest - (unsigned int)pNewDestBase;
+ pAnimBlock->dataend = (uintp)pNewDest - (uintp)pNewDestBase;
}
fixedFileSize = pNewDest - pNewDestBase;
@@ -1418,10 +1418,10 @@ int ByteswapMDLFile( void *pDestBase, void *pSrcBase, const int fileSize )
int index = pAnimDesc->pSection( i )->animindex;
// Base address of the animation in the animblock
- byte *pDataSrc = (byte *)pAnimDescSrc + index;
- byte *pDataDest = (byte *)pAnimDescDest + index;
+ byte *pDataSrcAnim = (byte *)pAnimDescSrc + index;
+ byte *pDataDestAnim = (byte *)pAnimDescDest + index;
- ByteswapAnimData( pAnimDesc, i, pDataSrc, pDataDest );
+ ByteswapAnimData( pAnimDesc, i, pDataSrcAnim, pDataDestAnim );
}
}
}
@@ -1580,7 +1580,7 @@ int ByteswapMDLFile( void *pDestBase, void *pSrcBase, const int fileSize )
if ( pIKRule->szattachmentindex )
{
SET_INDEX_POINTERS( pData, pIKRule, szattachmentindex )
- int size = strlen( (char*)pDataSrc ) + 1;
+ int size = V_strlen( (char*)pDataSrc ) + 1;
WriteBuffer( pDataDest, pDataSrc, size );
}
}
@@ -1957,7 +1957,7 @@ int ByteswapMDLFile( void *pDestBase, void *pSrcBase, const int fileSize )
for ( int i = 0; i < numCdTextures; ++i )
{
char *pPath = (char*)pHdrDest + SrcNative( &((int *)pDataSrc)[i] );
- int len = strlen( pPath );
+ int len = V_strlen( pPath );
if ( len >= 2 && ( pPath[len-1] == '\\' || pPath[len-1] == '/' ) && ( pPath[len-2] == '\\' || pPath[len-2] == '/' ) )
{
pPath[len-1] = '\0';
@@ -2068,7 +2068,7 @@ int ByteswapStudioFile( const char *pFilename, void *pOutBase, const void *pFile
void ProcessANIFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
{
studiohdr_t *pHdr = g_pHdr;
- byte *pData = (byte*)pDataBase;
+ //byte *pData = (byte*)pDataBase;
byte *pSrcBase = (byte*)g_pDataSrcBase;
// Since the animblocks and animdescs are native data, trick the system
@@ -2088,7 +2088,7 @@ void ProcessANIFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
mstudioanimdesc_t *pAnimDesc = pHdr->pLocalAnimdesc( 0 );
for ( int i = 0; i < pHdr->numlocalanim; ++i, ++pAnimDesc )
{
- mstudioanimblock_t *pAnimBlock = pHdr->pAnimBlock( pAnimDesc->animblock );
+ pAnimBlock = pHdr->pAnimBlock( pAnimDesc->animblock );
byte *pBlockBase = (byte*)pSrcBase + pAnimBlock->datastart;
ProcessFieldByName( pBlockBase, pAnimDesc, &mstudioanimdesc_t::m_DataMap, "animindex", pfnProcessFunc );
@@ -2133,7 +2133,7 @@ void ProcessANIFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData = (byte*)pBlockBase + pAnimDesc->animblockikruleindex;
mstudioikrule_t *pIKRule = (mstudioikrule_t *)pData;
- for ( int i = 0; i < pAnimDesc->numikrules; ++i, ++pIKRule )
+ for ( int iIK = 0; iIK < pAnimDesc->numikrules; ++iIK, ++pIKRule )
{
ProcessFields( pIKRule, &mstudioikrule_t::m_DataMap, pfnProcessFunc );
}
@@ -2227,7 +2227,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
/** HITBOXES **/
pData = (byte*)pHitboxSet + SrcNative( &pHitboxSet->hitboxindex );
mstudiobbox_t *pBBox = (mstudiobbox_t*)pData;
- for ( int i = 0; i < SrcNative( &pHitboxSet->numhitboxes ); ++i, ++pBBox )
+ for ( int iHit = 0; iHit < SrcNative( &pHitboxSet->numhitboxes ); ++iHit, ++pBBox )
{
ProcessFields( pBBox, &mstudiobbox_t::m_DataMap, pfnProcessFunc );
}
@@ -2275,7 +2275,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData = (byte*)pAnimDesc + SrcNative( &pAnimDesc->ikruleindex );
mstudioikrule_t *pIKRule = (mstudioikrule_t *)pData;
- for ( int i = 0; i < SrcNative( &pAnimDesc->numikrules ); ++i, ++pIKRule )
+ for ( int iIK = 0; iIK < SrcNative( &pAnimDesc->numikrules ); ++iIK, ++pIKRule )
{
ProcessFields( pIKRule, &mstudioikrule_t::m_DataMap, pfnProcessFunc );
}
@@ -2294,7 +2294,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData = (byte*)pHdr + SrcNative( &pSequenceHdr->eventindex );
mstudioevent_t *pEvent = (mstudioevent_t*)pData;
- for ( int i = 0; i < SrcNative( &pSequenceHdr->numevents ); ++i, ++pEvent )
+ for ( int iEvent = 0; iEvent < SrcNative( &pSequenceHdr->numevents ); ++iEvent, ++pEvent )
{
ProcessFields( pSequenceHdr, &mstudioevent_t::m_DataMap, pfnProcessFunc );
}
@@ -2310,9 +2310,9 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
/** MODEL INFO **/
- byte *pData = (byte*)pBodypart + SrcNative( &pBodypart->modelindex );
- mstudiomodel_t *pModel = (mstudiomodel_t*)pData;
- for ( int i = 0; i < SrcNative( &pBodypart->nummodels ); ++i, ++pModel )
+ byte *pDataModel = (byte*)pBodypart + SrcNative( &pBodypart->modelindex );
+ mstudiomodel_t *pModel = (mstudiomodel_t*)pDataModel;
+ for ( int iModel = 0; iModel < SrcNative( &pBodypart->nummodels ); ++iModel, ++pModel )
{
ProcessFields( pModel, &mstudiomodel_t::m_DataMap, pfnProcessFunc );
@@ -2320,7 +2320,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData = (byte*)pModel + SrcNative( &pModel->meshindex );
mstudiomesh_t *pMesh = (mstudiomesh_t*)pData;
- for ( int i = 0; i < SrcNative( &pModel->nummeshes ); ++i, ++pMesh )
+ for ( int iMesh = 0; iMesh < SrcNative( &pModel->nummeshes ); ++iMesh, ++pMesh )
{
ProcessFields( pMesh, &mstudiomesh_t::m_DataMap, pfnProcessFunc );
@@ -2331,7 +2331,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData = (byte*)pMesh + SrcNative( &pMesh->flexindex );
mstudioflex_t *pFlex = (mstudioflex_t*)pData;
- for ( int i = 0; i < SrcNative( &pMesh->numflexes ); ++i, ++pFlex )
+ for ( int iFlesh = 0; iFlesh < SrcNative( &pMesh->numflexes ); ++iFlesh, ++pFlex )
{
ProcessFields( pFlex, &mstudioflex_t::m_DataMap, pfnProcessFunc );
}
@@ -2341,7 +2341,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData= (byte*)pModel + SrcNative( &pModel->eyeballindex );
mstudioeyeball_t *pEyeball = (mstudioeyeball_t*)pData;
- for ( int i = 0; i < SrcNative( &pModel->numeyeballs ); ++i, ++pEyeball )
+ for ( int iEye = 0; iEye < SrcNative( &pModel->numeyeballs ); ++iEye, ++pEyeball )
{
ProcessFields( pEyeball, &mstudioeyeball_t::m_DataMap, pfnProcessFunc );
}
@@ -2445,7 +2445,7 @@ void ProcessMDLFields( void *pDataBase, datadescProcessFunc_t pfnProcessFunc )
pData = (byte*)pHdr + SrcNative( &pStudioHdr2->srcbonetransformindex );
mstudiosrcbonetransform_t *pSrcBoneTransform = (mstudiosrcbonetransform_t*)pData;
- for ( int i = 0; i < SrcNative( &pStudioHdr2->numsrcbonetransform ); ++i, ++pSrcBoneTransform )
+ for ( int iBone = 0; iBone < SrcNative( &pStudioHdr2->numsrcbonetransform ); ++iBone, ++pSrcBoneTransform )
{
ProcessFields( pSrcBoneTransform, &mstudiosrcbonetransform_t::m_DataMap, pfnProcessFunc );
}
@@ -2522,14 +2522,27 @@ BEGIN_BYTESWAP_DATADESC( studiohdr_t )
DEFINE_FIELD( contents, FIELD_INTEGER ),
DEFINE_FIELD( numincludemodels, FIELD_INTEGER ),
DEFINE_INDEX( includemodelindex, FIELD_INTEGER ),
+#ifdef PLATFORM_64BITS
+ DEFINE_FIELD( unused_virtualModel, FIELD_INTEGER ), // void*
+#else
DEFINE_FIELD( virtualModel, FIELD_INTEGER ), // void*
+#endif
DEFINE_INDEX( szanimblocknameindex, FIELD_INTEGER ),
DEFINE_FIELD( numanimblocks, FIELD_INTEGER ),
DEFINE_INDEX( animblockindex, FIELD_INTEGER ),
+#ifdef PLATFORM_64BITS
+ DEFINE_FIELD( unused_animblockModel, FIELD_INTEGER ), // void*
+#else
DEFINE_FIELD( animblockModel, FIELD_INTEGER ), // void*
+#endif
DEFINE_INDEX( bonetablebynameindex, FIELD_INTEGER ),
+#ifdef PLATFORM_64BITS
+ DEFINE_FIELD( unused_pVertexBase, FIELD_INTEGER ), // void*
+ DEFINE_FIELD( unused_pIndexBase, FIELD_INTEGER ), // void*
+#else
DEFINE_FIELD( pVertexBase, FIELD_INTEGER ), // void*
DEFINE_FIELD( pIndexBase, FIELD_INTEGER ), // void*
+#endif
DEFINE_FIELD( constdirectionallightdot, FIELD_CHARACTER ), // byte
DEFINE_FIELD( rootLOD, FIELD_CHARACTER ), // byte
DEFINE_FIELD( numAllowedRootLODs, FIELD_CHARACTER ), // byte
diff --git a/src/common/studiobyteswap.h b/src/common/studiobyteswap.h
index 3bec9eaf..c5255247 100644
--- a/src/common/studiobyteswap.h
+++ b/src/common/studiobyteswap.h
@@ -35,4 +35,4 @@ int ByteswapMDL( void *pOutBase, const void *pFileBase, int fileSize );
#define BYTESWAP_ALIGNMENT_PADDING 4096
}
-#endif // STUDIOBYTESWAP_H
\ No newline at end of file
+#endif // STUDIOBYTESWAP_H
diff --git a/src/common/userid.h b/src/common/userid.h
index 6152f207..524deb1b 100644
--- a/src/common/userid.h
+++ b/src/common/userid.h
@@ -14,8 +14,7 @@
#include "strtools.h"
#include "steam/steamclientpublic.h"
#if !defined( INCLUDED_STEAM_STEAMUSERIDTYPES_H )
-#define INCLUDED_STEAM2_USERID_STRUCTS
-#include "SteamCommon.h"
+#include "steamcommon.h"
#endif
#define IDTYPE_WON 0
diff --git a/src/common/vscript_utils.h b/src/common/vscript_utils.h
new file mode 100644
index 00000000..cceb3a28
--- /dev/null
+++ b/src/common/vscript_utils.h
@@ -0,0 +1,185 @@
+//===== Copyright � 1996-2011, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef COMMON_VSCRIPT_UTILS_H
+#define COMMON_VSCRIPT_UTILS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "KeyValues.h"
+#include "fmtstr.h"
+
+#define KV_VARIANT_SCRATCH_BUF_SIZE 128
+
+inline KeyValues * ScriptTableToKeyValues( IScriptVM *pVM, char const *szName, HSCRIPT hTable );
+inline HSCRIPT ScriptTableFromKeyValues( IScriptVM *pVM, KeyValues *kv, HSCRIPT hTable = INVALID_HSCRIPT );
+
+inline bool ScriptVmKeyValueToVariant( IScriptVM *pVM, KeyValues *val, ScriptVariant_t &varValue, char chScratchBuffer[KV_VARIANT_SCRATCH_BUF_SIZE] )
+{
+ switch ( val->GetDataType() )
+ {
+ case KeyValues::TYPE_STRING:
+ varValue = val->GetString();
+ return true;
+ case KeyValues::TYPE_INT:
+ varValue = val->GetInt();
+ return true;
+ case KeyValues::TYPE_FLOAT:
+ varValue = val->GetFloat();
+ return true;
+ case KeyValues::TYPE_UINT64:
+ V_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%llu", val->GetUint64() );
+ varValue = chScratchBuffer;
+ return true;
+ case KeyValues::TYPE_NONE:
+ varValue = ScriptTableFromKeyValues( pVM, val );
+ return true;
+ default:
+ Warning( "ScriptVmKeyValueToVariant failed to package parameter %s (type %d)\n", val->GetName(), val->GetDataType() );
+ return false;
+ }
+}
+
+inline bool ScriptVmStringFromVariant( ScriptVariant_t &varValue, char chScratchBuffer[KV_VARIANT_SCRATCH_BUF_SIZE] )
+{
+ switch ( varValue.GetType() )
+ {
+ case FIELD_INTEGER:
+ V_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%d", ( int ) varValue );
+ return true;
+ case FIELD_FLOAT:
+ V_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%f", ( float ) varValue );
+ return true;
+ case FIELD_BOOLEAN:
+ V_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%d", ( bool ) varValue );
+ return true;
+ case FIELD_CHARACTER:
+ V_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%c", ( char ) varValue );
+ return true;
+ case FIELD_CSTRING:
+ V_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%s", ( const char * ) varValue );
+ return true;
+ default:
+ Warning( "ScriptVmStringFromVariant failed to unpack parameter variant type %d\n", varValue.GetType() );
+ return false;
+ }
+}
+
+inline KeyValues * ScriptVmKeyValueFromVariant( IScriptVM *pVM, ScriptVariant_t &varValue )
+{
+ KeyValues *val = NULL;
+
+ switch ( varValue.GetType() )
+ {
+ case FIELD_INTEGER:
+ val = new KeyValues( "" );
+ val->SetInt( NULL, ( int ) varValue );
+ return val;
+ case FIELD_FLOAT:
+ val = new KeyValues( "" );
+ val->SetFloat( NULL, ( float ) varValue );
+ return val;
+ case FIELD_BOOLEAN:
+ val = new KeyValues( "" );
+ val->SetInt( NULL, ( ( bool ) varValue ) ? 1 : 0 );
+ return val;
+ case FIELD_CHARACTER:
+ val = new KeyValues( "" );
+ val->SetString( NULL, CFmtStr( "%c", ( char ) varValue ) );
+ return val;
+ case FIELD_CSTRING:
+ val = new KeyValues( "" );
+ val->SetString( NULL, ( char const * ) varValue );
+ return val;
+ case FIELD_HSCRIPT:
+ return ScriptTableToKeyValues( pVM, "", ( HSCRIPT ) varValue );
+ default:
+ Warning( "ScriptVmKeyValueFromVariant failed to unpack parameter variant type %d\n", varValue.GetType() );
+ return NULL;
+ }
+}
+
+inline KeyValues * ScriptTableToKeyValues( IScriptVM *pVM, char const *szName, HSCRIPT hTable )
+{
+ if ( !szName )
+ szName = "";
+
+ KeyValues *kv = new KeyValues( szName );
+
+ if ( hTable && pVM )
+ {
+ ScriptVariant_t varKey, varValue;
+ for ( int nIterator = 0;
+ ( nIterator = pVM->GetKeyValue( hTable, nIterator, &varKey, &varValue ) ) != -1;
+ pVM->ReleaseValue( varKey ), pVM->ReleaseValue( varValue ) )
+ {
+ char chScratchBuffer[ KV_VARIANT_SCRATCH_BUF_SIZE ] = {0};
+ ScriptVmStringFromVariant( varKey, chScratchBuffer );
+
+ if ( !chScratchBuffer[0] )
+ {
+ Assert( 0 );
+ continue;
+ }
+
+ KeyValues *sub = ScriptVmKeyValueFromVariant( pVM, varValue );
+ if ( !sub )
+ {
+ Assert( 0 );
+ // sub->deleteThis();
+ // continue;
+ // still proceed - it will be a key with no data
+ sub = new KeyValues( "" );
+ }
+ sub->SetName( chScratchBuffer );
+
+ kv->AddSubKey( sub );
+ }
+ }
+
+ return kv;
+}
+
+inline HSCRIPT ScriptTableFromKeyValues( IScriptVM *pVM, KeyValues *kv, HSCRIPT hTable )
+{
+ if ( !kv || !pVM )
+ return NULL;
+
+ if ( hTable == INVALID_HSCRIPT )
+ {
+ ScriptVariant_t varTable;
+ pVM->CreateTable( varTable );
+ hTable = varTable;
+ }
+
+ for ( KeyValues *val = kv->GetFirstSubKey(); val; val = val->GetNextKey() )
+ {
+ ScriptVariant_t varValue;
+ char chScratchBuffer[ KV_VARIANT_SCRATCH_BUF_SIZE ];
+ if ( !ScriptVmKeyValueToVariant( pVM, val, varValue, chScratchBuffer ) )
+ continue;
+
+#ifdef SCRIPTTABLE_SCRIPT_LOWERCASE_ALL_TABLE_KEYS
+ char chNameBuffer[ KV_VARIANT_SCRATCH_BUF_SIZE ];
+ V_strncpy( chNameBuffer, val->GetName(), KV_VARIANT_SCRATCH_BUF_SIZE );
+ V_strlower( chNameBuffer );
+#else
+ char const *chNameBuffer = val->GetName();
+#endif
+
+ pVM->SetValue( hTable, chNameBuffer, varValue );
+ }
+
+ return hTable;
+}
+
+
+
+#endif // COMMON_VSCRIPT_UTILS_H
diff --git a/src/createallprojects b/src/createallprojects
deleted file mode 100755
index 9f855f11..00000000
--- a/src/createallprojects
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-pushd `dirname $0`
-devtools/bin/vpc /hl2mp +everything /mksln everything
-popd
diff --git a/src/createallprojects.bat b/src/createallprojects.bat
index 40c0f22c..ba18f25e 100755
--- a/src/createallprojects.bat
+++ b/src/createallprojects.bat
@@ -1 +1 @@
-devtools\bin\vpc.exe /hl2mp +everything /mksln everything.sln
+devtools\bin\vpc.exe /hl2mp /tf /define:SOURCESDK +everything /mksln everything.sln
diff --git a/src/creategameprojects b/src/creategameprojects
deleted file mode 100755
index 1308ef12..00000000
--- a/src/creategameprojects
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-pushd `dirname $0`
-devtools/bin/vpc /hl2mp +game /mksln games
-popd
diff --git a/src/creategameprojects.bat b/src/creategameprojects.bat
deleted file mode 100755
index fa11d1c6..00000000
--- a/src/creategameprojects.bat
+++ /dev/null
@@ -1 +0,0 @@
-devtools\bin\vpc.exe /hl2mp +game /mksln games.sln
diff --git a/src/devtools/base.xcconfig b/src/devtools/base.xcconfig
deleted file mode 100644
index 0f0960d3..00000000
--- a/src/devtools/base.xcconfig
+++ /dev/null
@@ -1,46 +0,0 @@
-ALWAYS_SEARCH_USER_PATHS = YES
-HEADER_SEARCH_PATHS = $(HEADER_SEARCH_PATHS) $(SDKROOT)/usr/include/malloc
-
-ARCHS = i386
-ONLY_ACTIVE_ARCH = NO
-COPY_PHASE_STRIP = NO
-DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
-
-DEAD_CODE_STRIPPING = YES
-PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES
-
-GCC_C_LANGUAGE_STANDARD = gnu99
-GCC_ENABLE_OBJC_EXCEPTIONS = YES
-GCC_SYMBOLS_PRIVATE_EXTERN = YES
-GCC_INLINES_ARE_PRIVATE_EXTERN = YES
-GCC_REUSE_STRINGS = YES
-
-// CPP11_NO_LIBCXX is used to gate some C++11 features that require that we
-// switch to libc++. We haven't switched to libc++11 because we have been unable
-// to find a clean way to build libcef_dll_wrapper with libc++.
-// We currently build libcef for Steam which needs to run on 10.5, and Xcode
-// does not support linking with libc++ and targeting 10.5.
-// Once libcef_dll_wrapper has been built with libc++, and you rebuild protobuf
-// with libc++ (which is trivial), you can remove CPP11_NO_LIBCXX and add the
-// following line to the xcconfig:
-// CLANG_CXX_LIBRARY = libc++
-GCC_PREPROCESSOR_DEFINITIONS = _DLL_EXT=.dylib NO_MALLOC_OVERRIDE=1 VPROF_LEVEL=1 NO_HOOK_MALLOC=1 PNG_NO_PEDANTIC_WARNINGS CPP11_NO_LIBCXX
-BASE_CFLAGS= -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE -ftemplate-depth=512
-
-GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO
-WARNING_CFLAGS = -Wno-deprecated-writable-strings -Wno-switch-enum -Wno-switch -Wno-unused-value -Wno-parentheses -Wno-logical-op-parentheses -Wno-c++11-narrowing
-
-// CLANG - and use the ccache wrapper
-GCC_VERSION = com.apple.compilers.llvm.clang.1_0
-CC = $(SOURCE_ROOT)/devtools/bin/osx32/xcode_ccache_wrapper
-LDPLUSPLUS = $(DT_TOOLCHAIN_DIR)/usr/bin/clang++
-CLANG_WARN_CXX0X_EXTENSIONS = NO
-CLANG_CXX_LANGUAGE_STANDARD = gnu++11
-
-// include gets confused, 'cause ivp has one, and the system has one, and only one
-// gets into the header map, so sacrifice speed for corectness.
-USE_HEADERMAP = NO
-
-SDKROOT = macosx10.9
-MACOSX_DEPLOYMENT_TARGET = 10.5
-GCC_FAST_MATH = YES
diff --git a/src/devtools/bin/ShaderCompile2.exe b/src/devtools/bin/ShaderCompile2.exe
new file mode 100755
index 00000000..2f39d23c
Binary files /dev/null and b/src/devtools/bin/ShaderCompile2.exe differ
diff --git a/src/devtools/bin/ShaderCompile2_readme.txt b/src/devtools/bin/ShaderCompile2_readme.txt
new file mode 100644
index 00000000..39f183c9
--- /dev/null
+++ b/src/devtools/bin/ShaderCompile2_readme.txt
@@ -0,0 +1,5 @@
+Where does this come from?
+
+https://github.com/Joshua-Ashton/ShaderCompile2
+
+based on https://github.com/SCell555/ShaderCompile with some slight edits for compatibility. Thanks SCell! :D
\ No newline at end of file
diff --git a/src/devtools/bin/buildshaderlist.pl b/src/devtools/bin/buildshaderlist.pl
deleted file mode 100644
index 98a4051f..00000000
--- a/src/devtools/bin/buildshaderlist.pl
+++ /dev/null
@@ -1,22 +0,0 @@
-use File::DosGlob;
-@ARGV = map {
- my @g = File::DosGlob::glob($_) if /[*?]/;
- @g ? @g : $_;
- } @ARGV;
-
-open FILE, ">__tmpshaderlist.txt";
-
-foreach $arg (@ARGV)
-{
- if( $arg =~ m/\.fxc$/i || $arg =~ m/\.vsh$/i || $arg =~ m/\.psh$/i )
- {
- print $arg . "\n";
- print FILE $arg . "\n";
- }
-}
-
-close FILE;
-
-system "buildshaders.bat __tmpshaderlist";
-
-unlink "__tmpshaderlist.txt";
\ No newline at end of file
diff --git a/src/devtools/bin/checkshaderchecksums.pl b/src/devtools/bin/checkshaderchecksums.pl
deleted file mode 100644
index 26841cbe..00000000
--- a/src/devtools/bin/checkshaderchecksums.pl
+++ /dev/null
@@ -1,116 +0,0 @@
-use String::CRC32;
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-
-sub GetShaderType
-{
- my $shadername = shift;
- my $shadertype;
- if( $shadername =~ m/\.vsh/i )
- {
- $shadertype = "vsh";
- }
- elsif( $shadername =~ m/\.psh/i )
- {
- $shadertype = "psh";
- }
- elsif( $shadername =~ m/\.fxc/i )
- {
- $shadertype = "fxc";
- }
- else
- {
- die;
- }
- return $shadertype;
-}
-
-sub GetShaderSrc
-{
- my $shadername = shift;
- if ( $shadername =~ m/^(.*)-----/i )
- {
- return $1;
- }
- else
- {
- return $shadername;
- }
-}
-
-sub GetShaderType
-{
- my $shadername = shift;
- my $shadertype;
- if( $shadername =~ m/\.vsh/i )
- {
- $shadertype = "vsh";
- }
- elsif( $shadername =~ m/\.psh/i )
- {
- $shadertype = "psh";
- }
- elsif( $shadername =~ m/\.fxc/i )
- {
- $shadertype = "fxc";
- }
- else
- {
- die;
- }
- return $shadertype;
-}
-
-sub GetShaderBase
-{
- my $shadername = shift;
- if ( $shadername =~ m/-----(.*)$/i )
- {
- return $1;
- }
- else
- {
- my $shadertype = &GetShaderType( $shadername );
- $shadername =~ s/\.$shadertype//i;
- return $shadername;
- }
-}
-
-$g_x360 = 0;
-$g_vcsext = ".vcs";
-
-while( 1 )
-{
- $inputbase = shift;
-
- if( $inputbase =~ m/-x360/ )
- {
- $g_x360 = 1;
- $g_vcsext = ".360.vcs";
- }
- else
- {
- last;
- }
-}
-
-# rip the txt off the end if it's there.
-$inputbase =~ s/\.txt//i;
-
-my @srcfiles = &LoadShaderListFile( $inputbase );
-
-foreach $srcfile ( @srcfiles )
-{
- my $shadertype = &GetShaderType( $srcfile );
- my $shaderbase = &GetShaderBase( $srcfile );
- my $shadersrc = &GetShaderSrc( $srcfile );
- my $vcsFileName = "..\\..\\..\\game\\hl2\\shaders\\$shadertype\\$shaderbase" . $g_vcsext;
-# print "shadersrc: $shadersrc vcsFileName: $vcsFileName\n";
-
- if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) )
- {
- next; # skip _ps20 files for 360
- }
-
- &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 1 );
-}
diff --git a/src/devtools/bin/copyshaderincfiles.pl b/src/devtools/bin/copyshaderincfiles.pl
deleted file mode 100644
index c3419e62..00000000
--- a/src/devtools/bin/copyshaderincfiles.pl
+++ /dev/null
@@ -1,75 +0,0 @@
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-use Cwd;
-use String::CRC32;
-
-my $txtfilename = shift;
-my $arg = shift;
-
-my $is360 = 0;
-my $platformextension = "";
-if( $arg =~ m/-x360/i )
-{
- $is360 = 1;
- $platformextension = ".360";
-}
-
-open TXTFILE, "<$txtfilename";
-
-my $src;
-my $dst;
-while( $src = )
-{
- # get rid of comments
- $src =~ s,//.*,,g;
-
- # skip blank lines
- if( $src =~ m/^\s*$/ )
- {
- next;
- }
-
- # Get rid of newlines.
- $src =~ s/\n//g;
-
- # Save off the shader source filename.
- my $dst = $src;
-
- $dst =~ s/_tmp//gi;
-
- # Does the dst exist?
- my $dstexists = -e $dst;
- my $srcexists = -e $src;
- # What are the time stamps for the src and dst?
- my $srcmodtime = ( stat $src )[9];
- my $dstmodtime = ( stat $dst )[9];
-
- # Open for edit or add if different than what is in perforce already.
- if( !$dstexists || ( $srcmodtime != $dstmodtime ) )
- {
- # Make the target writable if it exists
- if( $dstexists )
- {
- MakeFileWritable( $dst );
- }
-
- my $dir = $dst;
- $dir =~ s,([^/\\]*$),,; # rip the filename off the end
- my $filename = $1;
-
- # create the target directory if it doesn't exist
- if( !$dstexists )
- {
- &MakeDirHier( $dir, 0777 );
- }
-
- # copy the file to its targets. . . we want to see STDERR here if there is an error.
- my $cmd = "copy $src $dst > nul";
-# print STDERR "$cmd\n";
- system $cmd;
-
- MakeFileReadOnly( $dst );
- }
-}
-
-close TXTFILE;
diff --git a/src/devtools/bin/copyshaders.pl b/src/devtools/bin/copyshaders.pl
deleted file mode 100644
index cb849a84..00000000
--- a/src/devtools/bin/copyshaders.pl
+++ /dev/null
@@ -1,172 +0,0 @@
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-use Cwd;
-use String::CRC32;
-
-sub ReadInputFileWithIncludes
-{
- local( $filename ) = shift;
-
- local( *INPUT );
- local( $output );
-
- open INPUT, "<$filename" || die;
-
- local( $line );
- local( $linenum ) = 1;
- while( $line = )
- {
- if( $line =~ m/\#include\s+\"(.*)\"/i )
- {
- $output.= ReadInputFileWithIncludes( $1 );
- }
- else
- {
- $output .= $line;
- }
- }
-
- close INPUT;
- return $output;
-}
-
-sub PatchCRC
-{
- my $filename = shift;
- my $crc = shift;
-# print STDERR "PatchCRC( $filename, $crc )\n";
- local( *FP );
- open FP, "+<$filename" || die;
- binmode( FP );
- seek FP, 6 * 4, 0;
- my $uInt = "I";
- if( $filename =~ m/360/ )
- {
- $uInt = "N";
- }
- print FP pack $uInt, $crc;
- close FP;
-}
-
-my $txtfilename = shift;
-my $arg = shift;
-
-my $is360 = 0;
-my $platformextension = "";
-if( $arg =~ m/-x360/i )
-{
- $is360 = 1;
- $platformextension = ".360";
-}
-
-# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
-my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\hl2\\shaders \"Shader Auto Checkout VCS\"`;
-# Get rid of the newline
-$changelistnumber =~ s/\n//g;
-
-my $changelistarg = "";
-if( $changelistnumber != 0 )
-{
- $changelistarg = "-c $changelistnumber"
-}
-
-open TXTFILE, "<$txtfilename";
-
-my $src;
-my $dst;
-while( $src = )
-{
- # get rid of comments
- $src =~ s,//.*,,g;
-
- # skip blank lines
- if( $src =~ m/^\s*$/ )
- {
- next;
- }
-
- # Get rid of newlines.
- $src =~ s/\n//g;
-
- # Save off the shader source filename.
- my $shadersrcfilename = $src;
- $shadersrcfilename =~ s/-----.*$//;
- # use only target basename.
- $src =~ s/^.*-----//;
-
- # where the binary vcs file is
- my $spath = "";
-
- if ( $shadersrcfilename =~ m@\.fxc@i )
- {
- $spath = "shaders\\fxc\\";
- }
- if ( $shadersrcfilename =~ m@\.vsh@i )
- {
- $spath = "shaders\\vsh\\";
- }
- if ( $shadersrcfilename =~ m@\.psh@i )
- {
- $spath = "shaders\\psh\\";
- }
-
- # make the source have path and extension
- $src = $spath . $src . $platformextension . ".vcs";
-
- # build the dest filename.
- $dst = $src;
-
- $dst =~ s/shaders\\/..\\..\\..\\game\\hl2\\shaders\\/i;
-
- # Does the dst exist?
- my $dstexists = -e $dst;
- my $srcexists = -e $src;
- # What are the time stamps for the src and dst?
- my $srcmodtime = ( stat $src )[9];
- my $dstmodtime = ( stat $dst )[9];
-
- # Write $dst to a file so that we can do perforce stuff to it later.
- local( *VCSLIST );
- open VCSLIST, ">>vcslist.txt" || die;
- print VCSLIST $dst . "\n";
- close VCSLIST;
-
- # Open for edit or add if different than what is in perforce already.
- if( !$dstexists || ( $srcmodtime != $dstmodtime ) )
- {
- if ( $srcexists && $shadersrcfilename =~ m@\.fxc@i )
- {
- # Get the CRC for the source file.
- my $srccode = ReadInputFileWithIncludes( $shadersrcfilename );
- my $crc = crc32( $srccode );
-
- # Patch the source VCS file with the CRC32 of the source code used to build that file.
- PatchCRC( $src, $crc );
- }
-
- # Make the target vcs writable if it exists
- if( $dstexists )
- {
- MakeFileWritable( $dst );
- }
-
- my $dir = $dst;
- $dir =~ s,([^/\\]*$),,; # rip the filename off the end
- my $filename = $1;
-
- # create the target directory if it doesn't exist
- if( !$dstexists )
- {
- &MakeDirHier( $dir, 0777 );
- }
-
- # copy the file to its targets. . . we want to see STDERR here if there is an error.
- my $cmd = "copy $src $dst > nul";
-# print STDERR "$cmd\n";
- system $cmd;
-
- MakeFileReadOnly( $dst );
- }
-}
-
-close TXTFILE;
diff --git a/src/devtools/bin/d3dx9_33.dll b/src/devtools/bin/d3dx9_33.dll
deleted file mode 100644
index a005f8fa..00000000
Binary files a/src/devtools/bin/d3dx9_33.dll and /dev/null differ
diff --git a/src/devtools/bin/fix_particle_operator_names.pl b/src/devtools/bin/fix_particle_operator_names.pl
deleted file mode 100644
index c0f5ee06..00000000
--- a/src/devtools/bin/fix_particle_operator_names.pl
+++ /dev/null
@@ -1,110 +0,0 @@
-#!perl
-use File::Find;
-
-&BuildRemapTable;
-
-find(\&convert, "." );
-
-
-sub convert
- {
- return unless (/\.pcf$/i);
- return if (/^tmp\.pcf$/i);
- return if (/^tmp2\.pcf$/i);
- return if (/360\.pcf$/i);
- print STDERR "process ", $File::Find::name," ($_) dir=",`cd`," \n";
- my $fname=$_;
- print `p4 edit $fname`;
- print `dmxconvert -i $_ -o tmp.pcf -oe keyvalues2`;
- open(TMP, "tmp.pcf" ) || return;
- open(OUT, ">tmp2.pcf" ) || die;
- while()
- {
- s/[\n\r]//g;
- if ( (/^(\s*\"functionName\"\s*\"string\"\s*\")(.*)\"(.*)$/) &&
- length($map{$2}) )
- {
- $_=$1.$map{$2}.'"'.$3;
- }
- if ( (/^(\s*\"name\"\s*\"string\"\s*\")(.*)\"(.*)$/) &&
- length($map{$2}) )
- {
- $_=$1.$map{$2}.'"'.$3;
- }
- print OUT "$_\n";
- }
- close OUT;
- close TMP;
- print `dmxconvert -i tmp2.pcf -o $fname -ie keyvalues2 -oe binary`;
- unlink "tmp.pcf";
- unlink "tmp2.pcf";
-}
-
-
-
-
-
-
-
-
-
-
-
-
-sub BuildRemapTable
-{
- $map{"alpha_fade"}= "Alpha Fade and Decay";
- $map{"alpha_fade_in_random"}= "Alpha Fade In Random";
- $map{"alpha_fade_out_random"}= "Alpha Fade Out Random";
- $map{"basic_movement"}= "Movement Basic";
- $map{"color_fade"}= "Color Fade";
- $map{"controlpoint_light"}= "Color Light From Control Point";
- $map{"Dampen Movement Relative to Control Point"}= "Movement Dampen Relative to Control Point";
- $map{"Distance Between Control Points Scale"}= "Remap Distance Between Two Control Points to Scalar";
- $map{"Distance to Control Points Scale"}= "Remap Distance to Control Point to Scalar";
- $map{"lifespan_decay"}= "Lifespan Decay";
- $map{"lock to bone"}= "Movement Lock to Bone";
- $map{"postion_lock_to_controlpoint"}= "Movement Lock to Control Point";
- $map{"maintain position along path"}= "Movement Maintain Position Along Path";
- $map{"Match Particle Velocities"}= "Movement Match Particle Velocities";
- $map{"Max Velocity"}= "Movement Max Velocity";
- $map{"noise"}= "Noise Scalar";
- $map{"vector noise"}= "Noise Vector";
- $map{"oscillate_scalar"}= "Oscillate Scalar";
- $map{"oscillate_vector"}= "Oscillate Vector";
- $map{"Orient Rotation to 2D Direction"}= "Rotation Orient to 2D Direction";
- $map{"radius_scale"}= "Radius Scale";
- $map{"Random Cull"}= "Cull Random";
- $map{"remap_scalar"}= "Remap Scalar";
- $map{"rotation_movement"}= "Rotation Basic";
- $map{"rotation_spin"}= "Rotation Spin Roll";
- $map{"rotation_spin yaw"}= "Rotation Spin Yaw";
- $map{"alpha_random"}= "Alpha Random";
- $map{"color_random"}= "Color Random";
- $map{"create from parent particles"}= "Position From Parent Particles";
- $map{"Create In Hierarchy"}= "Position In CP Hierarchy";
- $map{"random position along path"}= "Position Along Path Random";
- $map{"random position on model"}= "Position on Model Random";
- $map{"sequential position along path"}= "Position Along Path Sequential";
- $map{"position_offset_random"}= "Position Modify Offset Random";
- $map{"position_warp_random"}= "Position Modify Warp Random";
- $map{"position_within_box"}= "Position Within Box Random";
- $map{"position_within_sphere"}= "Position Within Sphere Random";
- $map{"Inherit Velocity"}= "Velocity Inherit from Control Point";
- $map{"Initial Repulsion Velocity"}= "Velocity Repulse from World";
- $map{"Initial Velocity Noise"}= "Velocity Noise";
- $map{"Initial Scalar Noise"}= "Remap Noise to Scalar";
- $map{"Lifespan from distance to world"}= "Lifetime from Time to Impact";
- $map{"Pre-Age Noise"}= "Lifetime Pre-Age Noise";
- $map{"lifetime_random"}= "Lifetime Random";
- $map{"radius_random"}= "Radius Random";
- $map{"random yaw"}= "Rotation Yaw Random";
- $map{"Randomly Flip Yaw"}= "Rotation Yaw Flip Random";
- $map{"rotation_random"}= "Rotation Random";
- $map{"rotation_speed_random"}= "Rotation Speed Random";
- $map{"sequence_random"}= "Sequence Random";
- $map{"second_sequence_random"}= "Sequence Two Random";
- $map{"trail_length_random"}= "Trail Length Random";
- $map{"velocity_random"}= "Velocity Random";
-}
-
diff --git a/src/devtools/bin/fxc_prep.pl b/src/devtools/bin/fxc_prep.pl
deleted file mode 100644
index 9f67ca50..00000000
--- a/src/devtools/bin/fxc_prep.pl
+++ /dev/null
@@ -1,949 +0,0 @@
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-
-sub ReadInputFile
-{
- local( $filename ) = shift;
- local( *INPUT );
- local( @output );
- open INPUT, "<$filename" || die;
-
- local( $line );
- local( $linenum ) = 1;
- while( $line = )
- {
-# print "LINE: $line";
-# $line =~ s/\n//g;
-# local( $postfix ) = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
-# $postfix .= "; LINEINFO($filename)($linenum)\n";
- if( $line =~ m/\#include\s+\"(.*)\"/i )
- {
- push @output, &ReadInputFile( $1 );
- }
- else
- {
-# push @output, $line . $postfix;
- push @output, $line;
- }
- $linenum++;
- }
-
- close INPUT;
-# print "-----------------\n";
-# print @output;
-# print "-----------------\n";
- return @output;
-}
-
-$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0;
-$generateListingFile = 0;
-$spewCombos = 0;
-
-@startTimes = times;
-$startTime = time;
-
-$g_produceCppClasses = 1;
-$g_produceCompiledVcs = 1;
-
-while( 1 )
-{
- $fxc_filename = shift;
- if( $fxc_filename =~ m/-source/ )
- {
- shift;
- }
- elsif( $fxc_filename =~ m/-nv3x/i )
- {
- $nvidia = 1;
- }
- elsif( $fxc_filename =~ m/-ps20a/i )
- {
- $ps2a = 1;
- }
- elsif( $fxc_filename =~ m/-x360/i )
- {
- # enable x360
- $g_x360 = 1;
- }
- elsif( $fxc_filename =~ m/-novcs/i )
- {
- $g_produceCompiledVcs = 0;
- }
- elsif( $fxc_filename =~ m/-nocpp/i )
- {
- $g_produceCppClasses = 0;
- }
- else
- {
- last;
- }
-}
-
-$argstring = $fxc_filename;
-$fxc_basename = $fxc_filename;
-$fxc_basename =~ s/^.*-----//;
-$fxc_filename =~ s/-----.*$//;
-
-$debug = 0;
-$forcehalf = 0;
-
-sub ToUpper
-{
- local( $in ) = shift;
- $in =~ tr/a-z/A-Z/;
- return $in;
-}
-
-sub CreateCCodeToSpewDynamicCombo
-{
- local( $out ) = "";
-
- $out .= "\t\tOutputDebugString( \"src:$fxc_filename vcs:$fxc_basename dynamic index\" );\n";
- $out .= "\t\tchar tmp[128];\n";
- $out .= "\t\tint shaderID = ";
- local( $scale ) = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- local( $name ) = @dynamicDefineNames[$i];
- local( $varname ) = "m_n" . $name;
- $out .= "( $scale * $varname ) + ";
- $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- $out .= "0;\n";
- if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 )
- {
- $out .= "\t\tint nCombo = shaderID;\n";
- }
-
- my $type = GetShaderType( $fxc_filename );
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $out .= "\t\tint n$dynamicDefineNames[$i] = nCombo % ";
- $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
- $out .= ";\n";
-
- $out .= "\t\tsprintf( tmp, \"\%d\", n$dynamicDefineNames[$i] );\n";
- $out .= "\t\tOutputDebugString( \" $dynamicDefineNames[$i]";
- $out .= "=\" );\n";
- $out .= "\t\tOutputDebugString( tmp );\n";
-
- $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
- $out .= "\n";
- }
- $out .= "\t\tOutputDebugString( \"\\n\" );\n";
- return $out;
-}
-
-sub CreateCCodeToSpewStaticCombo
-{
- local( $out ) = "";
-
- $out .= "\t\tOutputDebugString( \"src:$fxc_filename vcs:$fxc_basename static index\" );\n";
- $out .= "\t\tchar tmp[128];\n";
- $out .= "\t\tint shaderID = ";
-
- local( $scale ) = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- local( $name ) = @staticDefineNames[$i];
- local( $varname ) = "m_n" . $name;
- $out .= "( $scale * $varname ) + ";
- $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
- }
- $out .= "0;\n";
-
-# $out .= "\t\tsprintf( tmp, \"\%d\\n\", shaderID );\n";
-# $out .= "\t\tOutputDebugString( tmp );\n\n";
- if( scalar( @staticDefineNames ) + scalar( @staticDefineNames ) > 0 )
- {
- $out .= "\t\tint nCombo = shaderID;\n";
- }
-
- my $type = GetShaderType( $fxc_filename );
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $out .= "\t\tint n$staticDefineNames[$i] = nCombo % ";
- $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
- $out .= ";\n";
-
- $out .= "\t\tsprintf( tmp, \"\%d\", n$staticDefineNames[$i] );\n";
- $out .= "\t\tOutputDebugString( \" $staticDefineNames[$i]";
- $out .= "=\" );\n";
- $out .= "\t\tOutputDebugString( tmp );\n";
-
- $out .= "\t\tnCombo = nCombo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n";
- $out .= "\n";
- }
- $out .= "\t\tOutputDebugString( \"\\n\" );\n";
- return $out;
-}
-
-sub WriteHelperVar
-{
- local( $name ) = shift;
- local( $min ) = shift;
- local( $max ) = shift;
- local( $varname ) = "m_n" . $name;
- local( $boolname ) = "m_b" . $name;
- push @outputHeader, "private:\n";
- push @outputHeader, "\tint $varname;\n";
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\tbool $boolname;\n";
- push @outputHeader, "#endif\n";
- push @outputHeader, "public:\n";
- # int version of set function
- push @outputHeader, "\tvoid Set" . $name . "( int i )\n";
- push @outputHeader, "\t{\n";
- push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
- push @outputHeader, "\t\t$varname = i;\n";
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = true;\n";
- push @outputHeader, "#endif\n";
- push @outputHeader, "\t}\n";
- # bool version of set function
- push @outputHeader, "\tvoid Set" . $name . "( bool i )\n";
- push @outputHeader, "\t{\n";
-# push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
- push @outputHeader, "\t\t$varname = i ? 1 : 0;\n";
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = true;\n";
- push @outputHeader, "#endif\n";
- push @outputHeader, "\t}\n";
-}
-
-sub WriteStaticBoolExpression
-{
- local( $prefix ) = shift;
- local( $operator ) = shift;
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- if( $i )
- {
- push @outputHeader, " $operator ";
- }
- local( $name ) = @staticDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- push @outputHeader, "$prefix$boolname";
- }
- push @outputHeader, ";\n";
-}
-
-sub WriteDynamicBoolExpression
-{
- local( $prefix ) = shift;
- local( $operator ) = shift;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- if( $i )
- {
- push @outputHeader, " $operator ";
- }
- local( $name ) = @dynamicDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- push @outputHeader, "$prefix$boolname";
- }
- push @outputHeader, ";\n";
-}
-
-sub WriteDynamicHelperClasses
-{
- local( $basename ) = $fxc_basename;
- $basename =~ tr/A-Z/a-z/;
- local( $classname ) = $basename . "_Dynamic_Index";
- push @outputHeader, "class $classname\n";
- push @outputHeader, "{\n";
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $name = $dynamicDefineNames[$i];
- $min = $dynamicDefineMin[$i];
- $max = $dynamicDefineMax[$i];
- &WriteHelperVar( $name, $min, $max );
- }
- push @outputHeader, "public:\n";
-# push @outputHeader, "void SetPixelShaderIndex( IShaderAPI *pShaderAPI ) { pShaderAPI->SetPixelShaderIndex( GetIndex() ); }\n";
- push @outputHeader, "\t$classname()\n";
- push @outputHeader, "\t{\n";
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- local( $name ) = @dynamicDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- local( $varname ) = "m_n" . $name;
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = false;\n";
- push @outputHeader, "#endif // _DEBUG\n";
- push @outputHeader, "\t\t$varname = 0;\n";
- }
- push @outputHeader, "\t}\n";
- push @outputHeader, "\tint GetIndex()\n";
- push @outputHeader, "\t{\n";
- push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
- foreach $skip (@perlskipcodeindividual)
- {
- # can't do this static and dynamic can see each other.
-# $skip =~ s/\$/m_n/g;
-# $skip =~ s/defined//g;
-# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
-# print "\t\tAssert( !( $skip ) );\n";
- }
- push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
-
- push @outputHeader, "#ifdef _DEBUG\n";
- if( scalar( @dynamicDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tbool bAllDynamicVarsDefined = ";
- WriteDynamicBoolExpression( "", "&&" );
- }
- if( scalar( @dynamicDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tAssert( bAllDynamicVarsDefined );\n";
- }
- push @outputHeader, "#endif // _DEBUG\n";
-
- if( $spewCombos && scalar( @dynamicDefineNames ) )
- {
- push @outputHeader, &CreateCCodeToSpewDynamicCombo();
- }
- push @outputHeader, "\t\treturn ";
- local( $scale ) = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- local( $name ) = @dynamicDefineNames[$i];
- local( $varname ) = "m_n" . $name;
- push @outputHeader, "( $scale * $varname ) + ";
- $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- push @outputHeader, "0;\n";
- push @outputHeader, "\t}\n";
- push @outputHeader, "};\n";
- push @outputHeader, "\#define shaderDynamicTest_" . $basename . " ";
- my $prefix;
- my $shaderType = &GetShaderType( $fxc_filename );
- if( $shaderType =~ m/^vs/i )
- {
- $prefix = "vsh_";
- }
- else
- {
- $prefix = "psh_";
- }
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- local( $name ) = @dynamicDefineNames[$i];
- push @outputHeader, $prefix . "forgot_to_set_dynamic_" . $name . " + ";
- }
- push @outputHeader, "0\n";
-}
-
-sub WriteStaticHelperClasses
-{
- local( $basename ) = $fxc_basename;
- $basename =~ tr/A-Z/a-z/;
- local( $classname ) = $basename . "_Static_Index";
- push @outputHeader, "#include \"shaderlib/cshader.h\"\n";
- push @outputHeader, "class $classname\n";
- push @outputHeader, "{\n";
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $name = $staticDefineNames[$i];
- $min = $staticDefineMin[$i];
- $max = $staticDefineMax[$i];
- &WriteHelperVar( $name, $min, $max );
- }
- push @outputHeader, "public:\n";
-# push @outputHeader, "void SetShaderIndex( IShaderShadow *pShaderShadow ) { pShaderShadow->SetPixelShaderIndex( GetIndex() ); }\n";
- push @outputHeader, "\t$classname( )\n";
- push @outputHeader, "\t{\n";
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- local( $name ) = @staticDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- local( $varname ) = "m_n" . $name;
- if ( length( $staticDefineInit{$name} ) )
- {
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = true;\n";
- push @outputHeader, "#endif // _DEBUG\n";
- push @outputHeader, "\t\t$varname = $staticDefineInit{$name};\n";
- }
- else
- {
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = false;\n";
- push @outputHeader, "#endif // _DEBUG\n";
- push @outputHeader, "\t\t$varname = 0;\n";
- }
- }
- push @outputHeader, "\t}\n";
- push @outputHeader, "\tint GetIndex()\n";
- push @outputHeader, "\t{\n";
- push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
- foreach $skip (@perlskipcodeindividual)
- {
- $skip =~ s/\$/m_n/g;
-# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
- }
- push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
-
- push @outputHeader, "#ifdef _DEBUG\n";
- if( scalar( @staticDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tbool bAllStaticVarsDefined = ";
- WriteStaticBoolExpression( "", "&&" );
-
- }
- if( scalar( @staticDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tAssert( bAllStaticVarsDefined );\n";
- }
- push @outputHeader, "#endif // _DEBUG\n";
-
- if( $spewCombos && scalar( @staticDefineNames ) )
- {
- push @outputHeader, &CreateCCodeToSpewStaticCombo();
- }
- push @outputHeader, "\t\treturn ";
- local( $scale ) = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- local( $name ) = @staticDefineNames[$i];
- local( $varname ) = "m_n" . $name;
- push @outputHeader, "( $scale * $varname ) + ";
- $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
- }
- push @outputHeader, "0;\n";
- push @outputHeader, "\t}\n";
- push @outputHeader, "};\n";
- push @outputHeader, "\#define shaderStaticTest_" . $basename . " ";
- my $prefix;
- my $shaderType = &GetShaderType( $fxc_filename );
- if( $shaderType =~ m/^vs/i )
- {
- $prefix = "vsh_";
- }
- else
- {
- $prefix = "psh_";
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- local( $name ) = @staticDefineNames[$i];
- push @outputHeader, $prefix . "forgot_to_set_static_" . $name . " + " unless (length($staticDefineInit{$name} ));
- }
- push @outputHeader, "0\n";
-}
-
-sub GetNewMainName
-{
- local( $shadername ) = shift;
- local( $combo ) = shift;
- local( $i );
- $shadername =~ s/\./_/g;
- local( $name ) = $shadername;
- for( $i = 0; $i < scalar( @defineNames ); $i++ )
- {
- local( $val ) = ( $combo % ( $defineMax[$i] - $defineMin[$i] + 1 ) ) + $defineMin[$i];
- $name .= "_" . $defineNames[$i] . "_" . $val;
- $combo = $combo / ( $defineMax[$i] - $defineMin[$i] + 1 );
- }
-# return $name;
- return "main";
-}
-
-sub RenameMain
-{
- local( $shadername ) = shift;
- local( $combo ) = shift;
- local( $name ) = &GetNewMainName( $shadername, $combo );
- return "/Dmain=$name /E$name ";
-}
-
-sub GetShaderType
-{
- local( $shadername ) = shift; # hack - use global variables
- $shadername = $fxc_basename;
- if( $shadername =~ m/ps30/i )
- {
- if( $debug )
- {
- return "ps_3_sw";
- }
- else
- {
- return "ps_3_0";
- }
- }
- elsif( $shadername =~ m/ps20b/i )
- {
- return "ps_2_b";
- }
- elsif( $shadername =~ m/ps20/i )
- {
- if( $debug )
- {
- return "ps_2_sw";
- }
- else
- {
- if( $ps2a )
- {
- return "ps_2_a";
- }
- else
- {
- return "ps_2_0";
- }
- }
- }
- elsif( $shadername =~ m/ps14/i )
- {
- return "ps_1_4";
- }
- elsif( $shadername =~ m/ps11/i )
- {
- return "ps_1_1";
- }
- elsif( $shadername =~ m/vs30/i )
- {
- if( $debug )
- {
- return "vs_3_sw";
- }
- else
- {
- return "vs_3_0";
- }
- }
- elsif( $shadername =~ m/vs20/i )
- {
- if( $debug )
- {
- return "vs_2_sw";
- }
- else
- {
- return "vs_2_0";
- }
- }
- elsif( $shadername =~ m/vs14/i )
- {
- return "vs_1_1";
- }
- elsif( $shadername =~ m/vs11/i )
- {
- return "vs_1_1";
- }
- else
- {
- die "\n\nSHADERNAME = $shadername\n\n";
- }
-}
-
-sub CalcNumCombos
-{
- local( $i, $numCombos );
- $numCombos = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
- }
- return $numCombos;
-}
-
-sub CalcNumDynamicCombos
-{
- local( $i, $numCombos );
- $numCombos = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- return $numCombos;
-}
-
-sub CreateCFuncToCreateCompileCommandLine
-{
- local( $out ) = "";
-
- $out .= "\t\tOutputDebugString( \"compiling src:$fxc_filename vcs:$fxc_basename \" );\n";
- $out .= "\t\tchar tmp[128];\n";
- $out .= "\t\tsprintf( tmp, \"\%d\\n\", shaderID );\n";
- $out .= "\t\tOutputDebugString( tmp );\n";
- $out .= "\t\tstatic PrecompiledShaderByteCode_t byteCode;\n";
- if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 )
- {
- $out .= "\t\tint nCombo = shaderID;\n";
- }
-
-# $out .= "\tvoid BuildCompileCommandLine( int nCombo, char *pResult, int maxLength )\n";
-# $out .= "\t{\n";
- $out .= "\t\tD3DXMACRO ";
- $out .= "defineMacros";
- $out .= "[";
- $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) + 1; # add 1 for null termination
- $out .= "];\n";
- if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 )
- {
- $out .= "\t\tchar tmpStringBuf[1024];\n";
- $out .= "\t\tchar *pTmpString = tmpStringBuf;\n\n";
- }
-
- local( $i );
- my $type = GetShaderType( $fxc_filename );
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $out .= "\t\tsprintf( pTmpString, \"%d\", nCombo % ";
- $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
- $out .= " );\n";
- $out .= "\t\tdefineMacros";
- $out .= "[";
- $out .= $i;
- $out .= "]";
- $out .= "\.Name = ";
- $out .= "\"$dynamicDefineNames[$i]\";\n";
-
- $out .= "\t\tint n$dynamicDefineNames[$i] = nCombo % ";
- $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
- $out .= ";\n";
- $out .= "\t\tUNUSED( n$dynamicDefineNames[$i] );\n";
-
- $out .= "\t\tdefineMacros";
- $out .= "[";
- $out .= $i;
- $out .= "]";
- $out .= "\.Definition = ";
- $out .= "pTmpString;\n";
- $out .= "\t\tpTmpString += strlen( pTmpString ) + 1;\n";
-
- $out .= "\t\tsprintf( tmp, \"\%d\", n$dynamicDefineNames[$i] );\n";
- $out .= "\t\tOutputDebugString( \" $dynamicDefineNames[$i]";
- $out .= "=\" );\n";
- $out .= "\t\tOutputDebugString( tmp );\n";
-
- $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
- $out .= "\n";
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $out .= "\t\tsprintf( pTmpString, \"%d\", nCombo % ";
- $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
- $out .= " );\n";
- $out .= "\t\tdefineMacros";
- $out .= "[";
- $out .= $i + scalar( @dynamicDefineNames );
- $out .= "]";
- $out .= "\.Name = ";
- $out .= "\"$staticDefineNames[$i]\";\n";
-
- $out .= "\t\tint n$staticDefineNames[$i] = nCombo % ";
- $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
- $out .= ";\n";
- $out .= "\t\tUNUSED( n$staticDefineNames[$i] );\n";
-
- $out .= "\t\tdefineMacros";
- $out .= "[";
- $out .= $i + scalar( @dynamicDefineNames );
- $out .= "]";
- $out .= "\.Definition = ";
- $out .= "pTmpString;\n";
- $out .= "\t\tpTmpString += strlen( pTmpString ) + 1;\n";
-
- $out .= "\t\tsprintf( tmp, \"\%d\", n$staticDefineNames[$i] );\n";
- $out .= "\t\tOutputDebugString( \" $staticDefineNames[$i]";
- $out .= "=\" );\n";
- $out .= "\t\tOutputDebugString( tmp );\n";
-
- $out .= "\t\tnCombo = nCombo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n";
- $out .= "\n";
- }
-
- $out .= "\t\tOutputDebugString( \"\\n\" );\n";
-
- $cskipcode = $perlskipcode;
- $cskipcode =~ s/\$/n/g;
- $out .= "\t\tif( $cskipcode )\n\t\t{\n";
- $out .= "\t\t\tstatic char blah[4] = { 0, 0, 0, 0 };\n";
- $out .= "\t\t\tbyteCode.m_pRawData = blah;\n";
- $out .= "\t\t\tbyteCode.m_nSizeInBytes = 4;\n";
- $out .= "\t\t\treturn byteCode;\n";
- $out .= "\t\t}\n";
-
-
-
- $out .= "\t\t// Must null terminate macros.\n";
- $out .= "\t\tdefineMacros[";
- $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames );
- $out .= "]";
- $out .= ".Name = NULL;\n";
- $out .= "\t\tdefineMacros[";
- $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames );
- $out .= "]";
- $out .= ".Definition = NULL;\n\n";
-
-
- $out .= "\t\tLPD3DXBUFFER pShader; // NOTE: THESE LEAK!!!\n";
- $out .= "\t\tLPD3DXBUFFER pErrorMessages; // NOTE: THESE LEAK!!!\n";
- $out .= "\t\tHRESULT hr = D3DXCompileShaderFromFile( \"u:\\\\hl2_e3_2004\\\\src_e3_2004\\\\materialsystem\\\\stdshaders\\\\$fxc_filename\",\n\t\t\tdefineMacros,\n\t\t\tNULL, // LPD3DXINCLUDE \n\t\t\t\"main\",\n\t\t\t\"$type\",\n\t\t\t0, // DWORD Flags\n\t\t\t&pShader,\n\t\t\t&pErrorMessages,\n\t\t\tNULL // LPD3DXCONSTANTTABLE *ppConstantTable\n\t\t\t );\n";
- $out .= "\t\tif( hr != D3D_OK )\n";
- $out .= "\t\t{\n";
- $out .= "\t\t\tconst char *pErrorMessageString = ( const char * )pErrorMessages->GetBufferPointer();\n";
- $out .= "\t\t\tOutputDebugString( pErrorMessageString );\n";
- $out .= "\t\t\tOutputDebugString( \"\\n\" );\n";
- $out .= "\t\t\tAssert( 0 );\n";
- $out .= "\t\t\tstatic char blah[4] = { 0, 0, 0, 0 };\n";
- $out .= "\t\t\tbyteCode.m_pRawData = blah;\n";
- $out .= "\t\t\tbyteCode.m_nSizeInBytes = 4;\n";
- $out .= "\t\t}\n";
- $out .= "\t\telse\n";
- $out .= "\t\t{\n";
- $out .= "\t\t\tbyteCode.m_pRawData = pShader->GetBufferPointer();\n";
- $out .= "\t\t\tbyteCode.m_nSizeInBytes = pShader->GetBufferSize();\n";
- $out .= "\t\t}\n";
- $out .= "\t\treturn byteCode;\n";
- return $out;
-}
-
-#print "--------\n";
-
-if ( $g_x360 )
-{
- $fxctmp = "fxctmp9_360_tmp";
-}
-else
-{
- $fxctmp = "fxctmp9_tmp";
-}
-
-if( !stat $fxctmp )
-{
- mkdir $fxctmp, 0777 || die $!;
-}
-
-# suck in an input file (using includes)
-#print "$fxc_filename...";
-@fxc = ReadInputFile( $fxc_filename );
-
-# READ THE TOP OF THE FILE TO FIND SHADER COMBOS
-foreach $line ( @fxc )
-{
- $line="" if ($g_x360 && ($line=~/\[PC\]/)); # line marked as [PC] when building for x360
- $line="" if (($g_x360 == 0) && ($line=~/\[XBOX\]/)); # line marked as [XBOX] when building for pc
-
- if ( $fxc_basename =~ m/_ps(\d+\w?)$/i )
- {
- my $psver = $1;
- $line="" if (($line =~/\[ps\d+\w?\]/i) && ($line!~/\[ps$psver\]/i)); # line marked for a version of compiler and not what we build
- }
- if ( $fxc_basename =~ m/_vs(\d+\w?)$/i )
- {
- my $vsver = $1;
- $line="" if (($line =~/\[vs\d+\w?\]/i) && ($line!~/\[vs$vsver\]/i)); # line marked for a version of compiler and not what we build
- }
-
- my $init_expr;
-
- $init_expr = $1 if ( $line=~/\[\=([^\]]+)\]/); # parse default init expression for combos
-
- $line=~s/\[[^\[\]]*\]//; # cut out all occurrences of
- # square brackets and whatever is
- # inside all these modifications
- # to the line are seen later when
- # processing skips and centroids
-
- next if( $line =~ m/^\s*$/ );
-
- if( $line =~ m/^\s*\/\/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
- {
- local( $name, $min, $max );
- $name = $1;
- $min = $2;
- $max = $3;
- # print STDERR "STATIC: \"$name\" \"$min..$max\"\n";
- push @staticDefineNames, $name;
- push @staticDefineMin, $min;
- push @staticDefineMax, $max;
- $staticDefineInit{$name}=$init_expr;
- }
- elsif( $line =~ m/^\s*\/\/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
- {
- local( $name, $min, $max );
- $name = $1;
- $min = $2;
- $max = $3;
- # print STDERR "DYNAMIC: \"$name\" \"$min..$max\"\n";
- push @dynamicDefineNames, $name;
- push @dynamicDefineMin, $min;
- push @dynamicDefineMax, $max;
- }
-}
-# READ THE WHOLE FILE AND FIND SKIP STATEMENTS
-foreach $line ( @fxc )
-{
- if( $line =~ m/^\s*\/\/\s*SKIP\s*\s*\:\s*(.*)$/ )
- {
- # print $1 . "\n";
- $perlskipcode .= "(" . $1 . ")||";
- push @perlskipcodeindividual, $1;
- }
-}
-
-if( defined $perlskipcode )
-{
- $perlskipcode .= "0";
- $perlskipcode =~ s/\n//g;
-}
-else
-{
- $perlskipcode = "0";
-}
-
-# READ THE WHOLE FILE AND FIND CENTROID STATEMENTS
-foreach $line ( @fxc )
-{
- if( $line =~ m/^\s*\/\/\s*CENTROID\s*\:\s*TEXCOORD(\d+)\s*$/ )
- {
- $centroidEnable{$1} = 1;
-# print "CENTROID: $1\n";
- }
-}
-
-if( $spewCombos )
-{
- push @outputHeader, "#include \"windows.h\"\n";
-}
-
-#push @outputHeader, "\#include \"shaderlib\\baseshader.h\"\n";
-#push @outputHeader, "IShaderDynamicAPI *CBaseShader::s_pShaderAPI;\n";
-
-# Go ahead an compute the mask of samplers that need to be centroid sampled
-$centroidMask = 0;
-foreach $centroidRegNum ( keys( %centroidEnable ) )
-{
-# print "THING: $samplerName $centroidRegNum\n";
- $centroidMask += 1 << $centroidRegNum;
-}
-
-#printf "0x%x\n", $centroidMask;
-
-$numCombos = &CalcNumCombos();
-#print "$numCombos combos\n";
-
-
-if( $g_produceCompiledVcs && !$dynamic_compile )
-{
- open FOUT, ">>filelistgen.txt" || die "can't open filelistgen.txt";
-
- print FOUT "**** generated by fxc_prep.pl ****\n";
- print FOUT "#BEGIN " . $fxc_basename . "\n";
- print FOUT "$fxc_filename" . "\n";
- print FOUT "#DEFINES-D:\n";
- for( $i = 0; $i < scalar( @dynamicDefineNames ); \$i++ )
- {
- print FOUT "$dynamicDefineNames[$i]=";
- print FOUT $dynamicDefineMin[$i];
- print FOUT "..";
- print FOUT $dynamicDefineMax[$i];
- print FOUT "\n";
- }
- print FOUT "#DEFINES-S:\n";
- for( $i = 0; $i < scalar( @staticDefineNames ); \$i++ )
- {
- print FOUT "$staticDefineNames[$i]=";
- print FOUT $staticDefineMin[$i];
- print FOUT "..";
- print FOUT $staticDefineMax[$i];
- print FOUT "\n";
- }
- print FOUT "#SKIP:\n";
- print FOUT "$perlskipcode\n";
- print FOUT "#COMMAND:\n";
- # first line
- print FOUT "fxc.exe ";
- print FOUT "/DTOTALSHADERCOMBOS=$numCombos ";
- print FOUT "/DCENTROIDMASK=$centroidMask ";
- print FOUT "/DNUMDYNAMICCOMBOS=" . &CalcNumDynamicCombos() . " ";
- print FOUT "/DFLAGS=0x0 "; # Nothing here for now.
- print FOUT "\n";
-#defines go here
-# second line
- print FOUT &RenameMain( $fxc_filename, $i );
- print FOUT "/T" . &GetShaderType( $fxc_filename ) . " ";
- print FOUT "/DSHADER_MODEL_" . &ToUpper( &GetShaderType( $fxc_filename ) ) . "=1 ";
- if( $nvidia )
- {
- print FOUT "/DNV3X=1 "; # enable NV3X codepath
- }
- if ( $g_x360 )
- {
- print FOUT "/D_X360=1 "; # shaders can identify X360 centric code
- # print FOUT "/Xbe:2- "; # use the less-broken old back end
- }
- if( $debug )
- {
- print FOUT "/Od "; # disable optimizations
- print FOUT "/Zi "; # enable debug info
- }
-# print FOUT "/Zi "; # enable debug info
- print FOUT "/nologo ";
-# print FOUT "/Fhtmpshader.h ";
- print FOUT "/Foshader.o ";
- print FOUT "$fxc_filename";
- print FOUT ">output.txt 2>&1";
- print FOUT "\n";
- #end of command line
- print FOUT "#END\n";
- print FOUT "**** end ****\n";
-
- close FOUT;
-}
-
-if ( $g_produceCppClasses )
-{
- # Write out the C++ helper class for picking shader combos
- &WriteStaticHelperClasses();
- &WriteDynamicHelperClasses();
- my $incfilename = "$fxctmp\\$fxc_basename" . ".inc";
- &WriteFile( $incfilename, join( "", @outputHeader ) );
-}
-
-
-
-if( $generateListingFile )
-{
- my $listFileName = "$fxctmp/$fxc_basename" . ".lst";
- print "writing $listFileName\n";
- if( !open FILE, ">$listFileName" )
- {
- die;
- }
- print FILE @listingOutput;
- close FILE;
-}
-
-
-@endTimes = times;
-
-$endTime = time;
-
-#printf "Elapsed user time: %.2f seconds!\n", $endTimes[0] - $startTimes[0];
-#printf "Elapsed system time: %.2f seconds!\n", $endTimes[1] - $startTimes[1];
-#printf "Elapsed child user time: %.2f seconds!\n", $endTimes[2] - $startTimes[2];
-#printf "Elapsed child system time: %.2f seconds!\n", $endTimes[3] - $startTimes[3];
-
-#printf "Elapsed total time: %.2f seconds!\n", $endTime - $startTime;
-
diff --git a/src/devtools/bin/linux/ccache b/src/devtools/bin/linux/ccache
deleted file mode 100755
index 99dd2b4a..00000000
Binary files a/src/devtools/bin/linux/ccache and /dev/null differ
diff --git a/src/devtools/bin/osx32/ccache b/src/devtools/bin/osx32/ccache
deleted file mode 100755
index 1b6a2e5f..00000000
Binary files a/src/devtools/bin/osx32/ccache and /dev/null differ
diff --git a/src/devtools/bin/osx32/protoc b/src/devtools/bin/osx32/protoc
deleted file mode 100755
index f111cb24..00000000
Binary files a/src/devtools/bin/osx32/protoc and /dev/null differ
diff --git a/src/devtools/bin/osx32/xcode_ccache_wrapper b/src/devtools/bin/osx32/xcode_ccache_wrapper
deleted file mode 100755
index 475f508f..00000000
--- a/src/devtools/bin/osx32/xcode_ccache_wrapper
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-exec $(dirname $0)/ccache "${DT_TOOLCHAIN_DIR}"/usr/bin/clang -Qunused-arguments "$@"
diff --git a/src/devtools/bin/process_shaders.ps1 b/src/devtools/bin/process_shaders.ps1
new file mode 100644
index 00000000..d2e19895
--- /dev/null
+++ b/src/devtools/bin/process_shaders.ps1
@@ -0,0 +1,31 @@
+[CmdletBinding()]
+param (
+ [Parameter(Mandatory=$true, ValueFromPipeline=$true)][System.IO.FileInfo]$File,
+ [Parameter(Mandatory=$true)][string]$Version,
+ [Parameter(Mandatory=$false)][switch]$Dynamic,
+ [Parameter(Mandatory=$false)][System.UInt32]$Threads
+)
+
+if ($Version -notin @("20b", "30", "40", "41", "50", "51")) {
+ return
+}
+
+$fileList = $File.OpenText()
+while ($null -ne ($line = $fileList.ReadLine())) {
+ if ($line -match '^\s*$' -or $line -match '^\s*//') {
+ continue
+ }
+
+ if ($Dynamic) {
+ & "$PSScriptRoot\ShaderCompile2" "-dynamic" "-ver" $Version "-shaderpath" $File.DirectoryName $line
+ continue
+ }
+
+ if ($Threads -ne 0) {
+ & "$PSScriptRoot\ShaderCompile2" "-threads" $Threads "-ver" $Version "-shaderpath" $File.DirectoryName $line
+ continue
+ }
+
+ & "$PSScriptRoot\ShaderCompile2" "-ver" $Version "-shaderpath" $File.DirectoryName $line
+}
+$fileList.Close()
diff --git a/src/devtools/bin/psh_prep.pl b/src/devtools/bin/psh_prep.pl
deleted file mode 100644
index 1c44c41d..00000000
--- a/src/devtools/bin/psh_prep.pl
+++ /dev/null
@@ -1,333 +0,0 @@
-use String::CRC32;
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-
-sub BuildDefineOptions
-{
- local( $output );
- local( $combo ) = shift;
- local( $i );
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- local( $val ) = ( $combo % ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) ) + $dynamicDefineMin[$i];
- $output .= "/D$dynamicDefineNames[$i]=$val ";
- $combo = $combo / ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 );
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- local( $val ) = ( $combo % ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) ) + $staticDefineMin[$i];
- $output .= "/D$staticDefineNames[$i]=$val ";
- $combo = $combo / ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 );
- }
- return $output;
-}
-
-sub CalcNumCombos
-{
- local( $i, $numCombos );
- $numCombos = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
- }
- return $numCombos;
-}
-
-sub CalcNumDynamicCombos
-{
- local( $i, $numCombos );
- $numCombos = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- return $numCombos;
-}
-
-$g_dx9 = 1;
-
-while( 1 )
-{
- $psh_filename = shift;
-
- if( $psh_filename =~ m/-source/ )
- {
- $g_SourceDir = shift;
- }
- elsif( $psh_filename =~ m/-x360/ )
- {
- $g_x360 = 1;
- }
- else
- {
- last;
- }
-}
-
-$psh_filename =~ s/-----.*$//;
-
-
-# Get the shader binary version number from a header file.
-open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die;
-while( $line = )
-{
- if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ )
- {
- $shaderVersion = $1;
- last;
- }
-}
-if( !defined $shaderVersion )
-{
- die "couldn't get shader version from shader_vcs_version.h";
-}
-close FILE;
-
-
-
-local( @staticDefineNames );
-local( @staticDefineMin );
-local( @staticDefineMax );
-local( @dynamicDefineNames );
-local( @dynamicDefineMin );
-local( @dynamicDefineMax );
-
-# Parse the combos.
-open PSH, "<$psh_filename";
-while( )
-{
- last if( !m,^;, );
- s,^;\s*,,;
- if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
- {
- local( $name, $min, $max );
- $name = $1;
- $min = $2;
- $max = $3;
-# print "\"STATIC: $name\" \"$min..$max\"\n";
- if (/\[(.*)\]/)
- {
- $platforms=$1;
- next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
- next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
- }
- push @staticDefineNames, $name;
- push @staticDefineMin, $min;
- push @staticDefineMax, $max;
- }
- elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
- {
- local( $name, $min, $max );
- $name = $1;
- $min = $2;
- $max = $3;
-# print "\"DYNAMIC: $name\" \"$min..$max\"\n";
- if (/\[(.*)\]/)
- {
- $platforms=$1;
- next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
- next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
- }
- push @dynamicDefineNames, $name;
- push @dynamicDefineMin, $min;
- push @dynamicDefineMax, $max;
- }
-}
-close PSH;
-
-$numCombos = &CalcNumCombos();
-$numDynamicCombos = &CalcNumDynamicCombos();
-print "$psh_filename\n";
-#print "$numCombos combos\n";
-#print "$numDynamicCombos dynamic combos\n";
-
-if( $g_x360 )
-{
- $pshtmp = "pshtmp9_360";
-}
-elsif( $g_dx9 )
-{
- $pshtmp = "pshtmp9";
-}
-else
-{
- $pshtmp = "pshtmp8";
-}
-$basename = $psh_filename;
-$basename =~ s/\.psh$//i;
-
-for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
-{
- my $tempFilename = "shader$shaderCombo.o";
- unlink $tempFilename;
-
- if( $g_x360 )
- {
- $cmd = "$g_SourceDir\\x360xdk\\bin\\win32\\psa /D_X360=1 /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL";
- }
- else
- {
- $cmd = "$g_SourceDir\\dx9sdk\\utilities\\psa /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL";
- }
-
- if( !stat $pshtmp )
- {
- mkdir $pshtmp, 0777 || die $!;
- }
-
-# print $cmd . "\n";
- system $cmd || die $!;
-
- # Make sure a file got generated because sometimes the die above won't happen on compile errors.
- my $filesize = (stat $tempFilename)[7];
- if ( !$filesize )
- {
- die "Error compiling shader$shaderCombo.o";
- }
-
- push @outputHeader, @hdr;
-}
-
-$basename =~ s/\.fxc//gi;
-push @outputHeader, "static PrecompiledShaderByteCode_t " . $basename . "_pixel_shaders[" . $numCombos . "] = \n";
-push @outputHeader, "{\n";
-local( $j );
-for( $j = 0; $j < $numCombos; $j++ )
-{
- local( $thing ) = "pixelShader_" . $basename . "_" . $j;
- push @outputHeader, "\t{ " . "$thing, sizeof( $thing ) },\n";
-}
-push @outputHeader, "};\n";
-
-push @outputHeader, "struct $basename" . "PixelShader_t : public PrecompiledShader_t\n";
-push @outputHeader, "{\n";
-push @outputHeader, "\t$basename" . "PixelShader_t()\n";
-push @outputHeader, "\t{\n";
-push @outputHeader, "\t\tm_nFlags = 0;\n";
-push @outputHeader, "\t\tm_pByteCode = " . $basename . "_pixel_shaders;\n";
-push @outputHeader, "\t\tm_nShaderCount = $numCombos;\n";
-#push @outputHeader, "\t\tm_nDynamicCombos = m_nShaderCount;\n";
-push @outputHeader, "\t\t// NOTE!!! psh_prep.pl shaders are always static combos!\n";
-push @outputHeader, "\t\tm_nDynamicCombos = 1;\n";
-push @outputHeader, "\t\tm_pName = \"$basename\";\n";
-if( $basename =~ /vs\d\d/ ) # hack
-{
- push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n";
-}
-else
-{
- push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_PIXEL_SHADER, this );\n";
-}
-push @outputHeader, "\t}\n";
-push @outputHeader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n";
-push @outputHeader, "\t{\n";
-push @outputHeader, "\t\treturn m_pByteCode[shaderID];\n";
-push @outputHeader, "\t}\n";
-push @outputHeader, "};\n";
-
-push @outputHeader, "static $basename" . "PixelShader_t $basename" . "_PixelShaderInstance;\n";
-
-
-&MakeDirHier( "shaders/psh" );
-
-my $vcsName = "";
-if( $g_x360 )
-{
- $vcsName = $basename . ".360.vcs";
-}
-else
-{
- $vcsName = $basename . ".vcs";
-}
-
-open COMPILEDSHADER, ">shaders/psh/$vcsName" || die;
-binmode( COMPILEDSHADER );
-
-#
-# Write out the part of the header that we know. . we'll write the rest after writing the object code.
-#
-
-#print $numCombos . "\n";
-
-# Pack arguments
-my $sInt = "i";
-my $uInt = "I";
-if ( $g_x360 )
-{
- # Change arguments to "big endian long"
- $sInt = "N";
- $uInt = "N";
-}
-
-open PSH, "<$psh_filename";
-my $crc = crc32( *PSH );
-close PSH;
-#print STDERR "crc for $psh_filename: $crc\n";
-
-# version
-print COMPILEDSHADER pack $sInt, 4;
-# totalCombos
-print COMPILEDSHADER pack $sInt, $numCombos;
-# dynamic combos
-print COMPILEDSHADER pack $sInt, $numDynamicCombos;
-# flags
-print COMPILEDSHADER pack $uInt, 0x0; # nothing here for now.
-# centroid mask
-print COMPILEDSHADER pack $uInt, 0;
-# reference size for diffs
-print COMPILEDSHADER pack $uInt, 0;
-# crc32 of the source code
-print COMPILEDSHADER pack $uInt, $crc;
-
-my $beginningOfDir = tell COMPILEDSHADER;
-
-# Write out a blank directionary. . we'll fill it in later.
-for( $i = 0; $i < $numCombos; $i++ )
-{
- # offset from beginning of file.
- print COMPILEDSHADER pack $sInt, 0;
- # size
- print COMPILEDSHADER pack $sInt, 0;
-}
-
-my $startByteCode = tell COMPILEDSHADER;
-my @byteCodeStart;
-my @byteCodeSize;
-
-# Write out the shader object code.
-for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
-{
- my $filename = "shader$shaderCombo\.o";
- my $filesize = (stat $filename)[7];
-
- $byteCodeStart[$shaderCombo] = tell COMPILEDSHADER;
- $byteCodeSize[$shaderCombo] = $filesize;
- open SHADERBYTECODE, "<$filename";
- binmode SHADERBYTECODE;
-
- my $bin;
- my $numread = read SHADERBYTECODE, $bin, $filesize;
-# print "filename: $filename numread: $numread filesize: $filesize\n";
- close SHADERBYTECODE;
- unlink $filename;
-
- print COMPILEDSHADER $bin;
-}
-
-# Seek back to the directory and write it out.
-seek COMPILEDSHADER, $beginningOfDir, 0;
-for( $i = 0; $i < $numCombos; $i++ )
-{
- # offset from beginning of file.
- print COMPILEDSHADER pack $sInt, $byteCodeStart[$i];
- # size
- print COMPILEDSHADER pack $sInt, $byteCodeSize[$i];
-}
-
-close COMPILEDSHADER;
-
-
diff --git a/src/devtools/bin/shaderinfo.pl b/src/devtools/bin/shaderinfo.pl
deleted file mode 100644
index 57a81578..00000000
--- a/src/devtools/bin/shaderinfo.pl
+++ /dev/null
@@ -1,36 +0,0 @@
-#! perl
-
-my $fname=shift || die "format is shaderinfo blah.vcs";
-
-open(SHADER, $fname) || die "can't open $fname";
-binmode SHADER;
-
-read(SHADER,$header,20);
-($ver,$ntotal,$ndynamic,$flags,$centroidmask)=unpack("LLLLL",$header);
-
-#print "Version $ver total combos=$ntotal, num dynamic combos=$ndynamic,\n flags=$flags, centroid mask=$centroidmask\n";
-
-read(SHADER,$refsize,4);
-$refsize=unpack("L",$refsize);
-#print "Size of reference shader for diffing=$refsize\n";
-
-seek(SHADER,$refsize,1);
-
-$nskipped_combos=0;
-for(1..$ntotal)
- {
- read(SHADER,$combodata,8);
- ($ofs,$combosize)=unpack("LL",$combodata);
- if ( $ofs == 0xffffffff)
- {
- $nskipped_combos++;
- }
- else
- {
- }
- }
-#print "$nskipped_combos skipped, for an actual total of ",$ntotal-$nskipped_combos,"\n";
-#print "Real to skipped ratio = ",($ntotal-$nskipped_combos)/$ntotal,"\n";
-# csv output - name, real combos, virtual combos, dynamic combos
-my $real_combos=$ntotal-$nskipped_combos;
-print "$fname,$real_combos,$ntotal,$ndynamic\n";
diff --git a/src/devtools/bin/splitdiff3.pl b/src/devtools/bin/splitdiff3.pl
deleted file mode 100644
index ccba3a95..00000000
--- a/src/devtools/bin/splitdiff3.pl
+++ /dev/null
@@ -1,54 +0,0 @@
-$infilename = shift;
-$outfilename1 = shift;
-$outfilename2 = shift;
-open INPUT, $infilename || die;
-@input = ;
-close INPUT;
-
-open MERGEDMINE, ">$outfilename1" || die;
-open MERGEDTHEIRS, ">$outfilename2" || die;
-
-for( $i = 0; $i < scalar( @input ); $i++ )
-{
- $line = $input[$i];
-
- if( $line =~ m/^(.*)<<<<<< )
- {
- $first = 1;
- $second = 0;
- print MERGEDMINE $1;
- print MERGEDTHEIRS $1;
- next;
- }
- # Make sure that we are in a split block so that comments with ======= don't mess us up.
- if( $line =~ m/^(.*)=======$/ && $first == 1 )
- {
- $first = 0;
- $second = 1;
- print MERGEDMINE $1;
- next;
- }
- if( $line =~ m/^(.*)>>>>>>>/ )
- {
- $first = $second = 0;
- print MERGEDTHEIRS $1;
- next;
- }
-
- if( $first )
- {
- print MERGEDMINE $line;
- }
- elsif( $second )
- {
- print MERGEDTHEIRS $line;
- }
- else
- {
- print MERGEDMINE $line;
- print MERGEDTHEIRS $line;
- }
-}
-
-close MERGEDMINE;
-close MERGEDTHEIRS;
diff --git a/src/devtools/bin/texttoarray.py b/src/devtools/bin/texttoarray.py
new file mode 100755
index 00000000..ec04c8c2
--- /dev/null
+++ b/src/devtools/bin/texttoarray.py
@@ -0,0 +1,22 @@
+import sys
+
+def main(filename, objname):
+ with open(filename, 'rb') as file:
+ data = file.read()
+
+ output = f"static unsigned char {objname}[] = {{\n "
+
+ for i in range(len(data)):
+ output += f"0x{data[i]:02x},"
+ if i % 20 == 19:
+ output += "\n "
+
+ output += "0x00\n};\n"
+ print(output)
+
+if __name__ == "__main__":
+ if len(sys.argv) < 3:
+ print("Usage: python texttoarray.py ")
+ sys.exit(1)
+
+ main(sys.argv[1], sys.argv[2])
diff --git a/src/devtools/bin/tier0.dll b/src/devtools/bin/tier0.dll
new file mode 100644
index 00000000..c3533325
Binary files /dev/null and b/src/devtools/bin/tier0.dll differ
diff --git a/src/devtools/bin/uniqifylist.pl b/src/devtools/bin/uniqifylist.pl
deleted file mode 100644
index 1c3fd9c9..00000000
--- a/src/devtools/bin/uniqifylist.pl
+++ /dev/null
@@ -1,6 +0,0 @@
-foreach $_ (sort <> )
-{
- next if( defined( $prevline ) && $_ eq $prevline );
- $prevline = $_;
- print;
-}
diff --git a/src/devtools/bin/updateshaders.pl b/src/devtools/bin/updateshaders.pl
deleted file mode 100644
index 93f57ffd..00000000
--- a/src/devtools/bin/updateshaders.pl
+++ /dev/null
@@ -1,305 +0,0 @@
-use String::CRC32;
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-
-$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0;
-
-$depnum = 0;
-$baseSourceDir = ".";
-
-my %dep;
-
-sub GetAsmShaderDependencies_R
-{
- local( $shadername ) = shift;
- local( *SHADER );
-
- open SHADER, "<$shadername";
- while( )
- {
- if( m/^\s*\#\s*include\s+\"(.*)\"/ )
- {
- # make sure it isn't in there already.
- if( !defined( $dep{$1} ) )
- {
- $dep{$1} = 1;
- GetAsmShaderDependencies_R( $1 );
- }
- }
- }
- close SHADER;
-}
-
-sub GetAsmShaderDependencies
-{
- local( $shadername ) = shift;
- undef %dep;
- GetAsmShaderDependencies_R( $shadername );
-# local( $i );
-# foreach $i ( keys( %dep ) )
-# {
-# print "$shadername depends on $i\n";
-# }
- return keys( %dep );
-}
-
-sub GetShaderType
-{
- my $shadername = shift;
- my $shadertype;
- if( $shadername =~ m/\.vsh/i )
- {
- $shadertype = "vsh";
- }
- elsif( $shadername =~ m/\.psh/i )
- {
- $shadertype = "psh";
- }
- elsif( $shadername =~ m/\.fxc/i )
- {
- $shadertype = "fxc";
- }
- else
- {
- die;
- }
- return $shadertype;
-}
-
-sub GetShaderSrc
-{
- my $shadername = shift;
- if ( $shadername =~ m/^(.*)-----/i )
- {
- return $1;
- }
- else
- {
- return $shadername;
- }
-}
-
-sub GetShaderBase
-{
- my $shadername = shift;
- if ( $shadername =~ m/-----(.*)$/i )
- {
- return $1;
- }
- else
- {
- my $shadertype = &GetShaderType( $shadername );
- $shadername =~ s/\.$shadertype//i;
- return $shadername;
- }
-}
-
-sub DoAsmShader
-{
- my $argstring = shift;
- my $shadername = &GetShaderSrc( $argstring );
- my $shaderbase = &GetShaderBase( $argstring );
- my $shadertype = &GetShaderType( $argstring );
- my $incfile = "";
- if( $shadertype eq "fxc" || $shadertype eq "vsh" )
- {
- $incfile = $shadertype . "tmp9" . $g_tmpfolder . "\\$shaderbase.inc ";
- }
-
- my $vcsfile = $shaderbase . $g_vcsext;
- my $bWillCompileVcs = 1;
- if( ( $shadertype eq "fxc") && $dynamic_compile )
- {
- $bWillCompileVcs = 0;
- }
- if( $shadercrcpass{$argstring} )
- {
- $bWillCompileVcs = 0;
- }
-
- if( $bWillCompileVcs )
- {
- &output_makefile_line( $incfile . "shaders\\$shadertype\\$vcsfile: $shadername @dep\n") ;
- }
- else
- {
- # psh files don't need a rule at this point since they don't have inc files and we aren't compiling a vcs.
- if( $shadertype eq "fxc" || $shadertype eq "vsh" )
- {
- &output_makefile_line( $incfile . ": $shadername @dep\n") ;
- }
- }
-
-
- my $x360switch = "";
- my $moreswitches = "";
- if( !$bWillCompileVcs && $shadertype eq "fxc" )
- {
- $moreswitches .= "-novcs ";
- }
- if( $g_x360 )
- {
- $x360switch = "-x360";
-
- if( $bWillCompileVcs && ( $shaderbase =~ m/_ps20$/i ) )
- {
- $moreswitches .= "-novcs ";
- $bWillCompileVcs = 0;
- }
- }
-
- # if we are psh and we are compiling the vcs, we don't need this rule.
- if( !( $shadertype eq "psh" && !$bWillCompileVcs ) )
- {
- &output_makefile_line( "\tperl $g_SourceDir\\devtools\\bin\\" . $shadertype . "_prep.pl $moreswitches $x360switch -source \"$g_SourceDir\" $argstring\n") ;
- }
-
- if( $bWillCompileVcs )
- {
- &output_makefile_line( "\techo $shadername>> filestocopy.txt\n") ;
- my $dep;
- foreach $dep( @dep )
- {
- &output_makefile_line( "\techo $dep>> filestocopy.txt\n") ;
- }
- }
- &output_makefile_line( "\n") ;
-}
-
-if( scalar( @ARGV ) == 0 )
-{
- die "Usage updateshaders.pl shaderprojectbasename\n\tie: updateshaders.pl stdshaders_dx6\n";
-}
-
-$g_x360 = 0;
-$g_tmpfolder = "_tmp";
-$g_vcsext = ".vcs";
-
-while( 1 )
-{
- $inputbase = shift;
-
- if( $inputbase =~ m/-source/ )
- {
- $g_SourceDir = shift;
- }
- elsif( $inputbase =~ m/-x360/ )
- {
- $g_x360 = 1;
- $g_tmpfolder = "_360_tmp";
- $g_vcsext = ".360.vcs";
- }
- elsif( $inputbase =~ m/-execute/ )
- {
- $g_execute = 1;
- }
- elsif( $inputbase =~ m/-nv3x/ )
- {
- $nv3x = 1;
- }
- else
- {
- last;
- }
-}
-
-my @srcfiles = &LoadShaderListFile( $inputbase );
-
-open MAKEFILE, ">makefile\.$inputbase";
-open COPYFILE, ">makefile\.$inputbase\.copy";
-open INCLIST, ">inclist.txt";
-open VCSLIST, ">vcslist.txt";
-
-# make a default dependency that depends on all of the shaders.
-&output_makefile_line( "default: ") ;
-foreach $shader ( @srcfiles )
-{
- my $shadertype = &GetShaderType( $shader );
- my $shaderbase = &GetShaderBase( $shader );
- my $shadersrc = &GetShaderSrc( $shader );
- if( $shadertype eq "fxc" || $shadertype eq "vsh" )
- {
- # We only generate inc files for fxc and vsh files.
- my $incFileName = "$shadertype" . "tmp9" . $g_tmpfolder . "\\" . $shaderbase . "\.inc";
- &output_makefile_line( " $incFileName" );
- &output_inclist_line( "$incFileName\n" );
- }
-
- my $vcsfile = $shaderbase . $g_vcsext;
-
- my $compilevcs = 1;
- if( $shadertype eq "fxc" && $dynamic_compile )
- {
- $compilevcs = 0;
- }
- if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) )
- {
- $compilevcs = 0;
- }
- if( $compilevcs )
- {
- my $vcsFileName = "..\\..\\..\\game\\hl2\\shaders\\$shadertype\\$shaderbase" . $g_vcsext;
- # We want to check for perforce operations even if the crc matches in the event that a file has been manually reverted and needs to be checked out again.
- &output_vcslist_line( "$vcsFileName\n" );
- $shadercrcpass{$shader} = &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 0 );
- if( $shadercrcpass{$shader} )
- {
- $compilevcs = 0;
- }
- }
- if( $compilevcs )
- {
- &output_makefile_line( " shaders\\$shadertype\\$vcsfile" );
- # emit a list of vcs files to copy to the target since we want to build them.
- &output_copyfile_line( GetShaderSrc($shader) . "-----" . GetShaderBase($shader) . "\n" );
- }
-}
-&output_makefile_line( "\n\n") ;
-
-# Insert all of our vertex shaders and depencencies
-$lastshader = "";
-foreach $shader ( @srcfiles )
-{
- my $currentshader = &GetShaderSrc( $shader );
- if ( $lastshader ne $currentshader )
- {
- $lastshader = $currentshader;
- @dep = &GetAsmShaderDependencies( $lastshader );
- }
- &DoAsmShader( $shader );
-}
-close VCSLIST;
-close INCLIST;
-close COPYFILE;
-close MAKEFILE;
-
-# nuke the copyfile if it is zero length
-if( ( stat "makefile\.$inputbase\.copy" )[7] == 0 )
-{
- unlink "makefile\.$inputbase\.copy";
-}
-
-sub output_makefile_line
-{
- local ($_)=@_;
- print MAKEFILE $_;
-}
-
-sub output_copyfile_line
-{
- local ($_)=@_;
- print COPYFILE $_;
-}
-
-sub output_vcslist_line
-{
- local ($_)=@_;
- print VCSLIST $_;
-}
-
-sub output_inclist_line
-{
- local ($_)=@_;
- print INCLIST $_;
-}
-
diff --git a/src/devtools/bin/valve_perl_helpers.pl b/src/devtools/bin/valve_perl_helpers.pl
deleted file mode 100644
index 9257767a..00000000
--- a/src/devtools/bin/valve_perl_helpers.pl
+++ /dev/null
@@ -1,558 +0,0 @@
-sub BackToForwardSlash
-{
- my( $path ) = shift;
- $path =~ s,\\,/,g;
- return $path;
-}
-
-sub RemoveFileName
-{
- my( $in ) = shift;
- $in = &BackToForwardSlash( $in );
- $in =~ s,/[^/]*$,,;
- return $in;
-}
-
-sub RemovePath
-{
- my( $in ) = shift;
- $in = &BackToForwardSlash( $in );
- $in =~ s,^(.*)/([^/]*)$,$2,;
- return $in;
-}
-
-sub MakeDirHier
-{
- my( $in ) = shift;
-# print "MakeDirHier( $in )\n";
- $in = &BackToForwardSlash( $in );
- my( @path );
- while( $in =~ m,/, ) # while $in still has a slash
- {
- my( $end ) = &RemovePath( $in );
- push @path, $end;
-# print $in . "\n";
- $in = &RemoveFileName( $in );
- }
- my( $i );
- my( $numelems ) = scalar( @path );
- my( $curpath );
- for( $i = $numelems - 1; $i >= 0; $i-- )
- {
- $curpath .= "/" . $path[$i];
- my( $dir ) = $in . $curpath;
- if( !stat $dir )
- {
-# print "mkdir $dir\n";
- mkdir $dir, 0777;
- }
- }
-}
-
-sub FileExists
-{
- my $filename = shift;
- my @statresult = stat $filename;
- my $iswritable = @statresult != 0;
- return $iswritable;
-}
-
-sub MakeFileWritable
-{
- my $filename = shift;
- if ( &FileExists( $filename ) )
- {
- chmod 0666, $filename || die;
- }
-}
-
-sub MakeFileReadOnly
-{
- my $filename = shift;
- chmod 0444, $filename || die;
-}
-
-# Run a command and get stdout and stderr to an array
-sub RunCommand
-{
- my $cmd = shift;
-# print STDERR "command: $cmd\n";
- system "$cmd > cmdout.txt 2>&1" || die;
- local( *FILE );
- open FILE, ";
-# print STDERR "command output: @output\n";
- close FILE;
- unlink "cmdout.txt" || die;
- return @output;
-}
-
-sub PerforceEditOrAdd
-{
- return;
- my $filename = shift;
- my $changelistarg = shift;
-
- # Is the file on the client?
- my $cmd = "p4 fstat \"$filename\"";
- my @p4output = &RunCommand( $cmd );
- my $p4output = join "", @p4output;
- if( $p4output =~ m/no such file/ )
- {
- # not on client. . add
- my $cmd = "p4 add $changelistarg $filename";
- my @p4output = &RunCommand( $cmd );
- my $p4output = join "", @p4output;
- if( $p4output =~ m/opened for add/ )
- {
- print $p4output;
- return;
- }
- print "ERROR: $p4output";
- return;
- }
-
- # The file is known to be on the client at this point.
-
- # Is it open for edit?
- if( $p4output =~ m/action edit/ )
- {
- # Is is open for edit, let's see if it's still different.
- # check for opened files that are not different from the revision in the depot.
- my $cmd = "p4 diff -sr \"$filename\"";
- my @p4output = &RunCommand( $cmd );
- my $outputstring = join "", @p4output;
- # check for empty string
- if( !( $outputstring =~ m/^\s*$/ ) )
- {
- my $cmd = "p4 revert \"$filename\"";
- my @p4output = &RunCommand( $cmd );
- my $outputstring = join "", @p4output;
- print $outputstring;
- return;
- }
- }
-
- # check for unopened files that are different from the revision in the depot.
- my $cmd = "p4 diff -se \"$filename\"";
- my @p4output = &RunCommand( $cmd );
- my $outputstring = join "", @p4output;
- # check for empty string
- if( $outputstring =~ m/^\s*$/ )
- {
- &MakeFileReadOnly( $filename );
- return;
- }
-
- # We need to edit the file since it is known to be different here.
- my $cmd = "p4 edit $changelistarg \"$filename\"";
- my @p4output = &RunCommand( $cmd );
-
- my $line;
- foreach $line ( @p4output )
- {
- if( $line =~ m/not on client/ )
- {
- #print "notonclient...";
- print "ERROR: @p4output\n";
- return;
- }
- if( $line =~ m/currently opened for edit/ )
- {
- return;
- }
- if( $line =~ m/opened for edit/ )
- {
- print $line;
- }
- }
-}
-
-sub FileIsWritable
-{
- local( $filename ) = shift;
- local( @statresult ) = stat $filename;
- local( $mode, $iswritable );
- $mode = oct( $statresult[2] );
- $iswritable = ( $mode & 2 ) != 0;
- return $iswritable;
-}
-
-sub TouchFile
-{
- my $filename = shift;
- if( !&FileExists( $filename ) )
- {
- if( !open FILE, ">$filename" )
- {
- die;
- }
- close FILE;
- }
- my $now = time;
- local( *FILE );
- utime $now, $now, $filename;
-}
-
-sub FileExistsInPerforce
-{
- my $filename = shift;
- my @output = &RunCommand( "p4 fstat $filename" );
- my $line;
- foreach $line (@output)
- {
- if( $line =~ m/no such file/ )
- {
- return 0;
- }
- }
- return 1;
-}
-
-sub PerforceWriteFile
-{
- my $filename = shift;
- my $filecontents = shift;
-# my $changelistname = shift;
-
- # Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
-# my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`;
- # Get rid of the newline
-# $changelistnumber =~ s/\n//g;
-
-# my $changelistarg = "";
-# if( $changelistnumber != 0 )
-# {
-# $changelistarg = "-c $changelistnumber"
-# }
-
- # Make the target vcs writable if it exists
- MakeFileWritable( $filename );
-
- # Write the file.
- local( *FP );
- open FP, ">$filename";
- print FP $filecontents;
- close FP;
-
- # Do whatever needs to happen with perforce for this file.
-# &PerforceEditOrAdd( $filename, $changelistarg );
-}
-
-sub WriteFile
-{
- my $filename = shift;
- my $filecontents = shift;
-
- # Make the target vcs writable if it exists
- MakeFileWritable( $filename );
-
- # Write the file.
- local( *FP );
- open FP, ">$filename";
- print FP $filecontents;
- close FP;
-}
-
-sub PrintCleanPerforceOutput
-{
- my $line;
- while( $line = shift )
- {
- if( $line =~ m/currently opened/i )
- {
- next;
- }
- if( $line =~ m/already opened for edit/i )
- {
- next;
- }
- if( $line =~ m/also opened/i )
- {
- next;
- }
- if( $line =~ m/add of existing file/i )
- {
- next;
- }
- print $line;
- }
-}
-
-# HACK!!!! Need to pass something in to do this rather than hard coding.
-sub NormalizePerforceFilename
-{
- my $line = shift;
-
- # remove newlines.
- $line =~ s/\n//;
- # downcase.
- $line =~ tr/[A-Z]/[a-z]/;
- # backslash to forwardslash
- $line =~ s,\\,/,g;
-
- # for inc files HACK!
- $line =~ s/^.*(fxctmp9.*)/$1/i;
- $line =~ s/^.*(vshtmp9.*)/$1/i;
-
- # for vcs files. HACK!
- $line =~ s,^.*game/hl2/shaders/,,i;
-
- return $line;
-}
-
-sub MakeSureFileExists
-{
- local( $filename ) = shift;
- local( $testexists ) = shift;
- local( $testwrite ) = shift;
-
- local( @statresult ) = stat $filename;
- if( !@statresult && $testexists )
- {
- die "$filename doesn't exist!\n";
- }
- local( $mode, $iswritable );
- $mode = oct( $statresult[2] );
- $iswritable = ( $mode & 2 ) != 0;
- if( !$iswritable && $testwrite )
- {
- die "$filename isn't writable!\n";
- }
-}
-
-sub LoadShaderListFile_GetShaderType
-{
- my $shadername = shift;
- my $shadertype;
- if( $shadername =~ m/\.vsh/i )
- {
- $shadertype = "vsh";
- }
- elsif( $shadername =~ m/\.psh/i )
- {
- $shadertype = "psh";
- }
- elsif( $shadername =~ m/\.fxc/i )
- {
- $shadertype = "fxc";
- }
- else
- {
- die;
- }
- return $shadertype;
-}
-
-sub LoadShaderListFile_GetShaderSrc
-{
- my $shadername = shift;
- if ( $shadername =~ m/^(.*)-----/i )
- {
- return $1;
- }
- else
- {
- return $shadername;
- }
-}
-
-sub LoadShaderListFile_GetShaderBase
-{
- my $shadername = shift;
- if ( $shadername =~ m/-----(.*)$/i )
- {
- return $1;
- }
- else
- {
- my $shadertype = &LoadShaderListFile_GetShaderType( $shadername );
- $shadername =~ s/\.$shadertype//i;
- return $shadername;
- }
-}
-
-sub LoadShaderListFile
-{
- my $inputbase = shift;
-
- my @srcfiles;
- &MakeSureFileExists( "$inputbase.txt", 1, 0 );
-
- open SHADERLISTFILE, "<$inputbase.txt" || die;
- my $line;
- while( $line = )
- {
- $line =~ s/\/\/.*$//; # remove comments "//..."
- $line =~ s/^\s*//; # trim leading whitespace
- $line =~ s/\s*$//; # trim trailing whitespace
- next if( $line =~ m/^\s*$/ );
- if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ )
- {
- my $shaderbase = &LoadShaderListFile_GetShaderBase( $line );
-
- if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30
- {
- my $targetbase = $shaderbase;
- $targetbase =~ s/_ps2x/_ps30/i;
- $targetbase =~ s/_ps20b/_ps30/i;
- $targetbase =~ s/_ps20/_ps30/i;
- $targetbase =~ s/_vs20/_vs30/i;
- $targetbase =~ s/_vsxx/_vs30/i;
- push @srcfiles, ( $line . "-----" . $targetbase );
- }
- else
- {
- if( $shaderbase =~ m/_ps2x/i )
- {
- my $targetbase = $shaderbase;
- $targetbase =~ s/_ps2x/_ps20/i;
- push @srcfiles, ( $line . "-----" . $targetbase );
-
- $targetbase = $shaderbase;
- $targetbase =~ s/_ps2x/_ps20b/i;
- push @srcfiles, ( $line . "-----" . $targetbase );
- }
- elsif( $shaderbase =~ m/_vsxx/i )
- {
- my $targetbase = $shaderbase;
- $targetbase =~ s/_vsxx/_vs11/i;
- push @srcfiles, ( $line . "-----" . $targetbase );
-
- $targetbase = $shaderbase;
- $targetbase =~ s/_vsxx/_vs20/i;
- push @srcfiles, ( $line . "-----" . $targetbase );
- }
- else
- {
- push @srcfiles, ( $line . "-----" . $shaderbase );
- }
- }
- }
- }
- close SHADERLISTFILE;
- return @srcfiles;
-}
-
-sub ReadInputFileWithIncludes
-{
- local( $filename ) = shift;
-# print STDERR "ReadInputFileWithIncludes: $filename\n";
-
- local( *INPUT );
- local( $output );
-
-# print STDERR "before open\n";
- open INPUT, "<$filename" || die;
-# print STDERR "after open\n";
-
- local( $line );
- while( $line = )
- {
-# print STDERR $line;
- if( $line =~ m/\#include\s+\"(.*)\"/i )
- {
- $output.= ReadInputFileWithIncludes( $1 );
- }
- else
- {
- $output .= $line;
- }
- }
-
- close INPUT;
- return $output;
-}
-
-sub GetCRCFromSourceFile
-{
- my $filename = shift;
- my $data = &ReadInputFileWithIncludes( $filename );
-# print STDERR $data;
- $crc = crc32( $data );
-# print STDERR "GetCRCFromSourceFile: $crc\n";
- return $crc;
-}
-
-sub GetCRCFromVCSFile
-{
- my $filename = shift;
-# print STDERR "GetCRCFromVCSFile $filename\n";
- local( *FP );
- open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n";
- binmode( FP );
-
- # unpack arguments
- my $sInt = "i";
- my $uInt = "I";
- if( $filename =~ m/\.360\./ )
- {
- # Change arguments to "big endian long"
- $sInt = "N";
- $uInt = "N";
- }
-
- my $header;
- read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n";
- my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc;
- ($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header;
- unless( $version == 4 || $version == 5 || $version == 6 )
- {
- print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n";
- return 0;
- }
-# print STDERR "version: $version\n";
-# print STDERR "numCombos: $numCombos\n";
-# print STDERR "numDynamicCombos: $numDynamicCombos\n";
-# print STDERR "flags: $flags\n";
-# print STDERR "centroidMask: $centroidMask\n";
-# print STDERR "refSize: $refSize\n";
-# print STDERR "GetCRCFromVCSFile: $crc\n";
- close( FP );
- return $crc;
-}
-
-sub CheckCRCAgainstTarget
-{
- my $srcFileName = shift;
- my $vcsFileName = shift;
- my $warn = shift;
-
- # Make sure both files exist.
-# print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) );
-# print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) );
- if( !( -e $srcFileName ) )
- {
- if( $warn )
- {
- print "$srcFileName missing\n";
- }
- return 0;
- }
- if( !( -e $vcsFileName ) )
- {
- if( $warn )
- {
- print "$vcsFileName missing\n";
- }
- return 0;
- }
-# print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n";
-# print STDERR "vcsFileName: $vcsFileName\n";
-# print STDERR "vcsFileName: $srcFileName\n";
- my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName );
- my $srcCRC = &GetCRCFromSourceFile( $srcFileName );
- if( $warn && ( $vcsCRC != $srcCRC ) )
- {
- print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n";
- }
-
-# return 0; # use this to skip crc checking.
-# if( $vcsCRC == $srcCRC )
-# {
-# print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n";
-# }
- return $vcsCRC == $srcCRC;
-}
-
-1;
diff --git a/src/devtools/bin/vpc b/src/devtools/bin/vpc
index 3874f82c..2192fa18 100755
Binary files a/src/devtools/bin/vpc and b/src/devtools/bin/vpc differ
diff --git a/src/devtools/bin/vpc.exe b/src/devtools/bin/vpc.exe
old mode 100644
new mode 100755
index 8c4fd6aa..8bdf3d16
Binary files a/src/devtools/bin/vpc.exe and b/src/devtools/bin/vpc.exe differ
diff --git a/src/devtools/bin/vpc_linux b/src/devtools/bin/vpc_linux
deleted file mode 100755
index e7680782..00000000
Binary files a/src/devtools/bin/vpc_linux and /dev/null differ
diff --git a/src/devtools/bin/vpc_osx b/src/devtools/bin/vpc_osx
deleted file mode 100755
index 2827ae4b..00000000
Binary files a/src/devtools/bin/vpc_osx and /dev/null differ
diff --git a/src/devtools/bin/vpccrccheck.exe b/src/devtools/bin/vpccrccheck.exe
deleted file mode 100755
index 5a151b00..00000000
Binary files a/src/devtools/bin/vpccrccheck.exe and /dev/null differ
diff --git a/src/devtools/bin/vsh_prep.pl b/src/devtools/bin/vsh_prep.pl
deleted file mode 100644
index 8161c494..00000000
--- a/src/devtools/bin/vsh_prep.pl
+++ /dev/null
@@ -1,1106 +0,0 @@
-use String::CRC32;
-BEGIN {use File::Basename; push @INC, dirname($0); }
-require "valve_perl_helpers.pl";
-
-sub WriteHelperVar
-{
- local( $name ) = shift;
- local( $min ) = shift;
- local( $max ) = shift;
- local( $varname ) = "m_n" . $name;
- local( $boolname ) = "m_b" . $name;
- push @outputHeader, "private:\n";
- push @outputHeader, "\tint $varname;\n";
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\tbool $boolname;\n";
- push @outputHeader, "#endif\n";
- push @outputHeader, "public:\n";
- # int version of set function
- push @outputHeader, "\tvoid Set" . $name . "( int i )\n";
- push @outputHeader, "\t{\n";
- if ( $min != $max )
- {
- push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
- push @outputHeader, "\t\t$varname = i;\n";
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = true;\n";
- push @outputHeader, "#endif\n";
- }
- push @outputHeader, "\t}\n";
- # bool version of set function
- push @outputHeader, "\tvoid Set" . $name . "( bool i )\n";
- push @outputHeader, "\t{\n";
- if ( $min != $max )
- {
-# push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
- push @outputHeader, "\t\t$varname = i ? 1 : 0;\n";
- push @outputHeader, "#ifdef _DEBUG\n";
- push @outputHeader, "\t\t$boolname = true;\n";
- push @outputHeader, "#endif\n";
- }
- push @outputHeader, "\t}\n";
-}
-
-sub WriteStaticBoolExpression
-{
- local( $prefix ) = shift;
- local( $operator ) = shift;
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- if( $i )
- {
- push @outputHeader, " $operator ";
- }
- local( $name ) = @staticDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- push @outputHeader, "$prefix$boolname";
- }
- push @outputHeader, ";\n";
-}
-
-sub WriteDynamicBoolExpression
-{
- local( $prefix ) = shift;
- local( $operator ) = shift;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- if( $i )
- {
- push @outputHeader, " $operator ";
- }
- local( $name ) = @dynamicDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- push @outputHeader, "$prefix$boolname";
- }
- push @outputHeader, ";\n";
-}
-
-sub WriteDynamicHelperClasses
-{
- local( $basename ) = $fxc_filename;
- $basename =~ s/\.fxc//i;
- $basename =~ tr/A-Z/a-z/;
- local( $classname ) = $basename . "_Dynamic_Index";
- push @outputHeader, "class $classname\n";
- push @outputHeader, "{\n";
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $name = $dynamicDefineNames[$i];
- $min = $dynamicDefineMin[$i];
- $max = $dynamicDefineMax[$i];
- &WriteHelperVar( $name, $min, $max );
- }
- push @outputHeader, "public:\n";
- push @outputHeader, "\t$classname()\n";
- push @outputHeader, "\t{\n";
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $min = $dynamicDefineMin[$i];
- $max = $dynamicDefineMax[$i];
-
- local( $name ) = @dynamicDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- local( $varname ) = "m_n" . $name;
- push @outputHeader, "#ifdef _DEBUG\n";
- if ( $min != $max )
- {
- push @outputHeader, "\t\t$boolname = false;\n";
- }
- else
- {
- push @outputHeader, "\t\t$boolname = true;\n";
- }
- push @outputHeader, "#endif // _DEBUG\n";
- push @outputHeader, "\t\t$varname = 0;\n";
- }
- push @outputHeader, "\t}\n";
- push @outputHeader, "\tint GetIndex()\n";
- push @outputHeader, "\t{\n";
- push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
- foreach $skip (@perlskipcodeindividual)
- {
- $skip =~ s/\$/m_n/g;
-# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
- }
- push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
-
- push @outputHeader, "#ifdef _DEBUG\n";
- if( scalar( @dynamicDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tbool bAllDynamicVarsDefined = ";
- WriteDynamicBoolExpression( "", "&&" );
- }
- if( scalar( @dynamicDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tAssert( bAllDynamicVarsDefined );\n";
- }
- push @outputHeader, "#endif // _DEBUG\n";
-
- if( $spewCombos && scalar( @dynamicDefineNames ) )
- {
- push @outputHeader, &CreateCCodeToSpewDynamicCombo();
- }
- push @outputHeader, "\t\treturn ";
- local( $scale ) = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- local( $name ) = @dynamicDefineNames[$i];
- local( $varname ) = "m_n" . $name;
- push @outputHeader, "( $scale * $varname ) + ";
- $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- push @outputHeader, "0;\n";
- push @outputHeader, "\t}\n";
- push @outputHeader, "};\n";
-}
-
-sub WriteStaticHelperClasses
-{
- local( $basename ) = $fxc_filename;
- $basename =~ s/\.fxc//i;
- $basename =~ tr/A-Z/a-z/;
- local( $classname ) = $basename . "_Static_Index";
- push @outputHeader, "class $classname\n";
- push @outputHeader, "{\n";
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $name = $staticDefineNames[$i];
- $min = $staticDefineMin[$i];
- $max = $staticDefineMax[$i];
- &WriteHelperVar( $name, $min, $max );
- }
- push @outputHeader, "public:\n";
- push @outputHeader, "\t$classname()\n";
- push @outputHeader, "\t{\n";
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $min = $staticDefineMin[$i];
- $max = $staticDefineMax[$i];
-
- local( $name ) = @staticDefineNames[$i];
- local( $boolname ) = "m_b" . $name;
- local( $varname ) = "m_n" . $name;
-
- push @outputHeader, "#ifdef _DEBUG\n";
- if ( $min != $max )
- {
- push @outputHeader, "\t\t$boolname = false;\n";
- }
- else
- {
- push @outputHeader, "\t\t$boolname = true;\n";
- }
- push @outputHeader, "#endif // _DEBUG\n";
- push @outputHeader, "\t\t$varname = 0;\n";
- }
- push @outputHeader, "\t}\n";
- push @outputHeader, "\tint GetIndex()\n";
- push @outputHeader, "\t{\n";
- push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
- foreach $skip (@perlskipcodeindividual)
- {
- $skip =~ s/\$/m_n/g;
-# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
- }
- push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
-
- push @outputHeader, "#ifdef _DEBUG\n";
- if( scalar( @staticDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tbool bAllStaticVarsDefined = ";
- WriteStaticBoolExpression( "", "&&" );
-
- }
- if( scalar( @staticDefineNames ) > 0 )
- {
- push @outputHeader, "\t\tAssert( bAllStaticVarsDefined );\n";
- }
- push @outputHeader, "#endif // _DEBUG\n";
-
- if( $spewCombos && scalar( @staticDefineNames ) )
- {
- push @outputHeader, &CreateCCodeToSpewStaticCombo();
- }
- push @outputHeader, "\t\treturn ";
- local( $scale ) = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- local( $name ) = @staticDefineNames[$i];
- local( $varname ) = "m_n" . $name;
- push @outputHeader, "( $scale * $varname ) + ";
- $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
- }
- push @outputHeader, "0;\n";
- push @outputHeader, "\t}\n";
- push @outputHeader, "};\n";
-}
-
-sub CreateFuncToSetPerlVars
-{
- local( $out ) = "";
-
- $out .= "sub SetPerlVarsFunc\n";
- $out .= "{\n";
- $out .= " local( \$combo ) = shift;\n";
- $out .= " local( \$i );\n";
- local( $i );
- for( $i = 0; $i < scalar( @dynamicDefineNames ); \$i++ )
- {
- $out .= " \$$dynamicDefineNames[$i] = \$combo % ";
- $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
- $out .= ";\n";
- $out .= " \$combo = \$combo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); \$i++ )
- {
- $out .= " \$$staticDefineNames[$i] = \$combo % ";
- $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
- $out .= ";\n";
- $out .= " \$combo = \$combo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n";
- }
- $out .= "}\n";
-
-# print $out;
- eval $out;
-}
-
-# These sections can be interchanged to enable profiling.
-#$ShowTimers = 1;
-#use Time::HiRes;
-#sub SampleTime()
-#{
-# return Time::HiRes::time();
-#}
-
-$ShowTimers = 0;
-sub SampleTime() { return 0; }
-
-$total_start_time = SampleTime();
-
-# NOTE: These must match the same values in macros.vsh!
-$vPos = "v0";
-$vBoneWeights = "v1";
-$vBoneIndices = "v2";
-$vNormal = "v3";
-if( $g_x360 )
-{
- $vPosFlex = "v4";
- $vNormalFlex = "v13";
-}
-$vColor = "v5";
-$vSpecular = "v6";
-$vTexCoord0 = "v7";
-$vTexCoord1 = "v8";
-$vTexCoord2 = "v9";
-$vTexCoord3 = "v10";
-$vTangentS = "v11";
-$vTangentT = "v12";
-$vUserData = "v14";
-
-sub ReadInputFileWithLineInfo
-{
- local( $base_filename ) = shift;
-
- local( *INPUT );
- local( @output );
-
- # Look in the stdshaders directory, followed by the current directory.
- # (This is for the SDK, since some of its files are under stdshaders).
- local( $filename ) = $base_filename;
- if ( !-e $filename )
- {
- $filename = "$g_SourceDir\\materialsystem\\stdshaders\\$base_filename";
- if ( !-e $filename )
- {
- die "\nvsh_prep.pl ERROR: missing include file: $filename.\n\n";
- }
- }
-
- open INPUT, "<$filename" || die;
-
- local( $line );
- local( $linenum ) = 1;
- while( $line = )
- {
- $line =~ s/\n//g;
- local( $postfix ) = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
- $postfix .= "; LINEINFO($filename)($linenum)\n";
- if( $line =~ m/\#include\s+\"(.*)\"/i )
- {
- push @output, &ReadInputFileWithLineInfo( $1 );
- }
- else
- {
- push @output, $line . $postfix;
- }
- $linenum++;
- }
-
- close INPUT;
- return @output;
-}
-
-sub ReadInputFileWithoutLineInfo
-{
- local( $base_filename ) = shift;
-
- local( *INPUT );
- local( @output );
-
- # Look in the stdshaders directory, followed by the current directory.
- # (This is for the SDK, since some of its files are under stdshaders).
- local( $filename ) = $base_filename;
- if ( !-e $filename )
- {
- $filename = "$g_SourceDir\\materialsystem\\stdshaders\\$base_filename";
- if ( !-e $filename )
- {
- die "\nERROR: missing include file: $filename.\n\n";
- }
- }
-
- open INPUT, "<$filename" || die;
-
- local( $line );
- while( $line = )
- {
- if( $line =~ m/\#include\s+\"(.*)\"/i )
- {
- push @output, &ReadInputFileWithoutLineInfo( $1 );
- }
- else
- {
- push @output, $line;
- }
- }
-
- close INPUT;
- return @output;
-}
-
-sub IsPerl
-{
- local( $line ) = shift;
- if( $line =~ m/^\s*sub.*\,/ )
- {
- return 0;
- }
- if( $line =~ m/^\#include/ ||
- $line =~ m/^\#define/ ||
- $line =~ m/^\#undef/ ||
- $line =~ m/^\#ifdef/ ||
- $line =~ m/^\#ifndef/ ||
- $line =~ m/^\#else/ ||
- $line =~ m/^\#endif/ ||
- $line =~ m/^\#error/
- )
- {
- return 0;
- }
- if( $line =~ m/^\s*if\s*\(/ ||
- $line =~ m/^\s*else/ ||
- $line =~ m/^\s*elsif/ ||
- $line =~ m/^\s*for\s*\(/ ||
- $line =~ m/^\s*\{/ ||
- $line =~ m/^sub\s*/ ||
- $line =~ m/^\s*\}/ ||
- $line =~ m/^\s*\&/ ||
- $line =~ m/^\s*\#/ ||
- $line =~ m/^\s*\$/ ||
- $line =~ m/^\s*print/ ||
- $line =~ m/^\s*return/ ||
- $line =~ m/^\s*exit/ ||
- $line =~ m/^\s*die/ ||
- $line =~ m/^\s*eval/ ||
- $line =~ m/^\s*local/ ||
- $line =~ m/^\s*my\s+/ ||
- $line =~ m/^\s*@/ ||
- $line =~ m/^\s*alloc\s+/ ||
- $line =~ m/^\s*free\s+/
- )
- {
- return 1;
- }
- return 0;
-}
-
-# translate the output into something that takes us back to the source line
-# that we care about in msdev
-sub TranslateErrorMessages
-{
- local( $origline );
- while( $origline = shift )
- {
- if( $origline =~ m/(.*)\((\d+)\)\s*:\s*(.*)$/i )
- {
- local( $filename ) = $1;
- local( $linenum ) = $2;
- local( $error ) = $3;
- local( *FILE );
- open FILE, "<$filename" || die;
- local( $i );
- local( $line );
- for( $i = 1; $i < $linenum; $i++ )
- {
- $line = ;
- }
- if( $line =~ m/LINEINFO\((.*)\)\((.*)\)/ )
- {
- print "$1\($2\) : $error\n";
- my $num = $linenum - 1;
- print "$filename\($num\) : original error location\n";
- }
- close FILE;
- }
- else
- {
- $origline =~ s/successful compile\!.*//gi;
- if( !( $origline =~ m/^\s*$/ ) )
- {
-# print "WTF: $origline\n";
- }
- }
- }
-}
-
-
-sub CountInstructions
-{
- local( $line );
- local( $count ) = 0;
- while( $line = shift )
- {
- # get rid of comments
- $line =~ s/;.*//gi;
- $line =~ s/\/\/.*//gi;
- # skip the vs1.1 statement
- $line =~ s/^\s*vs.*//gi;
- # if there's any text left, it's an instruction
- if( $line =~ /\S/gi )
- {
- $count++;
- }
- }
- return $count;
-}
-
-
-%compiled = ();
-
-sub UsesRegister
-{
- my $registerName = shift;
- my $str = shift;
-
- # Cache a compiled RE for each register name. This makes UsesRegister about 2.5x faster.
- if ( !$compiled{$registerName} )
- {
- $compiled{$registerName} = qr/\b$registerName\b/;
- }
-
- $ret = 0;
- if( $str =~ /$compiled{$registerName}/gi )
- {
- $ret = 1;
- }
-
- return $ret;
-}
-
-sub PadString
-{
- local( $str ) = shift;
- local( $desiredLen ) = shift;
- local( $len ) = length $str;
- while( $len < $desiredLen )
- {
- $str .= " ";
- $len++;
- }
- return $str;
-}
-
-sub FixupAllocateFree
-{
- local( $line ) = shift;
- $line =~ s/\&AllocateRegister\s*\(\s*\\(\S+)\s*\)/&AllocateRegister( \\$1, \"\\$1\" )/g;
- $line =~ s/\&FreeRegister\s*\(\s*\\(\S+)\s*\)/&FreeRegister( \\$1, \"\\$1\" )/g;
- $line =~ s/alloc\s+(\S+)\s*/local( $1 ); &AllocateRegister( \\$1, \"\\$1\" );/g;
- $line =~ s/free\s+(\S+)\s*/&FreeRegister( \\$1, \"\\$1\" );/g;
- return $line;
-}
-
-sub TranslateDXKeywords
-{
- local( $line ) = shift;
- $line =~ s/\bENDIF\b/endif/g;
- $line =~ s/\bIF\b/if/g;
- $line =~ s/\bELSE\b/else/g;
-
- return $line;
-}
-
-# This is used to make the generated pl files all pretty.
-sub GetLeadingWhiteSpace
-{
- local( $str ) = shift;
- if( $str =~ m/^;\S/ || $str =~ m/^; \S/ )
- {
- return "";
- }
- $str =~ s/^;/ /g; # count a leading ";" as whitespace as far as this is concerned.
- $str =~ m/^(\s*)/;
- return $1;
-}
-
-$g_dx9 = 1;
-$g_SourceDir = "..\\..";
-
-while( 1 )
-{
- $filename = shift;
-
- if ( $filename =~ m/-source/i )
- {
- $g_SourceDir = shift;
- }
- elsif( $filename =~ m/-x360/i )
- {
- $g_x360 = 1;
- }
- else
- {
- last;
- }
-}
-
-$filename =~ s/-----.*$//;
-
-
-#
-# Get the shader binary version number from a header file.
-#
-open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die;
-while( $line = )
-{
- if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ )
- {
- $shaderVersion = $1;
- last;
- }
-}
-if( !defined $shaderVersion )
-{
- die "couldn't get shader version from shader_vcs_version.h";
-}
-close FILE;
-
-
-if( $g_x360 )
-{
- $vshtmp = "vshtmp9_360_tmp";
-}
-else
-{
- $vshtmp = "vshtmp9_tmp";
-}
-
-if( !stat $vshtmp )
-{
- mkdir $vshtmp, 0777 || die $!;
-}
-
-# suck in all files, including $include files.
-@input = &ReadInputFileWithLineInfo( $filename );
-
-sub CalcNumCombos
-{
- local( $i, $numCombos );
- $numCombos = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
- {
- $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
- }
- return $numCombos;
-}
-
-sub CalcNumDynamicCombos
-{
- local( $i, $numCombos );
- $numCombos = 1;
- for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
- {
- $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
- }
- return $numCombos;
-}
-
-# READ THE TOP OF THE FILE TO FIND SHADER COMBOS
-foreach $_ ( @input )
-{
- next if( m/^\s*$/ );
-# last if( !m,^//, );
- s,^//\s*,,;
- if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
- {
- local( $name, $min, $max );
- $name = $1;
- $min = $2;
- $max = $3;
-# print "\"$name\" \"$min..$max\"\n";
- if (/\[(.*)\]/)
- {
- $platforms=$1;
- next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
- next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
- }
- push @staticDefineNames, $name;
- push @staticDefineMin, $min;
- push @staticDefineMax, $max;
- }
- elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
- {
- local( $name, $min, $max );
- $name = $1;
- $min = $2;
- $max = $3;
- if (/\[(.*)\]/)
- {
- $platforms=$1;
- next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
- next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
- }
-# print "\"$name\" \"$min..$max\"\n";
- push @dynamicDefineNames, $name;
- push @dynamicDefineMin, $min;
- push @dynamicDefineMax, $max;
- }
-}
-
-# READ THE WHOLE FILE AND FIND SKIP STATEMENTS
-foreach $_ ( @input )
-{
- if( m/^\s*\#\s*SKIP\s*\:\s*(.*\S+)\s*\; LINEINFO.*$/ )
- {
- $perlskipcode .= "(" . $1 . ")||";
- push @perlskipcodeindividual, $1;
- }
-}
-if( defined $perlskipcode )
-{
- $perlskipcode .= "0";
- $perlskipcode =~ s/\n//g;
-}
-else
-{
- $perlskipcode = "0";
-}
-
-#print $perlskipcode . "\n";
-
-
-# Translate the input into a perl program that'll unroll everything and
-# substitute variables.
-while( $inputLine = shift @input )
-{
- $inputLine =~ s/\n//g;
- # leave out lines that are only whitespace.
- if( $inputLine =~ m/^\s*; LINEINFO.*$/ )
- {
- next;
- }
- local( $inputLineNoLineNum ) = $inputLine;
- $inputLineNoLineNum =~ s/; LINEINFO.*//gi;
- if( &IsPerl( $inputLineNoLineNum ) )
- {
- $inputLineNoLineNum = &FixupAllocateFree( $inputLineNoLineNum );
- push @outputProgram, $inputLineNoLineNum . "\n";
- }
- else
- {
- # make asm lines that have quotes in them not barf.
- $inputLine =~ s/\"/\\\"/g;
- $inputLine = &TranslateDXKeywords( $inputLine );
- push @outputProgram, &GetLeadingWhiteSpace( $inputLine ) . "push \@output, \"" .
- $inputLine . "\\n\";\n";
- }
-}
-
-$outputProgram = join "", @outputProgram;
-
-$filename_base = $filename;
-$filename_base =~ s/\.vsh//i;
-
-open DEBUGOUT, ">$vshtmp" . "/$filename_base.pl" || die;
-print DEBUGOUT $outputProgram;
-close DEBUGOUT;
-
-# Make a function called OutputProgram()
-$bigProg = "sub OutputProgram { " . $outputProgram . "}";
-eval( $bigProg );
-
-
-#print $outputProgram;
-
-#push @finalheader, "// hack to force dependency checking\n";
-#push @finalheader, "\#ifdef NEVER\n";
-#push @finalheader, "\#include \"" . $filename_base . "\.vsh\"\n";
-#push @finalheader, "\#include \"..\\..\\devtools\\bin\\vsh_prep.pl\"\n";
-#push @finalheader, "\#endif\n";
-
-%g_TimingBlocks = ();
-$main_start_time = SampleTime();
-
-$numCombos = &CalcNumCombos();
-$numDynamicCombos = &CalcNumDynamicCombos();
-#print "$numCombos total combos\n";
-#print "$numDynamicCombos dynamic combos\n";
-#print $numCombos / $numDynamicCombos . " static combos\n";
-
-# Write out the C++ helper class for picking shader combos
-$fxc_filename = $filename_base;
-&WriteStaticHelperClasses();
-&WriteDynamicHelperClasses();
-
-# Create a subroutine out of $perlskipcode
-$perlskipfunc = "sub SkipCombo { return $perlskipcode; }\n";
-#print $perlskipfunc;
-
-eval $perlskipfunc;
-&CreateFuncToSetPerlVars();
-
-my $incfilename = "$vshtmp/$filename_base" . ".inc";
-
-# Write the inc file that has indexing helpers, etc.
-&WriteFile( $incfilename, join( "", @outputHeader ) );
-
-
-# Run the output program for all the combinations of bones and lights.
-print "$filename_base.vsh\n";
-for( $i = 0; $i < $numCombos; $i++ )
-{
-# print "combo $i\n";
- &SetPerlVarsFunc( $i );
- local( $compileFailed );
- $ret = &SkipCombo;
- if( !defined $ret )
- {
- die "$@\n";
- }
- if( $ret )
- {
- # skip this combo!
- $compileFailed = 1;
- $numSkipped++;
- next;
- }
-
- $start = SampleTime();
-
- $g_usesPos = 0;
- $g_usesPosFlex = 0;
- $g_usesBoneWeights = 0;
- $g_usesBoneIndices = 0;
- $g_usesNormal = 0;
- $g_usesNormalFlex = 0;
- $g_usesColor = 0;
- $g_usesSpecular = 0;
- $g_usesTexCoord0 = 0;
- $g_usesTexCoord1 = 0;
- $g_usesTexCoord2 = 0;
- $g_usesTexCoord3 = 0;
- $g_usesTangentS = 0;
- $g_usesTangentT = 0;
- $g_usesUserData = 0;
-
- undef @output;
-
- $g_TimingBlocks{"inner1"} += SampleTime() - $start;
-
- $eval_start_time = SampleTime();
- &OutputProgram();
- $eval_total_time += (SampleTime() - $eval_start_time);
-
- $start = SampleTime();
-
- # Strip out comments once so we don't have to do it in all the UsesRegister calls.
- @stripped = @output;
- map
- {
- $_ =~ s/;.*//gi;
- $_ =~ s/\/\/.*//gi;
- } @stripped;
- my $strippedStr = join( "", @stripped );
-
- $g_TimingBlocks{"inner2"} += SampleTime() - $start;
-
- $start = SampleTime();
-
- # Have to make another pass through after we know which v registers are used. . yuck.
- $g_usesPos = &UsesRegister( $vPos, $strippedStr );
- if( $g_x360 )
- {
- $g_usesPosFlex = &UsesRegister( $vPosFlex, $strippedStr );
- $g_usesNormalFlex = &UsesRegister( $vNormalFlex, $strippedStr );
- }
- $g_usesBoneWeights = &UsesRegister( $vBoneWeights, $strippedStr );
- $g_usesBoneIndices = &UsesRegister( $vBoneIndices, $strippedStr );
- $g_usesNormal = &UsesRegister( $vNormal, $strippedStr );
- $g_usesColor = &UsesRegister( $vColor, $strippedStr );
- $g_usesSpecular = &UsesRegister( $vSpecular, $strippedStr );
- $g_usesTexCoord0 = &UsesRegister( $vTexCoord0, $strippedStr );
- $g_usesTexCoord1 = &UsesRegister( $vTexCoord1, $strippedStr );
- $g_usesTexCoord2 = &UsesRegister( $vTexCoord2, $strippedStr );
- $g_usesTexCoord3 = &UsesRegister( $vTexCoord3, $strippedStr );
- $g_usesTangentS = &UsesRegister( $vTangentS, $strippedStr );
- $g_usesTangentT = &UsesRegister( $vTangentT, $strippedStr );
- $g_usesUserData = &UsesRegister( $vUserData, $strippedStr );
- undef @output;
-
- $g_TimingBlocks{"inner2"} += SampleTime() - $start;
-
- $eval_start_time = SampleTime();
- # Running OutputProgram generates $outfilename
- &OutputProgram();
- $eval_total_time += (SampleTime() - $eval_start_time);
-
- $start = SampleTime();
-
- &CheckUnfreedRegisters();
-
- for( $j = 0; $j < scalar( @output ); $j++ )
- {
- # remove whitespace from the beginning of each line.
- $output[$j] =~ s/^\s+//;
- # remove LINEINFO from empty lines.
- $output[$j] =~ s/^; LINEINFO.*//;
- }
-
- $g_TimingBlocks{"inner3"} += SampleTime() - $start;
- $start = SampleTime();
-
-
- $outfilename_base = $filename_base . "_" . $i;
-
- # $outfilename is the name of the file generated from executing the perl code
- # for this shader. This file is generated once per combo.
- # We will assemble this shader with vsa.exe.
- $outfilename = "$vshtmp\\" . $outfilename_base . ".tmp";
-
-# $outhdrfilename = "$vshtmp\\" . $outfilename_base . ".h";
-# unlink $outhdrfilename;
-
- open OUTPUT, ">$outfilename" || die;
- print OUTPUT @output;
- close OUTPUT;
-
- $g_TimingBlocks{"inner4"} += SampleTime() - $start;
- $start = SampleTime();
-
- local( $instructionCount ) = &CountInstructions( @output );
- $g_TimingBlocks{"inner5"} += SampleTime() - $start;
-
- local( $debug );
-
- $debug = 1;
-# for( $debug = 1; $debug >= 0; $debug-- )
- {
- # assemble the vertex shader
- unlink "shader$i.o";
- if( $g_x360 )
- {
- $vsa = "..\\..\\x360xdk\\bin\\win32\\vsa";
- }
- else
- {
- $vsa = "..\\..\\dx9sdk\\utilities\\vsa";
- }
- $vsadebug = "$vsa /nologo /Foshader$i.o $outfilename";
- $vsanodebug = "$vsa /nologo /Foshader$i.o $outfilename";
-
- $vsa_start_time = SampleTime();
-
- if( $debug )
- {
-# print $vsadebug . "\n";
- @vsaoutput = `$vsadebug 2>&1`;
-# print @vsaoutput;
- }
- else
- {
- @vsaoutput = `$vsanodebug 2>&1`;
- }
-
- $vsa_total_time += SampleTime() - $vsa_start_time;
-
- $start = SampleTime();
-
- &TranslateErrorMessages( @vsaoutput );
-
- $g_TimingBlocks{"inner6"} += SampleTime() - $start;
-
- push @finalheader, @hdr;
- }
-}
-
-
-$main_total_time = SampleTime() - $main_start_time;
-
-# stick info about the shaders at the end of the inc file.
-push @finalheader, "static PrecompiledShaderByteCode_t $filename_base" . "_vertex_shaders[] = {\n";
-for( $i = 0; $i < $numCombos; $i++ )
-{
- $outfilename_base = $filename_base . "_" . $i;
- push @finalheader, "{ $outfilename_base, sizeof( $outfilename_base ) },\n";
-}
-push @finalheader, "};\n";
-
-
-push @finalheader, "struct $filename_base" . "_VertexShader_t : public PrecompiledShader_t\n";
-push @finalheader, "{\n";
-push @finalheader, "\t$filename_base" . "_VertexShader_t()\n";
-push @finalheader, "\t{\n";
-push @finalheader, "\t\tm_nFlags = 0;\n";
-
-$flags = 0;
-#push @finalheader, "\t\tppVertexShaders = $filename_base" . "_vertex_shaders;\n";
-push @finalheader, "\t\tm_pByteCode = $filename_base" . "_vertex_shaders;\n";
-push @finalheader, "\t\tm_pName = \"$filename_base\";\n";
-push @finalheader, "\t\tm_nShaderCount = " . ( $maxNumBones + 1 ) * $totalFogCombos * $totalLightCombos . ";\n";
-push @finalheader, "\t\tm_nDynamicCombos = m_nShaderCount;\n";
-push @finalheader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n";
-push @finalheader, "\t}\n";
-push @finalheader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n";
-push @finalheader, "\t{\n";
-push @finalheader, "\t\treturn m_pByteCode[shaderID];\n";
-push @finalheader, "\t}\n";
-push @finalheader, "};\n";
-push @finalheader, "static $filename_base" . "_VertexShader_t $filename_base" . "_VertexShaderInstance;\n";
-
-# Write the final header file with the compiled vertex shader programs.
-$finalheadername = "$vshtmp\\" . $filename_base . ".inc";
-#print "writing $finalheadername\n";
-#open FINALHEADER, ">$finalheadername" || die;
-#print FINALHEADER @finalheader;
-#close FINALHEADER;
-
-&MakeDirHier( "shaders/vsh" );
-
-my $vcsName = "";
-if( $g_x360 )
-{
- $vcsName = $filename_base . ".360.vcs";
-}
-else
-{
- $vcsName = $filename_base . ".vcs";
-}
-open COMPILEDSHADER, ">shaders/vsh/$vcsName" || die;
-binmode( COMPILEDSHADER );
-
-#
-# Write out the part of the header that we know. . we'll write the rest after writing the object code.
-#
-
-# Pack arguments
-my $sInt = "i";
-my $uInt = "I";
-if ( $g_x360 )
-{
- # Change arguments to "big endian long"
- $sInt = "N";
- $uInt = "N";
-}
-
-my $undecoratedinput = join "", &ReadInputFileWithoutLineInfo( $filename );
-#print STDERR "undecoratedinput: $undecoratedinput\n";
-my $crc = crc32( $undecoratedinput );
-#print STDERR "crc for $filename: $crc\n";
-
-# version
-print COMPILEDSHADER pack $sInt, 4;
-# totalCombos
-print COMPILEDSHADER pack $sInt, $numCombos;
-# dynamic combos
-print COMPILEDSHADER pack $sInt, $numDynamicCombos;
-# flags
-print COMPILEDSHADER pack $uInt, $flags;
-# centroid mask
-print COMPILEDSHADER pack $uInt, 0;
-# reference size
-print COMPILEDSHADER pack $uInt, 0;
-# crc32 of the source code
-print COMPILEDSHADER pack $uInt, $crc;
-
-my $beginningOfDir = tell COMPILEDSHADER;
-
-# Write out a blank directionary. . we'll fill it in later.
-for( $i = 0; $i < $numCombos; $i++ )
-{
- # offset from beginning of file.
- print COMPILEDSHADER pack $sInt, 0;
- # size
- print COMPILEDSHADER pack $sInt, 0;
-}
-
-my $startByteCode = tell COMPILEDSHADER;
-my @byteCodeStart;
-my @byteCodeSize;
-
-# Write out the shader object code.
-for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
-{
- my $filename = "shader$shaderCombo\.o";
- my $filesize = (stat $filename)[7];
- $byteCodeStart[$shaderCombo] = tell COMPILEDSHADER;
- $byteCodeSize[$shaderCombo] = $filesize;
- open SHADERBYTECODE, "<$filename" || die;
- binmode SHADERBYTECODE;
- my $bin;
- my $numread = read SHADERBYTECODE, $bin, $filesize;
-# print "filename: $filename numread: $numread filesize: $filesize\n";
- close SHADERBYTECODE;
- unlink $filename;
-
- print COMPILEDSHADER $bin;
-}
-
-# Seek back to the directory and write it out.
-seek COMPILEDSHADER, $beginningOfDir, 0;
-for( $i = 0; $i < $numCombos; $i++ )
-{
- # offset from beginning of file.
- print COMPILEDSHADER pack $sInt, $byteCodeStart[$i];
- # size
- print COMPILEDSHADER pack $sInt, $byteCodeSize[$i];
-}
-
-close COMPILEDSHADER;
-
-$total_time = SampleTime() - $total_start_time;
-
-if ( $ShowTimers )
-{
- print "\n\n";
- print sprintf( "Main loop time : %0.4f sec, (%0.2f%%)\n", $main_total_time, 100*$main_total_time / $total_time );
- print sprintf( "Inner1 time : %0.4f sec, (%0.2f%%)\n", $inner1_total_time, 100*$inner1_total_time / $total_time );
- print sprintf( "VSA time : %0.4f sec, (%0.2f%%)\n", $vsa_total_time, 100*$vsa_total_time / $total_time );
- print sprintf( "eval() time : %0.4f sec, (%0.2f%%)\n", $eval_total_time, 100*$eval_total_time / $total_time );
- print sprintf( "UsesRegister time: %0.4f sec, (%0.2f%%)\n", $usesr_total_time, 100*$usesr_total_time / $total_time );
-
- foreach $key ( keys %g_TimingBlocks )
- {
- print sprintf( "$key time: %0.4f sec, (%0.2f%%)\n", $g_TimingBlocks{$key}, 100*$g_TimingBlocks{$key} / $total_time );
- }
-
- print sprintf( "Total time : %0.4f sec\n", $total_time );
-}
-
diff --git a/src/devtools/bin/vstdlib.dll b/src/devtools/bin/vstdlib.dll
new file mode 100644
index 00000000..319ef7e4
Binary files /dev/null and b/src/devtools/bin/vstdlib.dll differ
diff --git a/src/devtools/debug.xcconfig b/src/devtools/debug.xcconfig
deleted file mode 100644
index 4f63198a..00000000
--- a/src/devtools/debug.xcconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "base.xcconfig"
-GCC_OPTIMIZATION_LEVEL = 0
-OTHER_CFLAGS = $(derived) $(BASE_CFLAGS)
-
diff --git a/src/devtools/makefile_base_posix.mak b/src/devtools/makefile_base_posix.mak
deleted file mode 100644
index c76a1b1f..00000000
--- a/src/devtools/makefile_base_posix.mak
+++ /dev/null
@@ -1,472 +0,0 @@
-#
-# Base makefile for Linux.
-#
-# !!!!! Note to future editors !!!!!
-#
-# before you make changes, make sure you grok:
-# 1. the difference between =, :=, +=, and ?=
-# 2. how and when this base makefile gets included in the generated makefile(s)
-# ( see http://www.gnu.org/software/make/manual/make.html#Flavors )
-#
-# Command line prefixes:
-# - errors are ignored
-# @ command is not printed to stdout before being executed
-# + command is executed even if Make is invoked in "do not exec" mode
-
-OS := $(shell uname)
-HOSTNAME := $(shell hostname)
-
--include $(SRCROOT)/devtools/steam_def.mak
--include $(SRCROOT)/devtools/sourcesdk_def.mak
-
-# To build with clang, set the following in your environment:
-# CC = clang
-# CXX = clang++
-ifneq (,$(findstring clang,$(CXX)))
- CLANG_BUILD = 1
-endif
-
-ifeq ($(OS),Darwin)
- $(error This file should never be used for Mac - use base.xconfig)
-endif
-
-ifeq ($(CFG), release)
- # With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3.
- # There also was no speed difference running at 1280x1024. May 2012, mikesart.
- # tonyp: The size increase was likely caused by -finline-functions and -fipa-cp-clone getting switched on with -O3.
- # -fno-omit-frame-pointer: need this for stack traces with perf.
- OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer -ftree-vectorize
- ifeq ($(CLANG_BUILD),1)
- # These aren't supported wit Clang 3.5. Need to remove when we update that.
- OptimizerLevel_CompilerSpecific += -fpredictive-commoning -funswitch-loops
- else
- OptimizerLevel_CompilerSpecific += -fpredictive-commoning -funswitch-loops
- endif
-else
- OptimizerLevel_CompilerSpecific = -O0
- #-O1 -finline-functions
-endif
-
-# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags"
-ARCH_FLAGS =
-BUILDING_MULTI_ARCH = 0
-# Preserve cflags set in environment
-ENV_CFLAGS := $(CFLAGS)
-ENV_CXXFLAGS := $(CXXFLAGS)
-CPPFLAGS = $(DEFINES) $(addprefix -I, $(abspath $(INCLUDEDIRS) ))
-BASE_CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE
-CFLAGS = $(BASE_CFLAGS) $(ENV_CFLAGS)
-# In -std=gnu++0x mode we get lots of errors about "error: narrowing conversion". -fpermissive
-# turns these into warnings in gcc, and -Wno-c++11-narrowing suppresses them entirely in clang 3.1+.
-ifeq ($(CLANG_BUILD),1)
- CXXFLAGS = $(BASE_CFLAGS) -std=gnu++0x -Wno-c++11-narrowing -Wno-dangling-else $(ENV_CXXFLAGS)
-else
- CXXFLAGS = $(BASE_CFLAGS) -std=gnu++0x -fpermissive $(ENV_CXXFLAGS)
-endif
-DEFINES += -DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE
-
-## TODO: This cases build errors in cstrike/bin right now. Need to debug.
-# This causes all filesystem interfaces to default to their 64bit versions on
-# 32bit systems, which means we don't break on filesystems with inodes > 32bit.
-# DEFINES += -D_FILE_OFFSET_BITS=64
-
-LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel)
-GENDEP_CXXFLAGS = -MMD -MP -MF $(@:.o=.P)
-MAP_FLAGS =
-Srv_GAMEOUTPUTFILE =
-COPY_DLL_TO_SRV = 0
-
-# We should always specify -Wl,--build-id, as documented at:
-# http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId
-LDFLAGS += -Wl,--build-id
-
-#
-# If we should be running in a chroot, check to see if we are. If not, then prefix everything with the
-# required chroot
-#
-ifdef MAKE_CHROOT
- export STEAM_RUNTIME_PATH := /usr
- ifneq ("$(SCHROOT_CHROOT_NAME)", "$(CHROOT_NAME)")
- $(info '$(SCHROOT_CHROOT_NAME)' is not '$(CHROOT_NAME)')
- $(error This makefile should be run from within a chroot. 'schroot --chroot $(CHROOT_NAME) -- $(MAKE) $(MAKEFLAGS)')
- endif
- GCC_VER = -4.8
- P4BIN = $(SRCROOT)/devtools/bin/linux/p4
- CRYPTOPPDIR=ubuntu12_32_gcc48
-else ifeq ($(USE_VALVE_BINDIR),1)
- # Using /valve/bin directory.
- export STEAM_RUNTIME_PATH ?= /valve
- GCC_VER = -4.6
- P4BIN = p4
- CRYPTOPPDIR=linux32
-else
- # Not using chroot, use old steam-runtime. (gcc 4.6.3)
- export STEAM_RUNTIME_PATH ?= /valve/steam-runtime
- GCC_VER =
- P4BIN = p4
- CRYPTOPPDIR=ubuntu12_32
-endif
-
-ifeq ($(TARGET_PLATFORM),linux64)
- MARCH_TARGET = core2
-else
- MARCH_TARGET = pentium4
-endif
-
-ifeq ($(USE_VALVE_BINDIR),1)
- # On dedicated servers, some plugins depend on global variable symbols in addition to functions.
- # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2.
- STRIP_FLAGS =
-else
- # Linux desktop client (or client/dedicated server in chroot).
- STRIP_FLAGS = -x
-endif
-
-ifeq ($(CLANG_BUILD),1)
- # Clang does not support -mfpmath=sse because it uses whatever
- # instruction set extensions are available by default.
- SSE_GEN_FLAGS = -msse2
-else
- SSE_GEN_FLAGS = -msse2 -mfpmath=sse
-endif
-
-CCACHE := $(SRCROOT)/devtools/bin/linux/ccache
-
-ifeq ($(origin AR), default)
- AR = $(STEAM_RUNTIME_PATH)/bin/ar crs
-endif
-ifeq ($(origin CC), default)
- CC = $(CCACHE) $(STEAM_RUNTIME_PATH)/bin/gcc$(GCC_VER)
-endif
-ifeq ($(origin CXX), default)
- CXX = $(CCACHE) $(STEAM_RUNTIME_PATH)/bin/g++$(GCC_VER)
-endif
-
-# Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to
-# a ccache quirk. Could also upgrade ccache.
-# http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html
-ifeq ($(CLANG_BUILD),1)
- CC := $(CCACHE) $(CC) -Qunused-arguments -fcolor-diagnostics
- CXX := $(CCACHE) $(CXX) -Qunused-arguments -fcolor-diagnostics
-endif
-LINK ?= $(CC)
-
-ifeq ($(STEAM_BRANCH),1)
- WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof
-else
- WARN_FLAGS = -Wall -Wno-invalid-offsetof -Wno-multichar -Wno-overloaded-virtual
- WARN_FLAGS += -Wno-write-strings
- WARN_FLAGS += -Wno-unused-variable
- WARN_FLAGS += -Wno-unused-but-set-variable
- WARN_FLAGS += -Wno-unused-function
-endif
-
-ifeq ($(CLANG_BUILD),1)
- # Clang specific flags
-else ifeq ($(GCC_VER),-4.8)
- WARN_FLAGS += -Wno-unused-local-typedefs
- WARN_FLAGS += -Wno-unused-result
- WARN_FLAGS += -Wno-narrowing
- # WARN_FLAGS += -Wno-unused-function
-endif
-
-WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers
-WARN_FLAGS += -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type
-WARN_FLAGS += -fdiagnostics-show-option -Wformat -Wformat-security
-
-ifeq ($(TARGET_PLATFORM),linux64)
- # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2)
- ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2
- LD_SO = ld-linux-x86_64.so.2
- LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a)
- LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a)
-else
- # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse
- ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS)
- LD_SO = ld-linux.so.2
- LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so)
- LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so)
- LDFLAGS += -m32
-endif
-
-GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh
-ifeq ($(CFG),release)
- STRIP ?= strip $(STRIP_FLAGS) -S
-# CFLAGS += -ffunction-sections -fdata-sections
-# LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections
-else
- STRIP ?= true
-endif
-VSIGN ?= true
-
-ifeq ($(SOURCE_SDK), 1)
- Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so)
- COPY_DLL_TO_SRV := 1
-endif
-
-LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map
-
-SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined
-
-_WRAP := -Xlinker --wrap=
-PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \
- $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \
- $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \
- $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \
- $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath
-
-LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group
-LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread
-
-LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group
-LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt
-
-#
-# Profile-directed optimizations.
-# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%!
-#
-# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are.
-# PROFILE_LINKER_FLAG=-fprofile-arcs
-# PROFILE_COMPILER_FLAG=-fprofile-arcs
-#
-# Then, comment the above flags out again and rebuild with this flag uncommented:
-# PROFILE_COMPILER_FLAG=-fprofile-use
-#
-
-#############################################################################
-# The compiler command lne for each src code file to compile
-#############################################################################
-
-OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG)
-CPP_TO_OBJ = $(CPPFILES:.cpp=.o)
-CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o)
-CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o)
-MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o)
-C_TO_OBJ = $(MM_TO_OBJ:.c=.o)
-OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ)))
-
-ifeq ($(MAKE_VERBOSE),1)
- QUIET_PREFIX =
- QUIET_ECHO_POSTFIX =
-else
- QUIET_PREFIX = @
- QUIET_ECHO_POSTFIX = > /dev/null
-endif
-
-ifeq ($(MAKE_CC_VERBOSE),1)
-CC += -v
-endif
-
-ifeq ($(CONFTYPE),lib)
- LIB_File = $(OUTPUTFILE)
-endif
-
-ifeq ($(CONFTYPE),dll)
- SO_File = $(OUTPUTFILE)
-endif
-
-ifeq ($(CONFTYPE),exe)
- EXE_File = $(OUTPUTFILE)
-endif
-
-# we generate dependencies as a side-effect of compilation now
-GEN_DEP_FILE=
-
-PRE_COMPILE_FILE =
-
-POST_COMPILE_FILE =
-
-ifeq ($(BUILDING_MULTI_ARCH),1)
- SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS))
- COMPILE_FILE = \
- $(QUIET_PREFIX) \
- echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\
- mkdir -p $(OBJ_DIR) && \
- $(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \
- $(CXX) $(CXXFLAGS) -o $@ -c $<
-else
- COMPILE_FILE = \
- $(QUIET_PREFIX) \
- echo "---- $(lastword $(subst /, ,$<)) ----";\
- mkdir -p $(OBJ_DIR) && \
- $(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $<
-endif
-
-ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined"
- P4_EDIT_START = chmod -R +w
- P4_EDIT_END = || true
- P4_REVERT_START = true
- P4_REVERT_END =
-else
- ifndef P4_EDIT_CHANGELIST
- # You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default
- # setting is best, but here is an alternate example:
- # export P4_EDIT_CHANGELIST_CMD="echo 1424335"
- # ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed.
- P4_EDIT_CHANGELIST_CMD ?= $(P4BIN) changes -c `$(P4BIN) client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1
- P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD))
- endif
- ifeq ($(P4_EDIT_CHANGELIST),)
- # If we haven't found a changelist to check out to then create one. The name must match the one from a few
- # lines above or else a new changelist will be created each time.
- # Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be
- # interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which
- # confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command.
- P4_EDIT_CHANGELIST = $(shell echo -e "Change: new\nDescription: POSIX Auto Checkout" | $(P4BIN) change -i | cut -f 2 -d ' ')
- endif
-
- P4_EDIT_START := for f in
- P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | $(P4BIN) -x - edit -c $(P4_EDIT_CHANGELIST); else $(P4BIN) edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX)
- P4_REVERT_START := for f in
- P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | $(P4BIN) -x - revert; else $(P4BIN) revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX)
-endif
-
-ifeq ($(CONFTYPE),dll)
-all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE)
- @echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX)
-else
-all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE)
- @echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX)
-endif
-
-.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile
-
-
-rebuild :
- $(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove
- $(MAKE) -f $(firstword $(MAKEFILE_LIST))
-
-
-# Use the relink target to force to relink the project.
-relink: RemoveOutputFile all
-
-RemoveOutputFile:
- rm -f $(OUTPUTFILE)
-
-
-# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file.
-# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that.
-SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o
- @echo ""
-
-RemoveSingleFile:
- $(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o
-
-clean:
-ifneq "$(OBJ_DIR)" ""
- $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)"
- $(QUIET_PREFIX) rm -rf $(OBJ_DIR)
-endif
-ifneq "$(OUTPUTFILE)" ""
- $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \
- echo "$(P4BIN) revert $(OUTPUTFILE)"; \
- $(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \
- fi;
-endif
-ifneq "$(OTHER_DEPENDENCIES)" ""
- $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)"
- $(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES)
-endif
-ifneq "$(GAMEOUTPUTFILE)" ""
- $(QUIET_PREFIX) echo "$(P4BIN) revert $(GAMEOUTPUTFILE)"
- $(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END)
-endif
-
-
-# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the
-# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave
-# us with archive files that have extra unused symbols, and also potentially cause compilation errors
-# when you rename a file and have many duplicate symbols.
-cleanandremove:
-ifneq "$(OBJ_DIR)" ""
- $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)"
- $(QUIET_PREFIX) -rm -rf $(OBJ_DIR)
-endif
-ifneq "$(OUTPUTFILE)" ""
- $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \
- echo "$(P4BIN) edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \
- $(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \
- fi;
- $(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT);
-endif
-ifneq "$(OTHER_DEPENDENCIES)" ""
- $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)"
- $(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES)
-endif
-ifneq "$(GAMEOUTPUTFILE)" ""
- $(QUIET_PREFIX) echo "$(P4BIN) edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)"
- $(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END)
- $(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE)
-endif
-
-
-# This just deletes the final targets so it'll do a relink next time we build.
-cleantargets:
- $(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE)
-
-
-$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS)
- $(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END);
- $(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES);
-
-SO_GameOutputFile = $(GAMEOUTPUTFILE)
-
-# Remove the target before installing a file over it; this prevents existing
-# instances of the game from crashing due to the overwrite.
-$(SO_GameOutputFile): $(SO_File)
- $(QUIET_PREFIX) \
- $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \
- echo "----" $(QUIET_ECHO_POSTFIX);\
- echo "---- COPYING TO $@ [$(CFG)] ----";\
- echo "----" $(QUIET_ECHO_POSTFIX);
- $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END);
- $(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null;
- $(QUIET_PREFIX) rm -f $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);
- $(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);
- $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END);
- $(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE);
- $(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE);
- $(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE);
- $(QUIET_PREFIX) if [ "$(COPY_DLL_TO_SRV)" = "1" ]; then\
- echo "----" $(QUIET_ECHO_POSTFIX);\
- echo "---- COPYING TO $(Srv_GAMEOUTPUTFILE) ----";\
- echo "----" $(QUIET_ECHO_POSTFIX);\
- cp -v $(GAMEOUTPUTFILE) $(Srv_GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);\
- cp -v $(GAMEOUTPUTFILE)$(SYM_EXT) $(Srv_GAMEOUTPUTFILE)$(SYM_EXT) $(QUIET_ECHO_POSTFIX);\
- fi;
- $(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\
- echo "----" $(QUIET_ECHO_POSTFIX);\
- echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\
- echo "----" $(QUIET_ECHO_POSTFIX);\
- $(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \
- mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \
- cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \
- fi;
-
-
-$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES)
- $(QUIET_PREFIX) \
- echo "----" $(QUIET_ECHO_POSTFIX);\
- echo "---- LINKING $@ [$(CFG)] ----";\
- echo "----" $(QUIET_ECHO_POSTFIX);\
- \
- $(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB);
- $(VSIGN) -signvalve $(OUTPUTFILE);
-
-
-$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES)
- $(QUIET_PREFIX) \
- echo "----" $(QUIET_ECHO_POSTFIX);\
- echo "---- LINKING EXE $@ [$(CFG)] ----";\
- echo "----" $(QUIET_ECHO_POSTFIX);\
- \
- $(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\
- $(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE);
- $(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END);
- $(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE);
- $(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE);
- $(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE);
-
-
-tags:
- etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx
diff --git a/src/devtools/release.xcconfig b/src/devtools/release.xcconfig
deleted file mode 100644
index d9258588..00000000
--- a/src/devtools/release.xcconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "base.xcconfig"
-
-GCC_OPTIMIZATION_LEVEL = 2
-OTHER_CFLAGS = $(derived) $(BASE_CFLAGS) -ftree-vectorize -funswitch-loops
diff --git a/src/devtools/sourcesdk_def.mak b/src/devtools/sourcesdk_def.mak
deleted file mode 100644
index fc561ad7..00000000
--- a/src/devtools/sourcesdk_def.mak
+++ /dev/null
@@ -1,3 +0,0 @@
-#defines these macros so that we skip VSIGN and P4 steps in the SDK
-SOURCE_SDK=1
-VALVE_NO_AUTO_P4=1
diff --git a/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll b/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll
deleted file mode 100644
index 001b2446..00000000
Binary files a/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll and /dev/null differ
diff --git a/src/dx9sdk/utilities/dx_proxy.dll b/src/dx9sdk/utilities/dx_proxy.dll
deleted file mode 100644
index 725a6273..00000000
Binary files a/src/dx9sdk/utilities/dx_proxy.dll and /dev/null differ
diff --git a/src/engine/audio/public/sound.h b/src/engine/audio/public/sound.h
new file mode 100644
index 00000000..5de9e99c
--- /dev/null
+++ b/src/engine/audio/public/sound.h
@@ -0,0 +1,112 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: client sound i/o functions
+//
+//===========================================================================//
+#ifndef SOUND_H
+#define SOUND_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "basetypes.h"
+#include "datamap.h"
+#include "mathlib/vector.h"
+#include "mathlib/mathlib.h"
+#include "tier1/strtools.h"
+#include "soundflags.h"
+#include "utlvector.h"
+#include "engine/SndInfo.h"
+#include "soundstartparams.h"
+
+#define MAX_SFX 2048
+
+#define AUDIOSOURCE_CACHE_ROOTDIR "maps/soundcache"
+
+class CSfxTable;
+enum soundlevel_t;
+struct SoundInfo_t;
+struct AudioState_t;
+class IFileList;
+
+void S_Init (void);
+void S_Shutdown (void);
+bool S_IsInitted();
+
+void S_StopAllSounds(bool clear);
+void S_Update( const AudioState_t *pAudioState );
+void S_ExtraUpdate (void);
+void S_ClearBuffer (void);
+void S_BlockSound (void);
+void S_UnblockSound (void);
+void S_UpdateWindowFocus( bool bWindowHasFocus );
+float S_GetMasterVolume( void );
+void S_SoundFade( float percent, float holdtime, float intime, float outtime );
+void S_OnLoadScreen(bool value);
+void S_EnableThreadedMixing( bool bEnable );
+void S_EnableMusic( bool bEnable );
+
+struct audio_device_description_t;
+void S_GetAudioDeviceList( CUtlVector &audioList );
+
+int S_StartSound( StartSoundParams_t& params );
+void S_StopSound ( int entnum, int entchannel );
+enum clocksync_index_t
+{
+ CLOCK_SYNC_CLIENT = 0,
+ CLOCK_SYNC_SERVER,
+ NUM_CLOCK_SYNCS
+};
+
+extern float S_ComputeDelayForSoundtime( float soundtime, clocksync_index_t syncIndex );
+
+void S_StopSoundByGuid( int guid );
+float S_SoundDurationByGuid( int guid );
+int S_GetGuidForLastSoundEmitted();
+bool S_IsSoundStillPlaying( int guid );
+void S_GetActiveSounds( CUtlVector< SndInfo_t >& sndlist );
+void S_SetVolumeByGuid( int guid, float fvol );
+float S_GetElapsedTimeByGuid( int guid );
+bool S_IsLoopingSoundByGuid( int guid );
+void S_ReloadSound( const char *pSample );
+float S_GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList );
+
+CSfxTable *S_DummySfx( const char *name );
+CSfxTable *S_PrecacheSound (const char *sample );
+void S_PrefetchSound( char const *name, bool bPlayOnce );
+void S_MarkUISound( CSfxTable *pSfx );
+void S_ReloadFilesInList( IFileList *pFilesToReload );
+
+vec_t S_GetNominalClipDist();
+
+extern bool TestSoundChar(const char *pch, char c);
+extern char *PSkipSoundChars(const char *pch);
+
+#include "soundchars.h"
+
+// for recording movies
+void SND_MovieStart( void );
+void SND_MovieEnd( void );
+void SND_MovieUpdateChannelCount( void );
+
+//-------------------------------------
+
+int S_GetCurrentStaticSounds( SoundInfo_t *pResult, int nSizeResult, int entchannel );
+
+//-----------------------------------------------------------------------------
+
+float S_GetGainFromSoundLevel( soundlevel_t soundlevel, vec_t dist );
+
+struct musicsave_t
+{
+ DECLARE_SIMPLE_DATADESC();
+
+ char songname[ 128 ];
+ int sampleposition;
+ short master_volume;
+};
+
+void S_GetCurrentlyPlayingMusic( CUtlVector< musicsave_t >& list );
+void S_RestartSong( const musicsave_t *song );
+
+#endif // SOUND_H
diff --git a/src/fgdlib/fgdlib.vpc b/src/fgdlib/fgdlib.vpc
index a44915d9..9475de7a 100644
--- a/src/fgdlib/fgdlib.vpc
+++ b/src/fgdlib/fgdlib.vpc
@@ -15,7 +15,7 @@ $Configuration
}
}
-$Project "Fgdlib"
+$Project "fgdlib"
{
$Folder "Source Files"
{
diff --git a/src/fgdlib/gdvar.cpp b/src/fgdlib/gdvar.cpp
index fe8df025..80c0d863 100644
--- a/src/fgdlib/gdvar.cpp
+++ b/src/fgdlib/gdvar.cpp
@@ -51,6 +51,8 @@ static TypeMap_t TypeMap[] =
{ ivVecLine, "vecline", STRING },
{ ivPointEntityClass, "pointentityclass", STRING },
{ ivNodeDest, "node_dest", INTEGER },
+ { ivScript, "script", STRING },
+ { ivScriptList, "scriptlist", STRING },
{ ivInstanceFile, "instance_file", STRING },
{ ivAngleNegativePitch, "angle_negative_pitch", STRING },
{ ivInstanceVariable, "instance_variable", STRING },
@@ -274,6 +276,20 @@ BOOL GDinputvariable::InitFromTokens(TokenReader& tr)
ttype = tr.PeekTokenType(szToken,sizeof(szToken));
}
+ //
+ // Check for the "report" specifier.
+ //
+ if ((ttype == IDENT) && IsToken(szToken, "report"))
+ {
+ tr.NextToken(szToken, sizeof(szToken));
+ m_bReportable = true;
+
+ //
+ // Look ahead at the next token.
+ //
+ ttype = tr.PeekTokenType(szToken,sizeof(szToken));
+ }
+
//
// Check for the ':' indicating a long name.
//
@@ -408,6 +424,42 @@ BOOL GDinputvariable::InitFromTokens(TokenReader& tr)
GDError(tr, "no %s specified", m_eType == ivFlags ? "flags" : "choices");
return(FALSE);
}
+
+ // For boolean values, we construct it as if it were a choices dialog
+ if ( m_eType == ivBoolean )
+ {
+ m_eType = ivChoices;
+
+ GDIVITEM ivi;
+
+ // Yes
+ strncpy( ivi.szValue, "1", MAX_STRING );
+ strncpy( ivi.szCaption, "Yes", MAX_STRING );
+ m_Items.AddToTail(ivi);
+
+ // No
+ strncpy( ivi.szValue, "0", MAX_STRING );
+ strncpy( ivi.szCaption, "No", MAX_STRING );
+ m_Items.AddToTail(ivi);
+
+ // Clean up string usages!
+ if ( stricmp( m_szDefault, "no" ) == 0 )
+ {
+ strncpy( m_szDefault, "0", MAX_STRING );
+ }
+ else if ( stricmp( m_szDefault, "yes" ) == 0 )
+ {
+ strncpy( m_szDefault, "1", MAX_STRING );
+ }
+
+ // Sanity check it!
+ if ( strcmp( m_szDefault, "0" ) && strcmp( m_szDefault, "1" ) )
+ {
+ GDError(tr, "boolean type specified with nonsensical default value: %s", m_szDefault );
+ return(FALSE);
+ }
+ }
+
return(TRUE);
}
@@ -669,7 +721,7 @@ void GDinputvariable::ToKeyValue(MDkeyvalue *pkv)
}
else if (eStoreAs == INTEGER)
{
- itoa(m_nValue, pkv->szValue, 10);
+ Q_snprintf(pkv->szValue, sizeof(pkv->szValue), "%d", m_nValue);
}
}
diff --git a/src/fgdlib/inputoutput.cpp b/src/fgdlib/inputoutput.cpp
index ee2b6033..ea810c13 100644
--- a/src/fgdlib/inputoutput.cpp
+++ b/src/fgdlib/inputoutput.cpp
@@ -36,6 +36,7 @@ static TypeMap_t TypeMap[] =
{ iotEHandle, "target_destination" },
{ iotColor, "color255" },
{ iotEHandle, "ehandle" }, // for backwards compatibility
+ { iotScript, "script" },
};
diff --git a/src/game/client/EffectsClient.cpp b/src/game/client/EffectsClient.cpp
index f7b6ffff..d06c36eb 100644
--- a/src/game/client/EffectsClient.cpp
+++ b/src/game/client/EffectsClient.cpp
@@ -165,15 +165,15 @@ void CEffectsClient::MuzzleFlash( const Vector &vecOrigin, const QAngle &vecAngl
switch( iType )
{
case MUZZLEFLASH_TYPE_DEFAULT:
- FX_MuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
+ FX_MuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE );
break;
case MUZZLEFLASH_TYPE_GUNSHIP:
- FX_GunshipMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
+ FX_GunshipMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE );
break;
case MUZZLEFLASH_TYPE_STRIDER:
- FX_StriderMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
+ FX_StriderMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE );
break;
default:
diff --git a/src/game/client/NextBot/C_NextBot.cpp b/src/game/client/NextBot/C_NextBot.cpp
new file mode 100644
index 00000000..355b62fa
--- /dev/null
+++ b/src/game/client/NextBot/C_NextBot.cpp
@@ -0,0 +1,246 @@
+// C_NextBot.cpp
+// Client-side implementation of Next generation bot system
+// Author: Michael Booth, April 2005
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#include "cbase.h"
+#include "C_NextBot.h"
+#include "debugoverlay_shared.h"
+#include
+#include "viewrender.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#undef NextBot
+
+ConVar NextBotShadowDist( "nb_shadow_dist", "400" );
+
+//-----------------------------------------------------------------------------
+IMPLEMENT_CLIENTCLASS_DT( C_NextBotCombatCharacter, DT_NextBot, NextBotCombatCharacter )
+END_RECV_TABLE()
+
+
+//-----------------------------------------------------------------------------
+C_NextBotCombatCharacter::C_NextBotCombatCharacter()
+{
+ // Left4Dead have surfaces too steep for IK to work properly
+ m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
+
+ m_shadowType = SHADOWS_SIMPLE;
+ m_forcedShadowType = SHADOWS_NONE;
+ m_bForceShadowType = false;
+
+ TheClientNextBots().Register( this );
+ UseClientSideAnimation();
+}
+
+
+//-----------------------------------------------------------------------------
+C_NextBotCombatCharacter::~C_NextBotCombatCharacter()
+{
+ TheClientNextBots().UnRegister( this );
+}
+
+
+//-----------------------------------------------------------------------------
+void C_NextBotCombatCharacter::Spawn( void )
+{
+ BaseClass::Spawn();
+}
+
+
+//-----------------------------------------------------------------------------
+void C_NextBotCombatCharacter::UpdateClientSideAnimation()
+{
+ if (IsDormant())
+ {
+ return;
+ }
+
+ BaseClass::UpdateClientSideAnimation();
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+void C_NextBotCombatCharacter::UpdateShadowLOD( void )
+{
+ ShadowType_t oldShadowType = m_shadowType;
+
+ if ( m_bForceShadowType )
+ {
+ m_shadowType = m_forcedShadowType;
+ }
+ else
+ {
+#ifdef NEED_SPLITSCREEN_INTEGRATION
+ FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
+ {
+ C_BasePlayer *pl = C_BasePlayer::GetLocalPlayer(hh);
+ if ( pl )
+ {
+ Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer(hh)->GetAbsOrigin();
+#else
+ {
+ if ( C_BasePlayer::GetLocalPlayer() )
+ {
+ Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer()->GetAbsOrigin();
+#endif
+ if ( delta.IsLengthLessThan( NextBotShadowDist.GetFloat() ) )
+ {
+ m_shadowType = SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
+ }
+ else
+ {
+ m_shadowType = SHADOWS_SIMPLE;
+ }
+ }
+ else
+ {
+ m_shadowType = SHADOWS_SIMPLE;
+ }
+ }
+ }
+
+ if ( oldShadowType != m_shadowType )
+ {
+ DestroyShadow();
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+ShadowType_t C_NextBotCombatCharacter::ShadowCastType( void )
+{
+ if ( !IsVisible() )
+ return SHADOWS_NONE;
+
+ if ( m_shadowTimer.IsElapsed() )
+ {
+ m_shadowTimer.Start( 0.15f );
+ UpdateShadowLOD();
+ }
+
+ return m_shadowType;
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+bool C_NextBotCombatCharacter::GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const
+{
+ if ( pForcedShadowType )
+ {
+ *pForcedShadowType = m_forcedShadowType;
+ }
+ return m_bForceShadowType;
+}
+
+//--------------------------------------------------------------------------------------------------------
+/**
+ * Singleton accessor.
+ * By returning a reference, we guarantee construction of the
+ * instance before its first use.
+ */
+C_NextBotManager &TheClientNextBots( void )
+{
+ static C_NextBotManager manager;
+ return manager;
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+C_NextBotManager::C_NextBotManager( void )
+{
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+C_NextBotManager::~C_NextBotManager()
+{
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+void C_NextBotManager::Register( C_NextBotCombatCharacter *bot )
+{
+ m_botList.AddToTail( bot );
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+void C_NextBotManager::UnRegister( C_NextBotCombatCharacter *bot )
+{
+ m_botList.FindAndRemove( bot );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool C_NextBotManager::SetupInFrustumData( void )
+{
+#ifdef ENABLE_AFTER_INTEGRATION
+ // Done already this frame.
+ if ( IsInFrustumDataValid() )
+ return true;
+
+ // Can we use the view data yet?
+ if ( !FrustumCache()->IsValid() )
+ return false;
+
+ // Get the number of active bots.
+ int nBotCount = m_botList.Count();
+
+ // Reset.
+ for ( int iBot = 0; iBot < nBotCount; ++iBot )
+ {
+ // Get the current bot.
+ C_NextBotCombatCharacter *pBot = m_botList[iBot];
+ if ( !pBot )
+ continue;
+
+ pBot->InitFrustumData();
+ }
+
+ FOR_EACH_VALID_SPLITSCREEN_PLAYER( iSlot )
+ {
+ ACTIVE_SPLITSCREEN_PLAYER_GUARD( iSlot );
+ // Get the active local player.
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ continue;
+
+ for ( int iBot = 0; iBot < nBotCount; ++iBot )
+ {
+ // Get the current bot.
+ C_NextBotCombatCharacter *pBot = m_botList[iBot];
+ if ( !pBot )
+ continue;
+
+ // Are we in the view frustum?
+ Vector vecMin, vecMax;
+ pBot->CollisionProp()->WorldSpaceAABB( &vecMin, &vecMax );
+ bool bInFrustum = !FrustumCache()->m_Frustums[iSlot].CullBox( vecMin, vecMax );
+
+ if ( bInFrustum )
+ {
+ Vector vecSegment;
+ VectorSubtract( pBot->GetAbsOrigin(), pPlayer->GetAbsOrigin(), vecSegment );
+ float flDistance = vecSegment.LengthSqr();
+ if ( flDistance < pBot->GetInFrustumDistanceSqr() )
+ {
+ pBot->SetInFrustumDistanceSqr( flDistance );
+ }
+
+ pBot->SetInFrustum( true );
+ }
+ }
+ }
+
+ // Mark as setup this frame.
+ m_nInFrustumFrame = gpGlobals->framecount;
+#endif
+
+ return true;
+}
+
+//--------------------------------------------------------------------------------------------------------
diff --git a/src/game/client/NextBot/C_NextBot.h b/src/game/client/NextBot/C_NextBot.h
new file mode 100644
index 00000000..c26d7b9b
--- /dev/null
+++ b/src/game/client/NextBot/C_NextBot.h
@@ -0,0 +1,134 @@
+// C_NextBot.h
+// Next generation bot system
+// Author: Michael Booth, April 2005
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#ifndef _C_NEXT_BOT_H_
+#define _C_NEXT_BOT_H_
+
+#include "c_ai_basenpc.h"
+
+//----------------------------------------------------------------------------------------------------------------
+/**
+* The interface holding IBody information
+*/
+class IBodyClient
+{
+public:
+ enum ActivityType
+ {
+ MOTION_CONTROLLED_XY = 0x0001, // XY position and orientation of the bot is driven by the animation.
+ MOTION_CONTROLLED_Z = 0x0002, // Z position of the bot is driven by the animation.
+ ACTIVITY_UNINTERRUPTIBLE= 0x0004, // activity can't be changed until animation finishes
+ ACTIVITY_TRANSITORY = 0x0008, // a short animation that takes over from the underlying animation momentarily, resuming it upon completion
+ ENTINDEX_PLAYBACK_RATE = 0x0010, // played back at different rates based on entindex
+ };
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+/**
+ * The client-side implementation of the NextBot
+ */
+class C_NextBotCombatCharacter : public C_BaseCombatCharacter
+{
+public:
+ DECLARE_CLASS( C_NextBotCombatCharacter, C_BaseCombatCharacter );
+ DECLARE_CLIENTCLASS();
+
+ C_NextBotCombatCharacter();
+ virtual ~C_NextBotCombatCharacter();
+
+public:
+ virtual void Spawn( void );
+ virtual void UpdateClientSideAnimation( void );
+ virtual ShadowType_t ShadowCastType( void );
+ virtual bool IsNextBot() { return true; }
+ void ForceShadowCastType( bool bForce, ShadowType_t forcedShadowType = SHADOWS_NONE ) { m_bForceShadowType = bForce; m_forcedShadowType = forcedShadowType; }
+ bool GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const;
+
+ // Local In View Data.
+ void InitFrustumData( void ) { m_bInFrustum = false; m_flFrustumDistanceSqr = FLT_MAX; m_nInFrustumFrame = gpGlobals->framecount; }
+ bool IsInFrustumValid( void ) { return ( m_nInFrustumFrame == gpGlobals->framecount ); }
+ void SetInFrustum( bool bInFrustum ) { m_bInFrustum = bInFrustum; }
+ bool IsInFrustum( void ) { return m_bInFrustum; }
+ void SetInFrustumDistanceSqr( float flDistance ) { m_flFrustumDistanceSqr = flDistance; }
+ float GetInFrustumDistanceSqr( void ) { return m_flFrustumDistanceSqr; }
+
+private:
+ ShadowType_t m_shadowType; // Are we LOD'd to simple shadows?
+ CountdownTimer m_shadowTimer; // Timer to throttle checks for shadow LOD
+ ShadowType_t m_forcedShadowType;
+ bool m_bForceShadowType;
+ void UpdateShadowLOD( void );
+
+ // Local In View Data.
+ int m_nInFrustumFrame;
+ bool m_bInFrustum;
+ float m_flFrustumDistanceSqr;
+
+private:
+ C_NextBotCombatCharacter( const C_NextBotCombatCharacter & ); // not defined, not accessible
+};
+
+//--------------------------------------------------------------------------------------------------------
+/**
+ * The C_NextBotManager manager
+ */
+class C_NextBotManager
+{
+public:
+ C_NextBotManager( void );
+ ~C_NextBotManager();
+
+ /**
+ * Execute functor for each NextBot in the system.
+ * If a functor returns false, stop iteration early
+ * and return false.
+ */
+ template < typename Functor >
+ bool ForEachCombatCharacter( Functor &func )
+ {
+ for( int i=0; i < m_botList.Count(); ++i )
+ {
+ C_NextBotCombatCharacter *character = m_botList[i];
+ if ( character->IsPlayer() )
+ {
+ continue;
+ }
+
+ if ( character->IsDormant() )
+ {
+ continue;
+ }
+
+ if ( !func( character ) )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ int GetActiveCount() { return m_botList.Count(); }
+
+ bool SetupInFrustumData( void );
+ bool IsInFrustumDataValid( void ) { return ( m_nInFrustumFrame == gpGlobals->framecount ); }
+
+private:
+ friend class C_NextBotCombatCharacter;
+
+ void Register( C_NextBotCombatCharacter *bot );
+ void UnRegister( C_NextBotCombatCharacter *bot );
+
+ CUtlVector< C_NextBotCombatCharacter * > m_botList; ///< list of all active NextBots
+
+ int m_nInFrustumFrame;
+};
+
+// singleton accessor
+extern C_NextBotManager &TheClientNextBots( void );
+
+
+#endif // _C_NEXT_BOT_H_
diff --git a/src/game/client/ScreenSpaceEffects.h b/src/game/client/ScreenSpaceEffects.h
index a93fa229..140e0ddf 100644
--- a/src/game/client/ScreenSpaceEffects.h
+++ b/src/game/client/ScreenSpaceEffects.h
@@ -85,4 +85,4 @@ public:
-#endif
\ No newline at end of file
+#endif
diff --git a/src/game/client/TeamBitmapImage.h b/src/game/client/TeamBitmapImage.h
index 5039698d..dcf7bdd1 100644
--- a/src/game/client/TeamBitmapImage.h
+++ b/src/game/client/TeamBitmapImage.h
@@ -77,4 +77,4 @@ bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pBitmapImage );
-#endif // TEAMBITMAPIMAGE_H
\ No newline at end of file
+#endif // TEAMBITMAPIMAGE_H
diff --git a/src/game/client/ViewConeImage.h b/src/game/client/ViewConeImage.h
index cfa2ea15..21cc6c14 100644
--- a/src/game/client/ViewConeImage.h
+++ b/src/game/client/ViewConeImage.h
@@ -53,4 +53,4 @@ bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage );
-#endif // VIEWCONEIMAGE_H
\ No newline at end of file
+#endif // VIEWCONEIMAGE_H
diff --git a/src/game/client/abuse_report.cpp b/src/game/client/abuse_report.cpp
new file mode 100644
index 00000000..285a633b
--- /dev/null
+++ b/src/game/client/abuse_report.cpp
@@ -0,0 +1,720 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generic in-game abuse reporting
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "abuse_report.h"
+#include "abuse_report_ui.h"
+#include "filesystem.h"
+#include "imageutils.h"
+#include "econ/confirm_dialog.h"
+#include "econ/econ_notifications.h"
+
+inline bool IsLoggedOnToSteam()
+{
+ return steamapicontext != NULL && steamapicontext->SteamUser() != NULL && steamapicontext->SteamUser()->BLoggedOn();
+}
+
+const char CAbuseReportManager::k_rchScreenShotFilenameBase[] = "abuse_report";
+const char CAbuseReportManager::k_rchScreenShotFilename[] = "screenshots\\abuse_report.jpg";
+
+//-----------------------------------------------------------------------------
+class CEconNotification_AbuseReportReady : public CEconNotification
+{
+public:
+ CEconNotification_AbuseReportReady() : CEconNotification()
+ {
+ m_bHasTriggered = false;
+ m_bShowInGame = false;
+ }
+
+ ~CEconNotification_AbuseReportReady()
+ {
+ //if ( !m_bHasTriggered )
+ //{
+ // ReallyTrigger();
+ //}
+ }
+
+ virtual void MarkForDeletion()
+ {
+ m_bHasTriggered = true;
+
+ CEconNotification::MarkForDeletion();
+ }
+
+ virtual bool BShowInGameElements() const { return m_bShowInGame; }
+ virtual EType NotificationType() { return eType_Trigger; }
+ virtual void Trigger()
+ {
+ ReallyTrigger();
+ MarkForDeletion();
+ }
+
+ virtual const char *GetUnlocalizedHelpText()
+ {
+ return "#AbuseReport_Notification_Help";
+ }
+
+ static bool IsNotificationType( CEconNotification *pNotification ) { return dynamic_cast< CEconNotification_AbuseReportReady *>( pNotification ) != NULL; }
+ static bool IsInGameNotificationType( CEconNotification *pNotification )
+ {
+ CEconNotification_AbuseReportReady *n = dynamic_cast< CEconNotification_AbuseReportReady *>( pNotification );
+ return n != NULL && n->BShowInGameElements();
+ }
+
+ bool m_bShowInGame;
+
+private:
+
+ void ReallyTrigger()
+ {
+ Assert( !m_bHasTriggered );
+ m_bHasTriggered = true;
+ engine->ClientCmd_Unrestricted( "abuse_report_submit" );
+ }
+
+ bool m_bHasTriggered;
+};
+
+AbuseIncidentData_t::AbuseIncidentData_t()
+{
+ m_nScreenShotWaitFrames = 5;
+}
+
+AbuseIncidentData_t::~AbuseIncidentData_t()
+{
+}
+
+bool AbuseIncidentData_t::Poll()
+{
+ bool bReady = true;
+
+ // Poll player data
+ for ( int i = 0 ; i < m_vecPlayers.Count() ; ++i )
+ {
+
+ // Make sure sure Steam knows we want the Avatar
+ PlayerData_t *p = &m_vecPlayers[i];
+ if ( p->m_iSteamAvatarIndex < 0 )
+ {
+ if ( steamapicontext && steamapicontext->SteamUser() )
+ {
+
+ p->m_iSteamAvatarIndex = steamapicontext->SteamFriends()->GetLargeFriendAvatar( p->m_steamID );
+ if ( p->m_iSteamAvatarIndex < 0 )
+ {
+ bReady = false;
+ }
+ }
+ else
+ {
+ p->m_iSteamAvatarIndex = 0;
+ }
+ }
+ }
+
+ // Screenshot ready?
+ if ( !m_bitmapScreenshot.IsValid() && m_nScreenShotWaitFrames > 0 )
+ {
+ --m_nScreenShotWaitFrames;
+
+ // Just load the whole file into a memory buffer
+ char szFullPath[ MAX_PATH ] = "";
+ if ( !g_pFullFileSystem->RelativePathToFullPath( CAbuseReportManager::k_rchScreenShotFilename, NULL, szFullPath, ARRAYSIZE(szFullPath) ) )
+ {
+ Assert( false ); // ???
+ }
+
+ // Load it
+
+ if ( g_pFullFileSystem->FileExists( szFullPath ) )
+ {
+
+ // Load the screenshot into a local buffer
+ if ( !g_pFullFileSystem->ReadFile( CAbuseReportManager::k_rchScreenShotFilename, NULL, m_bufScreenshotFileData ) )
+ {
+ Warning( "Failed to read back %s\n", CAbuseReportManager::k_rchScreenShotFilename );
+ m_nScreenShotWaitFrames = 0;
+ }
+ else
+ {
+ ConversionErrorType nErrorCode = ImgUtl_LoadBitmap( szFullPath, m_bitmapScreenshot );
+ if ( nErrorCode != CE_SUCCESS )
+ {
+ Warning( "Abuse report screenshot %s failed to load with error code %d\n", CAbuseReportManager::k_rchScreenShotFilename, nErrorCode );
+ Assert( nErrorCode == CE_SUCCESS );
+ m_nScreenShotWaitFrames = 0;
+ }
+ else
+ {
+ // !KLUDGE! Resize to power of two dimensions, since VGUI doesn't like odd sizes
+ ImgUtl_ResizeBitmap( m_bitmapScreenshot, 1024, 1024, &m_bitmapScreenshot );
+ }
+ }
+ g_pFullFileSystem->RemoveFile( CAbuseReportManager::k_rchScreenShotFilename );
+ }
+ }
+
+ return bReady;
+}
+
+CAbuseReportManager *g_AbuseReportMgr;
+
+CAbuseReportManager::CAbuseReportManager()
+{
+ m_pIncidentData = NULL;
+ m_bTestReport = false;
+ m_eIncidentDataStatus = k_EIncidentDataStatus_None;
+ m_bReportUIPending = false;
+
+ // We're the singleton --- set global pointer
+ Assert( g_AbuseReportMgr == NULL );
+ g_AbuseReportMgr = this;
+ m_timeLastReportReadyNotification = 0.0;
+ m_adrCurrentServer.Clear();
+}
+
+CAbuseReportManager::~CAbuseReportManager()
+{
+ Assert( m_pIncidentData == NULL );
+}
+
+char const *CAbuseReportManager::Name()
+{
+ return "AbuseRepotManager";
+}
+
+bool CAbuseReportManager::Init()
+{
+ // Clean out any temporary files
+ Assert( m_pIncidentData == NULL );
+ DestroyIncidentData();
+
+ ListenForGameEvent( "teamplay_round_win" );
+ ListenForGameEvent( "tf_game_over" );
+ ListenForGameEvent( "player_death" );
+ ListenForGameEvent( "server_spawn" );
+
+ return true;
+}
+
+void CAbuseReportManager::LevelShutdownPreEntity()
+{
+
+ // Don't keep the dialog open across a level transition. Don't discard their
+ // report data, but let's kill the dialog
+ if ( g_AbuseReportDlg.Get() != NULL )
+ {
+ Warning( "Abuse report dialog open during level shutdown. Closing it.\n" );
+ g_AbuseReportDlg.Get()->Close();
+ }
+
+ // And clear the 'pending' flag
+ m_bReportUIPending = false;
+}
+
+void CAbuseReportManager::FireGameEvent( IGameEvent *event )
+{
+ //C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+
+ const char *eventname = event->GetName();
+
+ if ( !eventname || !eventname[0] )
+ return;
+
+ if (
+ !Q_strcmp( "teamplay_round_win", eventname )
+ || !Q_strcmp( "tf_game_over", eventname )
+ ) {
+ // Periodically remind them that they have a report ready to file
+ CheckCreateReportReadyNotification( 60.0 * 5.0, true, 10.0f );
+ }
+ else if ( !Q_strcmp( "player_death", eventname ) )
+ {
+ // In some maps, the round just never ends.
+ // So make sure we do remind them every now and then about this.
+ // Just not too often
+ CheckCreateReportReadyNotification( 60.0 * 20.0, true, 5.0f );
+ }
+ else if ( !Q_strcmp( "server_spawn", eventname ) )
+ {
+ m_adrCurrentServer.Clear();
+ m_adrCurrentServer.SetFromString( event->GetString( "address", "" ), false );
+ m_adrCurrentServer.SetPort( event->GetInt( "port", 0 ) );
+
+ m_steamIDCurrentServer = CSteamID();
+ if ( steamapicontext && steamapicontext->SteamUser() && GetUniverse() != k_EUniverseInvalid )
+ {
+ m_steamIDCurrentServer.SetFromString( event->GetString( "steamid", "" ), GetUniverse() );
+ }
+ }
+}
+
+void CAbuseReportManager::Shutdown()
+{
+ // Close the dialog, if any
+ LevelShutdownPreEntity();
+
+ DestroyIncidentData();
+
+ // Clear global pointer
+ Assert( g_AbuseReportMgr == this );
+ if ( g_AbuseReportMgr == this )
+ {
+ g_AbuseReportMgr = NULL;
+ }
+}
+
+void CAbuseReportManager::Update( float frametime )
+{
+
+ // if a dialog is already displayed, make sure we don't try to activate another
+ if ( g_AbuseReportDlg.Get() != NULL )
+ {
+ m_bReportUIPending = false;
+ }
+
+ // Poll report data, if any
+ if ( m_pIncidentData != NULL )
+ {
+ if ( m_eIncidentDataStatus == k_EIncidentDataStatus_Preparing )
+ {
+ if ( m_pIncidentData->Poll() )
+ {
+ m_eIncidentDataStatus = k_EIncidentDataStatus_Ready;
+ CheckCreateReportReadyNotification( 1.0f, true, 7.0f );
+ }
+ }
+ else
+ {
+ Assert( m_eIncidentDataStatus == k_EIncidentDataStatus_Ready );
+ }
+
+ if ( m_eIncidentDataStatus == k_EIncidentDataStatus_Ready && m_bReportUIPending )
+ {
+ m_bReportUIPending = false;
+ ActivateSubmitReportUI();
+ }
+ }
+ else
+ {
+ m_bReportUIPending = false;
+ }
+
+ // Re-create notification constantly in the menu.
+ // While in game, we will only popup notifications
+ // periodically at round end or player death
+ CheckCreateReportReadyNotification( 10.0, false, 999.0f );
+}
+
+void CAbuseReportManager::SubmitReportUIRequested()
+{
+ if ( g_AbuseReportDlg.Get() != NULL )
+ {
+ Assert( g_AbuseReportDlg.Get() == NULL );
+ return;
+ }
+
+ // If no report data already, then create some
+ if ( m_pIncidentData == NULL )
+ {
+ QueueReport();
+ if ( m_pIncidentData == NULL )
+ {
+ // Failed
+ return;
+ }
+ }
+
+ // Set flag to bring up the reporting UI at earliest opportunity,
+ // once all data has been fetched asynchronously
+ m_bReportUIPending = true;
+}
+
+bool CAbuseReportManager::CreateAndPopulateIncident()
+{
+ Assert( m_pIncidentData == NULL );
+
+ // by default, just create the base class version
+ m_pIncidentData = new AbuseIncidentData_t;
+
+ // And populate it
+ return PopulateIncident();
+}
+
+bool CAbuseReportManager::PopulateIncident()
+{
+ if ( m_pIncidentData == NULL )
+ {
+ Assert( m_pIncidentData );
+ return false;
+ }
+
+ // Queue a screenshot
+ CUtlString cmd;
+ cmd.Format( "__screenshot_internal \"%s\"", k_rchScreenShotFilenameBase );
+ engine->ClientCmd_Unrestricted( cmd );
+
+ // Set status as preparing
+ m_eIncidentDataStatus = k_EIncidentDataStatus_Preparing;
+
+ m_pIncidentData->m_bCanReportGameServer = false;
+
+ m_pIncidentData->m_adrGameServer.Clear();
+ if (
+ m_adrCurrentServer.IsValid()
+ && !m_adrCurrentServer.IsLocalhost()
+ && m_steamIDCurrentServer.IsValid()
+ && ( !m_adrCurrentServer.IsReservedAdr() || m_steamIDCurrentServer.GetEUniverse() != k_EUniversePublic )
+ )
+ {
+ m_pIncidentData->m_adrGameServer = m_adrCurrentServer;
+ m_pIncidentData->m_steamIDGameServer = m_steamIDCurrentServer;
+ m_pIncidentData->m_bCanReportGameServer = true;
+ }
+
+ m_pIncidentData->m_matWorldToClip = engine->WorldToScreenMatrix();
+
+ // Add in players
+ for (int i = 1 ; i <= gpGlobals->maxClients ; ++i )
+ {
+ CBasePlayer *player = UTIL_PlayerByIndex( i );
+
+ #ifndef _DEBUG
+ // Skip local players
+ if ( player != NULL && player->IsLocalPlayer() )
+ {
+ continue;
+ }
+ #endif
+
+ // Get player info from the engine. This works even if they haven't spawned yet.
+ player_info_t pi;
+ if ( !engine->GetPlayerInfo( i, &pi ) )
+ {
+ continue;
+ }
+
+ if ( pi.fakeplayer )
+ {
+ continue;
+ }
+ if ( pi.friendsID == 0 )
+ {
+ continue;
+ }
+ CSteamID steamID( pi.friendsID, 1, GetUniverse(), k_EAccountTypeIndividual );
+ if ( !steamID.IsValid() )
+ {
+ Assert( steamID.IsValid() );
+ continue;
+ }
+
+ int arrayIndex = m_pIncidentData->m_vecPlayers.AddToTail();
+ AbuseIncidentData_t::PlayerData_t *p = &m_pIncidentData->m_vecPlayers[ arrayIndex ];
+
+ p->m_iClientIndex = i;
+ p->m_steamID = steamID;
+ p->m_sPersona = pi.name;
+ p->m_bHasEntity = false;
+ p->m_bRenderBoundsValid = false;
+ p->m_screenBoundsMin.x = p->m_screenBoundsMin.y = 1.0f;
+ p->m_screenBoundsMax.x = p->m_screenBoundsMax.y = 0.0f;
+
+ if ( player==NULL )
+ {
+ continue;
+ }
+
+ p->m_bHasEntity = true;
+ player->GetRenderBounds( p->m_vecRenderBoundsMin, p->m_vecRenderBoundsMax );
+ p->m_matModelToWorld.CopyFrom3x4( player->RenderableToWorldTransform() );
+ MatrixMultiply( m_pIncidentData->m_matWorldToClip, p->m_matModelToWorld, p->m_matModelToClip );
+
+ // Gather up screen extents
+ p->m_bRenderBoundsValid = false;
+ for ( int j = 0 ; j < 8 ; ++j )
+ {
+
+ // Get corner point in model space
+ Vector4D modelCorner(
+ ( j & 1 ) ? p->m_vecRenderBoundsMax.x : p->m_vecRenderBoundsMin.x,
+ ( j & 2 ) ? p->m_vecRenderBoundsMax.y : p->m_vecRenderBoundsMin.y,
+ ( j & 4 ) ? p->m_vecRenderBoundsMax.z : p->m_vecRenderBoundsMin.z,
+ 1.0f
+ );
+
+ // Transform to clip space
+ Vector4D clipCorner;
+ Vector4DMultiply( p->m_matModelToClip, modelCorner, clipCorner );
+
+ //Msg( "%6.3f, %6.3f, %6.3f, %6.3f\n", clipCorner[0], clipCorner[1], clipCorner[2], clipCorner[3] );
+
+ // If all points behind near clip plane, don't try to
+ // figure out screen space bounds
+ if ( clipCorner[3] > .1f )
+ {
+ p->m_bRenderBoundsValid = true;
+ }
+
+ // Push w forward to "near clip plane"
+ float w = MAX( clipCorner[3], .1f );
+
+ // Divide by w to project, and convert normalized device coordinates
+ // where the view volume is (-1...1), to normalized screen coords, where
+ // they are from 0...1
+ float x = ( clipCorner[0] / w + 1.0f ) / 2.0f;
+ float y = ( -clipCorner[1] / w + 1.0f ) / 2.0f;
+ p->m_screenBoundsMin.x = MIN( p->m_screenBoundsMin.x, x );
+ p->m_screenBoundsMax.x = MAX( p->m_screenBoundsMax.x, x );
+ p->m_screenBoundsMin.y = MIN( p->m_screenBoundsMin.y, y );
+ p->m_screenBoundsMax.y = MAX( p->m_screenBoundsMax.y, y );
+ }
+
+ // Clip projected rect to the screen
+ if ( p->m_bRenderBoundsValid )
+ {
+ p->m_screenBoundsMin.x = MAX( p->m_screenBoundsMin.x, 0.0f );
+ p->m_screenBoundsMax.x = MIN( p->m_screenBoundsMax.x, 1.0f );
+ p->m_screenBoundsMin.y = MAX( p->m_screenBoundsMin.y, 0.0f );
+ p->m_screenBoundsMax.y = MIN( p->m_screenBoundsMax.y, 1.0f );
+
+ p->m_bRenderBoundsValid =
+ p->m_screenBoundsMin.x + .01f < p->m_screenBoundsMax.x
+ && p->m_screenBoundsMin.y + .01f < p->m_screenBoundsMax.y;
+ }
+
+ // Sanity check that we agree on what their steam ID is!
+ if ( player->GetSteamID( &steamID ) )
+ {
+ Assert( p->m_steamID == steamID );
+ }
+ }
+
+ // Test harness: add in a handful of fake players
+ #ifdef _DEBUG
+ if ( m_bTestReport )
+ {
+ int arrayIndex = m_pIncidentData->m_vecPlayers.AddToTail();
+ AbuseIncidentData_t::PlayerData_t *p = &m_pIncidentData->m_vecPlayers[ arrayIndex ];
+
+ p->m_iClientIndex = -1;
+ p->m_sPersona = "Lippencott";
+ p->m_steamID.SetFromUint64( 148618791998333672 );
+
+ arrayIndex = m_pIncidentData->m_vecPlayers.AddToTail();
+ p = &m_pIncidentData->m_vecPlayers[ arrayIndex ];
+
+ p->m_iClientIndex = -1;
+ p->m_sPersona = "EricS";
+ p->m_steamID.SetFromUint64( 148618791998195668 );
+
+ arrayIndex = m_pIncidentData->m_vecPlayers.AddToTail();
+ p = &m_pIncidentData->m_vecPlayers[ arrayIndex ];
+
+ p->m_iClientIndex = -1;
+ p->m_sPersona = "Sarenya";
+ p->m_steamID.SetFromUint64( 148618791998429832 );
+
+ arrayIndex = m_pIncidentData->m_vecPlayers.AddToTail();
+ p = &m_pIncidentData->m_vecPlayers[ arrayIndex ];
+
+
+ p->m_iClientIndex = -1;
+ p->m_sPersona = "fletch";
+ p->m_steamID.SetFromUint64( 148618791998436114 );
+ {
+ AbuseIncidentData_t::PlayerImage_t img;
+ img.m_eType = AbuseIncidentData_t::k_PlayerImageType_UGC;
+ img.m_hUGCHandle = 6978249415967519;
+ p->m_vecImages.AddToTail( img );
+ }
+
+ if ( !m_pIncidentData->m_bCanReportGameServer)
+ {
+ m_pIncidentData->m_adrGameServer.SetFromString( "123.45.67.89:27015", false );
+ m_pIncidentData->m_steamIDGameServer = CSteamID( 12345, 0, GetUniverse(), k_EAccountTypeAnonGameServer );
+ m_pIncidentData->m_bCanReportGameServer = true;
+ }
+ }
+ #endif
+
+ // Make sure there is at least one other person we could file a report against!
+ if ( m_pIncidentData->m_vecPlayers.Count() < 1 )
+ {
+ Warning( "No players to accuse of abuse, cannot file report\n" );
+ return false;
+ }
+
+ return true;
+}
+
+void CAbuseReportManager::DestroyIncidentData()
+{
+ if ( m_pIncidentData != NULL )
+ {
+ delete m_pIncidentData;
+ m_pIncidentData = NULL;
+ }
+ m_eIncidentDataStatus = k_EIncidentDataStatus_None;
+
+ // Get rid of any existing screenshot file, both locally
+ // and in the cloud. We don't want this to count against
+ // our quota
+ if ( steamapicontext && steamapicontext->SteamRemoteStorage() && steamapicontext->SteamRemoteStorage()->FileExists( k_rchScreenShotFilename ) )
+ {
+ steamapicontext->SteamRemoteStorage()->FileDelete( k_rchScreenShotFilename );
+ }
+
+ if ( g_pFullFileSystem->FileExists( k_rchScreenShotFilename ) ) // !KLUDGE! To prevent warning if the file doesn't exist!
+ {
+ g_pFullFileSystem->RemoveFile( k_rchScreenShotFilename );
+ }
+
+ m_timeLastReportReadyNotification = 0.0;
+
+ // Make sure we don't have any notifications queued
+ NotificationQueue_Remove( &CEconNotification_AbuseReportReady::IsNotificationType );
+}
+
+void CAbuseReportManager::QueueReport()
+{
+ // Dialog is already active?
+ if ( g_AbuseReportDlg.Get() != NULL )
+ {
+ Warning( "Cannot capture another incident report. Submission dialog is active.\n" );
+ return;
+ }
+
+ // Destroy any existing data
+ DestroyIncidentData();
+
+ // Make sure we're logged on to Steam
+ if ( !IsLoggedOnToSteam() )
+ {
+ g_AbuseReportMgr->ShowNoSteamErrorMessage();
+ return;
+ }
+
+ if ( CreateAndPopulateIncident() )
+ {
+ Msg( "Captured data for abuse report.\n");
+ }
+ else
+ {
+ Warning( "Failed to captured data for abuse report.\n");
+ DestroyIncidentData();
+ }
+}
+
+void CAbuseReportManager::ShowNoSteamErrorMessage()
+{
+ ShowMessageBox( "#AbuseReport_NoSteamTitle", "#AbuseReport_NoSteamMessage", "#GameUI_OK" );
+}
+
+void CAbuseReportManager::CheckCreateReportReadyNotification( float flMinSecondsSinceLastNotification, bool bInGame, float flLifetime )
+{
+ // We have to have some data ready
+ if ( m_pIncidentData == NULL || m_eIncidentDataStatus != k_EIncidentDataStatus_Ready )
+ {
+ return;
+ }
+
+ // Don't pester them if they are already trying to do something about it
+ if ( g_AbuseReportDlg.Get() != NULL || m_bReportUIPending )
+ {
+ return;
+ }
+
+ // Already notified them too recently?
+ if ( m_timeLastReportReadyNotification != 0.0 && Plat_FloatTime() < m_timeLastReportReadyNotification + flMinSecondsSinceLastNotification )
+ {
+ return;
+ }
+
+ // Already a notification in the queue?
+ if ( bInGame )
+ {
+ if ( NotificationQueue_Count( &CEconNotification_AbuseReportReady::IsInGameNotificationType ) > 0 )
+ {
+ return;
+ }
+ }
+ else
+ {
+ if ( NotificationQueue_Count( &CEconNotification_AbuseReportReady::IsNotificationType ) > 0 )
+ {
+ return;
+ }
+ }
+
+ CreateReportReadyNotification( bInGame, flLifetime );
+}
+
+void CAbuseReportManager::CreateReportReadyNotification( bool bInGame, float flLifetime )
+{
+ NotificationQueue_Remove( &CEconNotification_AbuseReportReady::IsNotificationType );
+ CEconNotification_AbuseReportReady *pNotification = new CEconNotification_AbuseReportReady();
+ pNotification->SetText( "AbuseReport_Notification" );
+ pNotification->SetLifetime( flLifetime );
+ pNotification->m_bShowInGame = bInGame;
+ NotificationQueue_Add( pNotification );
+
+ m_timeLastReportReadyNotification = Plat_FloatTime();
+}
+
+CON_COMMAND_F( abuse_report_queue, "Capture data for abuse report and queue for submission. Use abose_report_submit to activate UI to submit the report", FCVAR_DONTRECORD )
+{
+ if ( !g_AbuseReportMgr )
+ {
+ Warning( "abuse_report_queue: No abuse report manager, cannot create report.\n" );
+ return;
+ }
+
+ g_AbuseReportMgr->QueueReport();
+}
+
+CON_COMMAND_F( abuse_report_submit, "Activate UI to submit queued report. Use abuse_report_queue to capture data for the report the report", FCVAR_DONTRECORD )
+{
+ if ( !g_AbuseReportMgr )
+ {
+ Warning( "abuse_report_submit: No abuse report manager, cannot submit report.\n" );
+ return;
+ }
+
+ // Make sure we're logged on to Steam
+ if ( !IsLoggedOnToSteam() )
+ {
+ g_AbuseReportMgr->ShowNoSteamErrorMessage();
+ return;
+ }
+
+ if ( g_AbuseReportDlg.Get() != NULL )
+ {
+ // Dialog is already active
+ return;
+ }
+ g_AbuseReportMgr->SubmitReportUIRequested();
+}
+
+// Test harness
+#ifdef _DEBUG
+
+CON_COMMAND_F( abuse_report_test, "Make a test abuse incident and activate UI", FCVAR_DONTRECORD )
+{
+ if ( !g_AbuseReportMgr )
+ {
+ Assert( g_AbuseReportMgr );
+ return;
+ }
+ g_AbuseReportMgr->m_bTestReport = true;
+ g_AbuseReportMgr->QueueReport();
+ g_AbuseReportMgr->m_bTestReport = false;
+ engine->ClientCmd_Unrestricted( "abuse_report_submit" );
+}
+
+#endif
diff --git a/src/game/client/abuse_report.h b/src/game/client/abuse_report.h
new file mode 100644
index 00000000..43410864
--- /dev/null
+++ b/src/game/client/abuse_report.h
@@ -0,0 +1,274 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generic in-game abuse reporting
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef ABUSE_REPORT_H
+#define ABUSE_REPORT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include
+#include
+#include
+#include
+
+/// Different content types that can be reported as abusive.
+///
+/// WARNING: These enum values MUST MATCH the values in Steam's
+/// ECommunityContentType!
+enum EAbuseReportContentType
+{
+ k_EAbuseReportContentNoSelection = -1, // dummy ilegal value: the user has not made a selection
+ k_EAbuseReportContentUnspecified = 0, // we use this to mean "other"
+ //k_EAbuseReportContentAll = 1, // reset all community content
+ k_EAbuseReportContentAvatarImage = 2, // clear avatar image
+ //k_EAbuseReportContentProfileText = 3, // reset profile text
+ //k_EAbuseReportContentWebLinks = 4, // delete web links
+ //k_EAbuseReportContentAnnouncement = 5,
+ //k_EAbuseReportContentEventText = 6,
+ //k_EAbuseReportContentCustomCSS = 7,
+ //k_EAbuseReportContentProfileURL = 8, // delete community URL ID
+ k_EAbuseReportContentComments = 9, // just comments this guy has written
+ k_EAbuseReportContentPersonaName = 10, // persona name
+ //k_EAbuseReportContentScreenshot = 11, // screenshot
+ //k_EAbuseReportContentVideo = 12, // videos
+ k_EAbuseReportContentCheating = 13, // cheating
+ k_EAbuseReportContentUGCImage = 14, // Image stored in UGC --- the report is accusing the image of being offensive
+ k_EAbuseReportContentActorUGCImage = 15, // Abuse report actor has uploaded a UGC image to server as supporting documentation of their claim
+};
+
+
+/// Types of reasons why a violation report was issued
+///
+/// WARNING: These enum values MUST MATCH the values in Steam's
+/// EAbuseReportType!
+enum EAbuseReportType
+{
+ k_EAbuseReportTypeNoSelection = -1, // dummy ilegal value: the user has not made a selection
+ k_EAbuseReportTypeUnspecified = 0,
+ k_EAbuseReportTypeInappropriate = 1, // just not ok to post
+ k_EAbuseReportTypeProhibited = 2, // prohibited by EULA or general law
+ k_EAbuseReportTypeSpamming = 3, // excessive spamming
+ k_EAbuseReportTypeAdvertisement = 4, // unwanted advertisement
+ //k_EAbuseReportTypeExploit = 5, // content data attempts to exploit code issue
+ k_EAbuseReportTypeSpoofing = 6, // user/group is impersonating an official contact
+ k_EAbuseReportTypeLanguage = 7, // bad language
+ k_EAbuseReportTypeAdultContent = 8, // any kind of adult material, references etc
+ k_EAbuseReportTypeHarassment = 9, // harassment, discrimination, racism etc
+ k_EAbuseReportTypeCheating = 10, // cheating
+};
+
+/// Container class that has everything we need to know in order to file
+/// an abuse report, which is significantly more than the data we actually
+/// include in a particular abuse report. It's everything we save off at the
+/// time the user initiates the abuse reporting mechanism. Games can derive
+/// their own report types and put game-specific data in here.
+struct AbuseIncidentData_t
+{
+ AbuseIncidentData_t();
+ virtual ~AbuseIncidentData_t();
+
+ enum EPlayerImageType
+ {
+ k_PlayerImageType_UGC,
+ k_PlayerImageType_Spray,
+ };
+
+ /// A custom image of the player's that could be considered offensive
+ struct PlayerImage_t
+ {
+
+ /// What kind of image is it?
+ EPlayerImageType m_eType;
+
+ /// For UGC images, what's the handle?
+ uint64 m_hUGCHandle;
+ };
+
+ /// Info we remember for one player.
+ struct PlayerData_t
+ {
+ PlayerData_t()
+ {
+ m_iClientIndex = -1;
+ m_iSteamAvatarIndex = -1;
+ }
+
+ /// The client index. (See UTIL_PlayerByIndex). Note that this
+ /// index is really only valid at the time the incident is captured.
+ /// Because players can leave after the incident is captured.
+ int m_iClientIndex;
+
+ /// The name they were going by at the time
+ CUtlString m_sPersona;
+
+ /// Their steam ID. This is essential so we can file
+ /// an abuse report!
+ CSteamID m_steamID;
+
+ /// Index of steam friends icon for their avatar.
+ /// 0 if they don't have one!
+ int m_iSteamAvatarIndex;
+
+ /// Do we have an entity for this player? They might not have spawned,
+ /// or might be outside our PVS, etc.
+ bool m_bHasEntity;
+
+ /// Model transform for the player's render stuff
+ VMatrix m_matModelToWorld;
+
+ /// Model->clip matrix for the player's render stuff
+ VMatrix m_matModelToClip;
+
+ /// True if the render bounds are approximately correct, false if not
+ bool m_bRenderBoundsValid;
+
+ /// Bounds (in model space) of the player's renderable stuff
+ Vector m_vecRenderBoundsMin, m_vecRenderBoundsMax;
+
+ /// Bounds (in normalized screen space coords 0...1) of the player's
+ /// renderable stuff
+ Vector2D m_screenBoundsMin, m_screenBoundsMax;
+
+ /// List of his images
+ CUtlVector m_vecImages;
+ };
+
+ /// List of base player data. You got more data per player in your derived
+ /// incident type? Store it in a parallel array.
+ CUtlVector m_vecPlayers;
+
+ /// Camera world -> clip matrix.
+ VMatrix m_matWorldToClip;
+
+ /// Screenshot
+ Bitmap_t m_bitmapScreenshot;
+
+ // Screenshot file data
+ CUtlBuffer m_bufScreenshotFileData;
+
+ /// Number of frames we're willing to wait for the engine to write out a screenshot.
+ /// Zero if we already failed
+ int m_nScreenShotWaitFrames;
+
+ /// Is it possible to report the game server itself for abuse?
+ bool m_bCanReportGameServer;
+
+ /// What Game Server/IP are we on? Will be an invalid address if we don't know
+ netadr_t m_adrGameServer;
+
+ /// Steam ID of the game server / IP we are on
+ CSteamID m_steamIDGameServer;
+
+ /// Poll report (some data may have to be fetched asynchronously),
+ /// return true if everything is ready
+ virtual bool Poll();
+};
+
+/// Generic abuse reporting panel. Your
+class CAbuseReportManager : public CBaseGameSystemPerFrame, public CGameEventListener
+{
+public:
+ CAbuseReportManager();
+ virtual ~CAbuseReportManager();
+
+ //
+ // CAutoGameSystemPerFrame overrides
+ //
+ virtual char const *Name();
+ virtual bool Init();
+ virtual void Shutdown();
+ virtual void LevelShutdownPreEntity();
+
+ //
+ // CGameEventListener overrides
+ //
+ virtual void FireGameEvent( IGameEvent *event );
+
+// CAutoGameSystemPerFrame defines different stuff depending on which DLL we're building
+#ifdef CLIENT_DLL
+
+ // Do our frame-time processing
+ virtual void Update( float frametime );
+
+#else
+ #error "Why is this being included?"
+#endif
+
+ /// Called when the console command is executed to capture data for a report
+ virtual void QueueReport();
+
+ /// Called when the console command is executed to submit data for a report
+ virtual void SubmitReportUIRequested();
+
+ /// Called to actually trigger the report UI, after all data is ready
+ virtual void ActivateSubmitReportUI() = 0;
+
+ /// Fetch the incident that's queued to be reported
+ AbuseIncidentData_t *GetIncidentData() const { return m_pIncidentData; }
+
+ /// Delete any current report incident. Also should clean
+ /// out any temporary files used by the incident system.
+ virtual void DestroyIncidentData();
+
+ /// Show a message box complaining about lack of steam
+ /// connection
+ virtual void ShowNoSteamErrorMessage();
+
+ /// Insert a a notification into the queue indicating that an unfiled report is ready
+ virtual void CreateReportReadyNotification( bool bInGame, float flLifetime );
+
+ /// Test harness. Set this to true, to generate fake data
+ bool m_bTestReport;
+
+ static const char k_rchScreenShotFilenameBase[];
+ static const char k_rchScreenShotFilename[];
+
+protected:
+
+ /// Your app will probably define its own abuse report types.
+ /// if so, you will need to override this function.
+ /// The base class just calls new to create an object, then calls
+ /// PopulateIncident()
+ virtual bool CreateAndPopulateIncident();
+
+ /// Fill in the details about the current incident. This just fills in the
+ /// base class data, and it should be called from CreateAndPopulateIncident
+ bool PopulateIncident();
+
+ /// Current incident that is pending to be reported or is being generated.
+ /// Might be NULL.
+ AbuseIncidentData_t *m_pIncidentData;
+
+ /// Status of incident data.
+ enum EIncidentDataStatus
+ {
+ k_EIncidentDataStatus_None,
+ k_EIncidentDataStatus_Preparing, // we shuld call Poll() until it's ready
+ k_EIncidentDataStatus_Ready, // it's ready
+ };
+ EIncidentDataStatus m_eIncidentDataStatus;
+
+ /// Do we want to show the report UI as soon as the report is ready?
+ bool m_bReportUIPending;
+
+ void CheckCreateReportReadyNotification( float flMinSecondsSinceLastNotification, bool bInGame, float flLifetime );
+
+ /// Time when we last pestered them about filing their report
+ double m_timeLastReportReadyNotification;
+
+ /// Address of the lasts server we connected to
+ netadr_t m_adrCurrentServer;
+ CSteamID m_steamIDCurrentServer;
+
+};
+
+/// Pointer to the app-specific instance. This pointer mght be NULL! Your
+/// app should define set this pointer if it uses the system
+extern CAbuseReportManager *g_AbuseReportMgr;
+
+#endif // ABUSE_REPORT_H
diff --git a/src/game/client/abuse_report_ui.cpp b/src/game/client/abuse_report_ui.cpp
new file mode 100644
index 00000000..0d1ab592
--- /dev/null
+++ b/src/game/client/abuse_report_ui.cpp
@@ -0,0 +1,949 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generic in-game abuse reporting
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "abuse_report_ui.h"
+#include "econ/econ_controls.h"
+#include "ienginevgui.h"
+#include "vgui/ISurface.h"
+#include
+#include
+#include
+#include "vgui_bitmappanel.h"
+#include "vgui_avatarimage.h"
+#include "gc_clientsystem.h"
+#include "econ/tool_items/tool_items.h"
+#include "econ/econ_gcmessages.h"
+#include "econ/confirm_dialog.h"
+#include "tool_items/custom_texture_cache.h"
+
+vgui::DHANDLE g_AbuseReportDlg;
+
+CAbuseReportDlg::CAbuseReportDlg( vgui::Panel *parent, AbuseIncidentData_t *pIncidentData )
+: EditablePanel( parent, "AbuseReportSubmitDialog" )
+, m_pSubmitButton( NULL )
+, m_pScreenShot( NULL )
+, m_pScreenShotAttachCheckButton( NULL )
+, m_pOffensiveImage( NULL )
+, m_pDescriptionTextEntry( NULL )
+, m_pPlayerLabel( NULL )
+, m_pPlayerRadio( NULL )
+, m_pGameServerRadio( NULL )
+, m_pPlayerCombo( NULL )
+, m_pAbuseContentLabel( NULL )
+, m_pAbuseContentCombo( NULL )
+, m_pAbuseTypeLabel( NULL )
+, m_pAbuseTypeCombo( NULL )
+, m_pScreenShotBitmap( NULL )
+, m_pAvatarImage( NULL )
+, m_pNoAvatarLabel( NULL )
+, m_pCustomTextureImagePanel( NULL )
+, m_pNoCustomTexturesLabel( NULL )
+, m_pCustomTextureNextButton( NULL )
+, m_pCustomTexturePrevButton( NULL )
+, m_iUserImageIndex( 0 )
+, m_pIncidentData( pIncidentData )
+{
+ vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
+ SetScheme(scheme);
+ SetProportional( true );
+ //m_pContainer = new vgui::EditablePanel( this, "Container" );
+
+ Assert( g_AbuseReportDlg.Get() == NULL );
+ g_AbuseReportDlg.Set( this );
+
+ engine->ExecuteClientCmd("gameui_preventescape");
+}
+
+CAbuseReportDlg::~CAbuseReportDlg()
+{
+ Assert( g_AbuseReportDlg.Get() == this );
+ if ( g_AbuseReportDlg.Get() == this )
+ {
+ engine->ExecuteClientCmd("gameui_allowescape");
+ g_AbuseReportDlg = NULL;
+ }
+}
+
+void CAbuseReportDlg::OnCommand( const char *command )
+{
+ if ( !Q_stricmp( command, "cancel" ) )
+ {
+ Close();
+ return;
+ }
+ if ( !Q_stricmp( command, "discard" ) )
+ {
+ Close();
+ g_AbuseReportMgr->DestroyIncidentData();
+ return;
+ }
+ if ( !Q_stricmp( command, "submit" ) )
+ {
+ OnSubmitReport();
+ return;
+ }
+ if ( !Q_stricmp( command, "nextcustomtexture" ) )
+ {
+ ++m_iUserImageIndex;
+ UpdateCustomTextures();
+ return;
+ }
+
+ if ( !Q_stricmp( command, "prevcustomtexture" ) )
+ {
+ --m_iUserImageIndex;
+ UpdateCustomTextures();
+ return;
+ }
+
+}
+
+void CAbuseReportDlg::MakeModal()
+{
+ TFModalStack()->PushModal( this );
+ MakePopup();
+ MoveToFront();
+ SetKeyBoardInputEnabled( true );
+ SetMouseInputEnabled( true );
+
+ // !KLUDGE! Initially set the dialog to be hidden, so we can take a screenshot!
+ SetEnabled( m_pIncidentData != NULL );
+ //SetVisible( m_pIncidentData != NULL );
+}
+
+void CAbuseReportDlg::Close()
+{
+ TFModalStack()->PopModal( this );
+ SetVisible( false );
+ MarkForDeletion();
+}
+
+const char *CAbuseReportDlg::GetResFilename()
+{
+ return "Resource/UI/AbuseReportSubmitDialog.res";
+ //return "Resource/UI/QuickplayDialog.res";
+}
+
+void CAbuseReportDlg::PerformLayout()
+{
+ BaseClass::PerformLayout();
+
+ // Center it, keeping requested size
+ int x, y, ww, wt, wide, tall;
+ vgui::surface()->GetWorkspaceBounds( x, y, ww, wt );
+ GetSize(wide, tall);
+ SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2));
+
+ // @todo setup
+}
+
+class CCustomTextureImagePanel : public vgui::Panel
+{
+public:
+ CCustomTextureImagePanel( Panel *parent, const char *panelName ) : vgui::Panel( parent, panelName )
+ {
+ m_ugcHandle = 0;
+ }
+
+ uint64 m_ugcHandle;
+
+ virtual void Paint()
+ {
+ if ( m_ugcHandle == 0 )
+ {
+ return;
+ }
+ int iTextureHandle = GetCustomTextureGuiHandle( m_ugcHandle );
+ if ( iTextureHandle <= 0)
+ {
+ return;
+ }
+
+ vgui::surface()->DrawSetColor(COLOR_WHITE);
+ vgui::surface()->DrawSetTexture( iTextureHandle );
+ int iWide, iTall;
+ GetSize( iWide, iTall );
+
+ vgui::Vertex_t verts[4];
+ verts[0].Init( Vector2D( 0, 0 ), Vector2D( 0.0f, 0.0f ) );
+ verts[1].Init( Vector2D( iWide, 0 ), Vector2D( 1.0f, 0.0f ) );
+ verts[2].Init( Vector2D( iWide, iTall ), Vector2D( 1.0f, 1.0f ) );
+ verts[3].Init( Vector2D( 0, iTall ), Vector2D( 0.0f, 1.0f ) );
+
+ vgui::surface()->DrawTexturedPolygon( 4, verts );
+ vgui::surface()->DrawSetColor(COLOR_WHITE);
+ }
+
+};
+
+class CAbuseReportScreenShotPanel : public CBitmapPanel
+{
+public:
+ CAbuseReportScreenShotPanel( CAbuseReportDlg *pDlg, const char *panelName )
+ : CBitmapPanel( pDlg, panelName )
+ , m_pDlg( pDlg )
+ {}
+
+ CAbuseReportDlg *m_pDlg;
+
+ virtual void Paint()
+ {
+ CBitmapPanel::Paint();
+
+ const AbuseIncidentData_t::PlayerData_t *p = m_pDlg->GetAccusedPlayerPtr();
+ if ( p == NULL || !p->m_bRenderBoundsValid )
+ {
+ return;
+ }
+ int w, t;
+ GetSize( w, t );
+
+ int x0 = int( p->m_screenBoundsMin.x * (float)w );
+ int y0 = int( p->m_screenBoundsMin.y * (float)t );
+ int x1 = int( p->m_screenBoundsMax.x * (float)w );
+ int y1 = int( p->m_screenBoundsMax.y * (float)t );
+
+ vgui::surface()->DrawSetColor( Color(200, 10, 10, 200 ) );
+ vgui::surface()->DrawOutlinedRect( x0, y0, x1, y1 );
+ vgui::surface()->DrawSetColor( COLOR_WHITE );
+ }
+};
+
+void CAbuseReportDlg::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ EditablePanel::ApplySchemeSettings( pScheme );
+
+ m_pScreenShotBitmap = new CAbuseReportScreenShotPanel( this, "ScreenShotBitmap" );
+ m_pCustomTextureImagePanel = new CCustomTextureImagePanel( this, "CustomTextureImage" );
+
+ LoadControlSettings( GetResFilename() );
+
+ m_pPlayerRadio = dynamic_cast(FindChildByName( "PlayerRadio", true ));
+ Assert( m_pPlayerRadio );
+ if ( m_pPlayerRadio )
+ {
+ m_pPlayerRadio->SetVisible( m_pIncidentData->m_bCanReportGameServer );
+ }
+
+ m_pGameServerRadio = dynamic_cast(FindChildByName( "GameServerRadio", true ));
+ Assert( m_pGameServerRadio );
+ if ( m_pGameServerRadio )
+ {
+ m_pGameServerRadio->SetVisible( m_pIncidentData->m_bCanReportGameServer );
+ }
+
+ m_pPlayerLabel = FindChildByName( "PlayerLabel", true );
+ Assert( m_pPlayerLabel );
+
+ m_pScreenShotAttachCheckButton = dynamic_cast(FindChildByName( "ScreenShotAttachCheckButton", true ));
+ Assert( m_pScreenShotAttachCheckButton );
+ if ( m_pScreenShotAttachCheckButton )
+ {
+ m_pScreenShotAttachCheckButton->SetSelected( true );
+ }
+
+ m_pSubmitButton = dynamic_cast(FindChildByName( "SubmitButton", true ));
+ Assert( m_pSubmitButton );
+
+ m_pDescriptionTextEntry = dynamic_cast(FindChildByName( "DescriptionTextEntry", true ));
+ Assert( m_pDescriptionTextEntry );
+ if ( m_pDescriptionTextEntry )
+ {
+ m_pDescriptionTextEntry->SetMultiline( true );
+ }
+
+ m_pAvatarImage = dynamic_cast(FindChildByName( "AvatarImage", true ));
+ Assert( m_pAvatarImage );
+
+ m_pNoAvatarLabel = FindChildByName( "NoAvatarLabel", true );
+ Assert( m_pNoAvatarLabel );
+
+ m_pNoCustomTexturesLabel = FindChildByName( "NoCustomTexturesLabel", true );
+ Assert( m_pNoCustomTexturesLabel );
+
+ m_pCustomTextureNextButton = dynamic_cast(FindChildByName( "CustomTextureNextButton", true ));
+ Assert( m_pCustomTextureNextButton );
+
+ m_pCustomTexturePrevButton = dynamic_cast(FindChildByName( "CustomTexturePrevButton", true ));
+ Assert( m_pCustomTexturePrevButton );
+
+ m_pPlayerCombo = dynamic_cast(FindChildByName( "PlayerComboBox", true ));
+ Assert( m_pPlayerCombo );
+
+ m_pAbuseContentLabel = FindChildByName( "AbuseContentLabel", true );
+ Assert( m_pAbuseContentLabel );
+
+ m_pAbuseContentCombo = dynamic_cast(FindChildByName( "AbuseContentComboBox", true ));
+ Assert( m_pAbuseContentCombo );
+ if ( m_pAbuseContentCombo )
+ {
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentNoSelection ) );
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentAvatarImage", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentAvatarImage ) );
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentPlayerName", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentPersonaName ) );
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentItemDecal", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentUGCImage ) );
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentChatText", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentComments ) );
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentCheating", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentCheating ) );
+ m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentOther", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentUnspecified ) );
+ m_pAbuseContentCombo->SilentActivateItemByRow( 0 );
+ m_pAbuseContentCombo->SetNumberOfEditLines( m_pAbuseContentCombo->GetItemCount() );
+ }
+
+ m_pAbuseTypeLabel = FindChildByName( "AbuseTypeLabel", true );
+ Assert( m_pAbuseTypeLabel );
+
+ m_pAbuseTypeCombo = dynamic_cast(FindChildByName( "AbuseTypeComboBox", true ));
+ Assert( m_pAbuseTypeCombo );
+
+ Assert( m_pScreenShotBitmap );
+ if ( m_pScreenShotBitmap && m_pIncidentData->m_bitmapScreenshot.IsValid() )
+ {
+ m_pScreenShotBitmap->SetBitmap( m_pIncidentData->m_bitmapScreenshot );
+ }
+
+ PopulatePlayerList();
+ SetIsAccusingGameServer( false );
+
+ SetEnabled( true );
+ SetVisible( true );
+}
+
+bool CAbuseReportDlg::IsAccusingGameServer()
+{
+ return m_pIncidentData && m_pIncidentData->m_bCanReportGameServer && m_pGameServerRadio && m_pGameServerRadio->IsSelected();
+}
+
+EAbuseReportContentType CAbuseReportDlg::GetAbuseContentType()
+{
+ if ( m_pAbuseContentCombo == NULL || IsAccusingGameServer() )
+ {
+ Assert( m_pAbuseContentCombo );
+ return k_EAbuseReportContentNoSelection;
+ }
+ KeyValues *pUserData = m_pAbuseContentCombo->GetActiveItemUserData();
+ if ( pUserData == NULL )
+ {
+ return k_EAbuseReportContentNoSelection;
+ }
+ return (EAbuseReportContentType)pUserData->GetInt( "code", k_EAbuseReportContentNoSelection );
+}
+
+EAbuseReportType CAbuseReportDlg::GetAbuseType()
+{
+ if ( m_pAbuseTypeCombo == NULL || IsAccusingGameServer() )
+ {
+ Assert( m_pAbuseTypeCombo );
+ return k_EAbuseReportTypeNoSelection;
+ }
+ KeyValues *pUserData = m_pAbuseTypeCombo->GetActiveItemUserData();
+ if ( pUserData == NULL )
+ {
+ return k_EAbuseReportTypeNoSelection;
+ }
+ return (EAbuseReportType)pUserData->GetInt( "code", k_EAbuseReportTypeNoSelection );
+}
+
+CUtlString CAbuseReportDlg::GetAbuseDescription()
+{
+ char buf[ 1024 ] = "";
+ if ( m_pDescriptionTextEntry )
+ {
+ m_pDescriptionTextEntry->GetText( buf, ARRAYSIZE(buf) );
+ }
+
+ return CUtlString( buf );
+}
+
+int CAbuseReportDlg::GetAccusedPlayerIndex()
+{
+ // If accusing a game server, then there's no player
+ if ( IsAccusingGameServer() )
+ {
+ return -1;
+ }
+
+ if ( m_pPlayerCombo == NULL )
+ {
+ Assert( m_pPlayerCombo );
+ return -1;
+ }
+
+ // Item 0 is the "