Merge Mapbase into 2025 MP branch

This commit is contained in:
ALLEN-PC\acj30 2025-02-23 17:36:54 -06:00
commit c748a82eb3
930 changed files with 153829 additions and 1919 deletions

2
.gitattributes vendored
View File

@ -32,9 +32,9 @@ vpc binary
*.inl text
*.asm text
.github/CONTRIBUTING.md text
.gitignore text
README.md text
CONTRIBUTING text
LICENSE text
*.exe binary

66
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,66 @@
This file details how to contribute to the Mapbase project on GitHub:
https://github.com/mapbase-source/source-sdk-2013
For the original Source SDK 2013 contribution guidelines, click here:
https://github.com/ValveSoftware/source-sdk-2013/blob/master/CONTRIBUTING
---
Mapbase is a project which many Source modders draw from, so it has its own unique standards
for contributions which differ from other projects, but it is still an open-source repository
that is always open to contributions.
Whenever you contribute to the Mapbase repository, you must keep in mind that any contributions
made could be deployed to all mods utilizing Mapbase, which can include everything from high-profile
Steam mods to amateur HL2 maps. Many contributions can also end up being available in both SP and MP
if the contributions are not obviously exclusive to one of the two.
All contributions must follow the following rules:
* A contribution must be aligned with Mapbase's goals and priorities and should not be "subjective"
or related to a specific mod or type of mod. For example, fixing an existing issue or adding a
new tool for mappers to use is usually fine, but adding a new custom weapon with its own assets
is usually not fit for Mapbase.
* All content in a contribution must be either already legally open-source or done with the
full permission of the content's original creator(s). If a license is involved, the contributor
should ensure Mapbase conforms to its terms.
* **NOTE:** Due to concerns with mods which do not wish to be open-source, content using GPL licenses (or any
license with similar open-source requirements) are currently not allowed to be distributed with Mapbase.
Contributions which can draw from them without actually distributing the licensed content may be excepted
from this rule.
* Contributions must not break existing maps/content or interfere with them in a negative or non-objective way.
* Code contributions are not obliged to follow Mapbase's preprocessor conventions (e.g. #ifdef MAPBASE),
although following them is usually acceptable.
* Code contributions which modify or add onto existing code should generally match its syntax and shouldn't
change the spacing unless necessary.
* If you are contributing a file you created yourself specifically for Mapbase, you are required to
use the custom "Mapbase - Source 2013" header used in other Mapbase files as of Mapbase v5.0.
You are encouraged to append an "Author(s)" part to that header in your file in order to clarify who wrote it.
* Do not modify the README to add attribution for your contribution. That is handled by Mapbase's maintainers.
Contributions which do not follow these guidelines cannot be accepted into Mapbase. Attempting to contribute content
which seriously violates the rules above can lead to being blocked from contributing, especially if done repeatedly.
---
Mapbase uses GitHub Actions to help manage issues and pull requests. Some of these workflows build the code of incoming
contributions to make sure they compile properly. The code is compiled separately for Visual Studio 2022 and GCC/G++ 9 (Linux)
and on both Debug and Release configurations.
If these workflows fail, don't freak out! Accidents can happen frequently due to compiler syntax differences and conflicts
from other contributions. You can look at a failed workflow's log by clicking "Details", which will include the build's output
in the "Build" step(s). Any errors must be resolved by you and/or by code reviewers before a pull request can be merged.
If your contribution is accepted, you may be listed in Mapbase's credits and the README's external content list:
https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits#Contributors
https://github.com/mapbase-source/source-sdk-2013/blob/master/README
You may also receive the "Contributor" or "Major Contributor" role on Mapbase's Discord server if you are
a member of it.

View File

@ -0,0 +1,25 @@
---
name: Bug report - Code
about: Create a bug report related to the source code itself. (e.g. a compile error)
title: "[CODE] "
labels: Bug
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Have '...' set to something
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,25 @@
---
name: Bug report - Game
about: Create a bug report related to game behavior.
title: "[GAME] "
labels: Bug
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Have '...' in the map
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,25 @@
---
name: Bug report - Miscellaneous
about: Create a bug report not related to any of the other subjects.
title: "[MISC] "
labels: Bug
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Do '...'
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,25 @@
---
name: Bug report - NPCs
about: Create a bug report related to NPCs.
title: "[NPCs] "
labels: Bug
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Have '...' do something
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,25 @@
---
name: Bug report - Tools
about: Create a bug report related to compile tools, editor stuff, etc.
title: "[TOOLS] "
labels: Bug, Tools
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Have '...' in the map
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,29 @@
---
name: Bug report - Visuals/Graphics
about: Create a bug report related to visual issues. (e.g. shaders, projected textures,
etc.)
title: "[VISUAL] "
labels: Bug
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Have '...' in the map
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
### Media
Any related screenshots, videos, etc. which show the bug.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,25 @@
---
name: Bug report - VScript
about: Create a bug report related to VScript.
title: "[VSCRIPT] "
labels: Bug, VScript
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior:
1. Have '...' in the script
2. ???
3. See error
### Expected behavior
A clear and concise description of what you expected to happen.
---
### Additional context
(Optional) Add any other context about the problem here.

View File

@ -0,0 +1,22 @@
---
name: Feature request - Code
about: Suggest an idea related to the source code itself. (e.g. a new utility function)
title: "[CODE] "
labels: Enhancement
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,22 @@
---
name: Feature request - Game
about: Suggest an idea related to game behavior.
title: "[GAME] "
labels: Enhancement
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,22 @@
---
name: Feature request - Miscellaneous
about: Suggest an idea not related to any of the other subjects.
title: "[MISC] "
labels: Enhancement
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,22 @@
---
name: Feature request - NPCs
about: Suggest an idea related to NPCs.
title: "[NPCs] "
labels: Enhancement
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,22 @@
---
name: Feature request - Tools
about: Suggest an idea related to compile tools, editor stuff, etc.
title: "[TOOLS] "
labels: Enhancement, Tools
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,23 @@
---
name: Feature request - Visuals/Graphics
about: Suggest an idea related to visuals or graphics. (e.g. shaders, projected textures,
etc.)
title: "[VISUAL] "
labels: Enhancement
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,22 @@
---
name: Feature request - VScript
about: Suggest an idea related to VScript.
title: "[VSCRIPT] "
labels: Enhancement, VScript
assignees: ''
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
---
### Additional context
(Optional) Add any other context or screenshots about the feature request here.

35
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,35 @@
#
# MAPBASE REPO AUTOMATION
#
# Automatically labels pull requests according to changed file paths.
# See mapbase_pr.yml for more information.
#
Repo:
- '*'
- '.github/**'
Project Generation:
- '**/src/vpc_scripts/**'
- '**/src/devtools/**'
- '**/src/create*'
Entities:
- '**/src/game/**/**logic**'
- '**/src/game/**/**point**'
Shaders:
- '**/src/materialsystem/**'
VScript:
- '**vscript**'
Tools:
- '**utils**'
NPCs:
- '**npc_**'
- '**ai_**'
VGUI:
- '**hud_**'
- '**vgui_**'

11
.github/pull-request-template.md vendored Normal file
View File

@ -0,0 +1,11 @@
(Describe your PR here and then fill out the checklist at the bottom)
---
#### Does this PR close any issues?
* (Optional) Insert issue number(s) and any related info here
<!-- Replace [ ] with [x] for each item your PR satisfies -->
#### PR Checklist
- [ ] **My PR follows all guidelines in the CONTRIBUTING.md file**
- [ ] My PR targets a `develop` branch OR targets another branch with a specific goal in mind

View File

@ -0,0 +1,70 @@
#
# MAPBASE SOURCE 2013 CI
#
# This can be used to manually build the codebase.
#
# See mapbase_build-base.yml for more information on how this works.
name: Build Projects (Manual)
on:
workflow_dispatch:
inputs:
configuration:
description: 'Which configuration to build with'
default: 'Release'
required: true
type: choice
options:
- Release
- Debug
branch:
description: 'Which Source 2013 engine branch to compile for'
default: 'sp'
required: true
type: choice
options:
- sp
- mp
game:
description: 'Name of the game to build (if relevant)'
default: 'episodic'
required: false
type: choice
options:
- episodic
- hl2
project-group:
description: 'Which group of projects to compile'
required: true
type: choice
options:
- all
- game
- shaders
- maptools
solution-name:
description: 'Name of the solution/makefile'
required: true
type: choice
options:
- everything
- games
- shaders
- maptools
build-on-linux:
description: 'Build on Ubuntu/Linux?'
default: true
required: false
type: boolean
jobs:
build_manual:
uses: ./.github/workflows/mapbase_build-base.yml
with:
configuration: '${{ github.event.inputs.configuration }}'
branch: '${{ github.event.inputs.branch }}'
game: '${{ github.event.inputs.game }}'
project-group: '${{ github.event.inputs.project-group }}'
solution-name: '${{ github.event.inputs.solution-name }}'
build-on-linux: "${{ github.event.inputs.build-on-linux == 'true' }}"

195
.github/workflows/mapbase_build-base.yml vendored Normal file
View File

@ -0,0 +1,195 @@
#
# MAPBASE SOURCE 2013 CI
#
# This workflow script automatically builds the Source SDK 2013 codebase on Windows and Linux using GitHub Actions.
#
# This is useful in a number of ways:
#
# 1. It ensures pull requests compile correctly on multiple platforms and provides binaries that can be used to test them.
# 2. It can be used to compile code for releases without having to pull and prepare a local development environment.
# 3. It opens potential for scripts that can employ more principles of CI/CD. (e.g. automatically publishing a release)
#
# This is based on a workflow originally created by z33ky.
name: Build Projects
on:
workflow_call:
inputs:
configuration:
description: 'Which configuration to build with'
default: 'Release'
required: true
type: string
branch:
description: 'Which Source 2013 engine branch to compile for'
default: 'sp'
required: true
type: string
game:
description: 'The name of the game to build (if relevant)'
default: 'episodic'
required: false
type: string
project-group:
description: 'Which group of projects to compile'
required: true
type: string
solution-name:
description: 'The name of the solution/makefile'
required: true
type: string
build-on-linux:
description: 'Build on Ubuntu/Linux?'
default: true
required: false
type: boolean
jobs:
build_windows:
name: Windows (VS2022)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Add MSBuild to PATH
uses: compnerd/gha-setup-vsdevenv@v6
- name: Enable VS2022
working-directory: '${{inputs.branch}}/src/vpc_scripts'
shell: bash
run: sed -i 's/^\($Conditional[ ]\+VS2022[ ]\+\).*/\1"1"/' newer_vs_toolsets.vpc
- name: Pick game
if: inputs.project-group == 'game' || inputs.project-group == 'shaders'
working-directory: '${{inputs.branch}}/src'
shell: bash
run: sed -i 's/\/hl2 \/episodic/\/${{inputs.game}}/' create${{inputs.project-group}}projects.bat
- name: Create project files
working-directory: '${{inputs.branch}}/src'
shell: cmd
# https://github.com/ValveSoftware/source-sdk-2013/issues/72
run: |
reg add "HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\10.0\Projects\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" /v DefaultProjectExtension /t REG_SZ /d vcproj /f
create${{inputs.project-group}}projects.bat
# --------------------------------------------------------------------
- name: Build
#if: steps.filter.outputs.game == 'true'
working-directory: '${{inputs.branch}}/src'
shell: cmd
run: |
devenv ${{inputs.solution-name}}.sln /upgrade
msbuild -m -t:Rebuild -p:Configuration=${{inputs.configuration}};Platform=x86 ${{inputs.solution-name}}.sln
# --------------------------------------------------------------------
- name: Publish game binaries
if: inputs.project-group == 'game' || inputs.project-group == 'shaders'
uses: actions/upload-artifact@v4
with:
name: '${{inputs.project-group}}_${{inputs.game}}_win32_${{ inputs.configuration }}'
path: |
${{inputs.branch}}/game/mod_${{inputs.game}}/bin/*.dll
if-no-files-found: error
- name: Publish map tools
if: inputs.project-group == 'maptools'
uses: actions/upload-artifact@v4
with:
name: '${{inputs.project-group}}_win32_${{ inputs.configuration }}'
path: |
${{inputs.branch}}/game/bin/*.exe
${{inputs.branch}}/game/bin/*.dll
if-no-files-found: error
- name: Publish everything
if: inputs.project-group == 'all'
uses: actions/upload-artifact@v4
with:
name: 'everything_win32_${{ inputs.configuration }}'
path: |
${{inputs.branch}}/game/bin
${{inputs.branch}}/game/mod_*/bin
if-no-files-found: error
build_ubuntu:
if: inputs.build-on-linux == true && inputs.project-group != 'maptools' # No Linux map tools for now
name: Ubuntu (GCC/G++)
runs-on: ubuntu-latest
env:
config: ${{ inputs.configuration }}
steps:
- uses: actions/checkout@v3
- name: Install GCC/G++ multilib
run: |
sudo apt-get update
sudo apt-get install gcc-multilib g++-multilib
- name: Pick game
if: inputs.project-group == 'game' || inputs.project-group == 'shaders'
working-directory: '${{inputs.branch}}/src'
shell: bash
run: sed -i 's/\/hl2 \/episodic/\/${{inputs.game}}/' create${{inputs.project-group}}projects
- name: Set configuration
working-directory: '${{inputs.branch}}/src'
shell: bash
run: |
config=${{inputs.configuration}}
export CFG=${config,,}
echo "config=${CFG}" >> $GITHUB_ENV
- name: Create project files
working-directory: '${{inputs.branch}}/src'
run: ./create${{inputs.project-group}}projects
# --------------------------------------------------------------------
- name: Build
working-directory: '${{inputs.branch}}/src'
run: make CFG=${{env.config}} -f ${{inputs.solution-name}}.mak
# --------------------------------------------------------------------
- name: Publish game binaries
if: inputs.project-group == 'game' || inputs.project-group == 'shaders'
uses: actions/upload-artifact@v4
with:
name: '${{inputs.project-group}}_${{inputs.game}}_linux32_${{ inputs.configuration }}'
path: |
${{inputs.branch}}/game/mod_${{inputs.game}}/bin/*.so
!${{inputs.branch}}/game/mod_${{inputs.game}}/bin/*_srv.so
if-no-files-found: error
#- name: Publish map tools
# if: inputs.project-group == 'maptools'
# uses: actions/upload-artifact@v4
# with:
# name: '${{inputs.project-group}}_linux32_${{ inputs.configuration }}'
# path: |
# ${{inputs.branch}}/game/bin/vbsp
# ${{inputs.branch}}/game/bin/vvis
# ${{inputs.branch}}/game/bin/vvis_dll.so
# ${{inputs.branch}}/game/bin/vrad
# ${{inputs.branch}}/game/bin/vrad_dll.so
# if-no-files-found: error
# For now, don't publish the .dbg files even though we publish .pdb files on Windows
# (they're too big)
- name: Publish everything
if: inputs.project-group == 'all'
uses: actions/upload-artifact@v4
with:
name: 'everything_linux32_${{ inputs.configuration }}'
path: |
${{inputs.branch}}/game/bin/*.so
!${{inputs.branch}}/game/bin/*_srv.so
${{inputs.branch}}/game/mod_*/bin/*.so
!${{inputs.branch}}/game/mod_*/bin/*_srv.so
if-no-files-found: error

View File

@ -0,0 +1,31 @@
#
# MAPBASE SOURCE 2013 CI
#
# Builds all projects when a pull request to the master branch is opened.
# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs.
#
# The "mapbase_build-sp" set of workflows can build specific projects depending on what files are changed.
# They are designed around a "develop" branch, but can be configured to target "master" and replace this
# instead (or target a similar branch with a different name)
#
# See mapbase_build-base.yml for more information on how this works.
name: Build All Projects #(SP Release)
on:
pull_request:
branches:
- master
jobs:
everything:
strategy:
matrix:
configuration: [Release, Debug]
uses: ./.github/workflows/mapbase_build-base.yml
with:
configuration: ${{ matrix.configuration }}
branch: 'sp'
project-group: 'all'
solution-name: 'everything'
build-on-linux: true # Disable this if you don't want to compile for Linux

View File

@ -0,0 +1,38 @@
#
# MAPBASE SOURCE 2013 CI
#
# Builds game projects every time a pull request which modifies the game code is opened.
# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs.
#
# See mapbase_build-base.yml for more information on how this works.
name: Build Game Projects #(SP Release)
on:
pull_request:
branches:
- develop
paths:
- '.github/workflows/mapbase_build-base.yml'
- '.github/workflows/mapbase_build-sp-rel-games.yml'
- 'sp/src/vpc_scripts/**'
- 'sp/src/game/**'
- 'sp/src/mathlib/**'
- 'sp/src/responserules/runtime/**'
- 'sp/src/tier1/**'
- 'sp/src/vgui2/vgui_controls/**'
- 'sp/src/vscript/**'
jobs:
games:
strategy:
matrix:
configuration: [Release, Debug]
uses: ./.github/workflows/mapbase_build-base.yml
with:
configuration: ${{ matrix.configuration }}
branch: 'sp'
game: 'episodic' # Change this if your mod is not using HL2/Episodic game projects
project-group: 'game'
solution-name: 'games'
build-on-linux: true # Disable this if you don't want to compile for Linux

View File

@ -0,0 +1,38 @@
#
# MAPBASE SOURCE 2013 CI
#
# Builds map tool projects every time a pull request which modifies the map tool code is opened.
# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs.
#
# See mapbase_build-base.yml for more information on how this works.
name: Build Map Tool Projects #(SP Release)
on:
pull_request:
branches:
- develop
paths:
- '.github/workflows/mapbase_build-sp-rel-maptools.yml'
- 'sp/src/vpc_scripts/**'
- 'sp/src/utils/vbsp/**'
- 'sp/src/utils/vvis/**'
- 'sp/src/utils/vvis_launcher/**'
- 'sp/src/utils/vrad/**'
- 'sp/src/utils/vrad_launcher/**'
- 'sp/src/mathlib/**'
- 'sp/src/tier1/**'
- 'sp/src/vgui2/vgui_controls/**'
- 'sp/src/vscript/**'
jobs:
maptools:
strategy:
matrix:
configuration: [Release, Debug]
uses: ./.github/workflows/mapbase_build-base.yml
with:
configuration: ${{ matrix.configuration }}
branch: 'sp'
project-group: 'maptools'
solution-name: 'maptools'

View File

@ -0,0 +1,33 @@
#
# MAPBASE SOURCE 2013 CI
#
# Builds shader projects every time a pull request which modifies the shader code is opened.
# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs.
#
# See mapbase_build-base.yml for more information on how this works.
name: Build Shader Projects #(SP Release)
on:
pull_request:
branches:
- develop
paths:
- '.github/workflows/mapbase_build-sp-rel-shaders.yml'
- 'sp/src/vpc_scripts/**'
- 'sp/src/materialsystem/**'
- 'sp/src/mathlib/**'
jobs:
shaders:
strategy:
matrix:
configuration: [Release, Debug]
uses: ./.github/workflows/mapbase_build-base.yml
with:
configuration: ${{ matrix.configuration }}
branch: 'sp'
game: 'episodic' # Change this if your mod is not using HL2/Episodic game projects
project-group: 'shaders'
solution-name: 'shaders'
build-on-linux: true # Disable this if you don't want to compile for Linux

23
.github/workflows/mapbase_pr.yml vendored Normal file
View File

@ -0,0 +1,23 @@
#
# MAPBASE REPO AUTOMATION
#
# Automatically labels pull requests according to changed file paths.
#
# https://github.com/actions/labeler
name: Pull Request Automation
on: [pull_request] # pull_request_target
jobs:
label:
if: github.repository_owner == 'mapbase-source' # ${{ vars.MAPBASE_LABELS == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

8
.gitignore vendored
View File

@ -26,6 +26,7 @@ ipch
*.xcodeproj/
obj*/
!devtools/*.mak
sp/src/devtools/makefile_base_posix.mak.link
!utils/smdlexp/smdlexp.mak
# Specific Source build products
@ -53,6 +54,13 @@ config.cfg
# shader files
*.tmp
*.vcs
# Unnecessary files
*.lib
*.filters
*.vpc_crc
*.sentinel
# GCH
*.h.gch

View File

@ -1,38 +0,0 @@
Thanks for your interest in the Source SDK 2013 project. When you make a
contribution to the project (e.g. create an Issue or submit a Pull Request)
(a "Contribution"), Valve wants to be able to use your Contribution to improve
the SDK and other Valve products.
As a condition of providing a Contribution, you agree that:
- You grant Valve a non-exclusive, irrevocable, royalty-free, worldwide license
to make, use, sell, reproduce, modify, distribute (directly and indirectly),
and publicly display and perform the Contribution, and any derivative works
that Valve may make from the Contribution, under any intellectual property you
own or have the right to license.
- You warrant and represent that the Contribution is your original creation,
that you have the authority to grant this license to Valve, and that this
license does not require the permission of any third party. Otherwise, you
provide your Contribution "as is" without warranties.
Should you wish to submit a suggestion or work that is not your original
creation, you may submit it to Valve separate from any Contribution,
explicitly identifying it as sourced from a third party, stating the details
of its origin, and informing Valve of any license or other restriction of
which you are personally aware.
Valve is happy to accept pull requests and issues in the source-sdk-2013
repository in these cases:
* Changes that fix bugs in the SDK deployment process itself. The repository
should build out of the box, and anything that prevents that is a pull
request we want.
* High priority bugs in HL2, the Episodes, or HL2MP that can be fixed in
client.dll or server.dll.
For other changes we suggest that you issue a pull request to one of these
fine community-maintained repositories instead:
https://developer.valvesoftware.com/wiki/Source-sdk-2013-community-repos
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.

223
README.md
View File

@ -1,3 +1,226 @@
//=========================================================================================================================
Mapbase v7.3 - Source 2013
https://github.com/mapbase-source/source-sdk-2013
https://www.moddb.com/mods/mapbase
//=========================================================================================================================
This repository contains code from Mapbase, a modification of the Source 2013 SDK which serves as a combined package
of general-purpose improvements, fixes, and utility features for mods.
Mapbase's main content in this repository may include:
- 80+ custom entities (new logic entities, filters, etc.)
- Hundreds of Inputs/Outputs/KeyValues additions and modifications
- Custom SDK_ shaders with improvements adapted from Alien Swarm SDK code, including projected texture fixes and radial fog
- Custom VScript implementation based on public Squirrel API and Alien Swarm SDK interfaces/descriptions
- Additional gameplay control for Half-Life 2 mods, including grenade features for more NPCs and singleplayer respawning
- More map-specific capabilities for maps unable to branch into their own mods, e.g. MP mods or map compilations
- View rendering changes for drawing 3D skyboxes and RT-based entities
- Countless other fixes and improvements
For more information, view this page:
https://github.com/mapbase-source/source-sdk-2013/wiki/Introduction-to-Mapbase
//=========================================================================================================================
Mapbase is an open-source project and its contents can be distributed and used at the discretion of its users. However, this project contains content from
a vast number of different sources which have their own licensing or attribution requirements. We try to handle most of that ourselves, but users who plan on
distributing Mapbase content are expected to comply with certain rules.
Up-to-date information about Mapbase content usage and credit are addressed in this article on Mapbase's wiki:
https://github.com/mapbase-source/source-sdk-2013/wiki/Using-Mapbase-Content
//=========================================================================================================================
>>>>>>>> EXTERNAL CONTENT USED IN MAPBASE <<<<<<<<
The Mapbase project is a combination of original code from its creators, code contributed by other Source modders, and code borrowed from open-source articles
and repositories (especially ones which are specifically published as free source code). One of Mapbase's goals is to make the most popular fixes and the most obscure
or complicated code changes accessible and easy to use for level designers and other kinds of Source modders who would otherwise have no idea how to implement them.
*** DISCLAIMER: Mapbase has a strict no-leak-content policy and only allows content created directly by contributors or content originating from open-source repositories.
If you believe any content in Mapbase originates from any leak or unauthorized source (Valve or otherwise), please contact Blixibon immediately.
Mapbase is intended to be usable by everyone, including licensed Source projects and Steam mods. ***
Mapbase uses content from the following non-Source SDK 2013 Valve games or SDKs:
-- Alien Swarm SDK (Used to backport features and code from newer branches of Source into a Source 2013/Half-Life 2 environment)
-- Source SDK 2007 Code (Used to implement some of Tony Sergi's code changes)
-- Alien Swarm (Used to port assets from the aforementioned SDK code features, e.g. game instructor icons)
-- Left 4 Dead (Used to port certain animations as well as assets from the aforementioned SDK code features, e.g. particle rain)
-- Half-Life: Source (Used to port friction tool textures)
Valve allows assets from these titles to be distributed for modding purposes. Note that ported assets are only used in the release build, not the code repository.
Mapbase may also contain new third-party software distributed under specific licensing. Please see the bottom of thirdpartylegalnotices.txt for more information.
Here's a list of Mapbase's other external code sources:
- https://github.com/95Navigator/insolence-2013 (Initial custom shader code and projected texture improvements; also used to implement ASW SDK particle precipitation code)
-- https://github.com/Biohazard90/g-string_2013 (Custom shadow filters, included indirectly via Insolence repo)
-- https://github.com/KyleGospo/City-17-Episode-One-Source (Brush phong and projected texture changes, included indirectly via Insolence repo)
- https://github.com/DownFall-Team/DownFall (Multiple skybox code and fix for ent_fire delay not using floats; Also used as a guide to port certain Alien Swarm SDK changes to Source 2013,
including radial fog, rope code, and treesway)
- https://github.com/momentum-mod/game (Used as a guide to port postprocess_controller and env_dof_controller to Source 2013 from the Alien Swarm SDK)
- https://github.com/DeathByNukes/source-sdk-2013 (VBSP manifest fixes)
- https://github.com/entropy-zero/source-sdk-2013 (skill_changed game event)
- https://github.com/Nbc66/source-sdk-2013-ce/tree/v142 (Base for VS2019 toolset support)
//-------------------------------------------------------------------------------------------------------------------------
Valve Developer Community (VDC) sources:
- https://developer.valvesoftware.com/wiki/Dynamic_RTT_shadow_angles_in_Source_2007 (Dynamic RTT shadow angles by Saul Rennison)
- https://developer.valvesoftware.com/wiki/Parallax_Corrected_Cubemaps (Parallax corrected cubemaps implementation from Brian Charles)
- https://developer.valvesoftware.com/wiki/Adding_the_Game_Instructor (ASW SDK game instructor adapted to Source 2013 by Kolesias123; was implemented based on a translated article)
- https://developer.valvesoftware.com/wiki/Brush_ladders (Functional func_ladders in Source 2013)
- https://developer.valvesoftware.com/wiki/CAreaPortalOneWay (func_areaportal_oneway)
- https://developer.valvesoftware.com/wiki/Implementing_Discord_RPC (Discord RPC implementation; Mapbase has its own framework originally based on this article)
- https://developer.valvesoftware.com/wiki/Rain_splashes (NOTE: This code is not completely used in Mapbase, but may still exist in its codebase)
- https://developer.valvesoftware.com/wiki/Hand_Viewmodels (NOTE: This code is not completely supported by default because Mapbase does not yet have weapon viewmodels which support
interchangeable arms; this may change in the future)
- https://developer.valvesoftware.com/wiki/General_SDK_Snippets_%26_Fixes (Various snippets on the article, including the dropship gun fix)
- https://developer.valvesoftware.com/wiki/Memory_Leak_Fixes (Most of these snippets were applied in later SDK updates, but some were not and have been added to Mapbase)
- https://developer.valvesoftware.com/wiki/Env_projectedtexture/fixes (Misc. env_projectedtexture fixes; Some of these are superceded by Alien Swarm-based changes and not used)
- https://developer.valvesoftware.com/wiki/Scenes.image (Original raw VCD file support; Code was improved for Mapbase and the article was later updated with it)
- https://developer.valvesoftware.com/wiki/Extending_Prop_Sphere (prop_sphere customization)
- https://developer.valvesoftware.com/wiki/TF2_Glow_Effect_(2013_SDK) (Glow effect)
- https://developer.valvesoftware.com/wiki/CFuncMoveLinear_ParentingFix (func_movelinear parenting fix; Code was improved for Mapbase and the article was later updated with it)
- https://developer.valvesoftware.com/wiki/Viewmodel_Prediction_Fix (Viewmodel prediction fix)
- https://developer.valvesoftware.com/wiki/Owner#Collisions_with_owner (FSOLID_COLLIDE_WITH_OWNER flag)
- https://developer.valvesoftware.com/wiki/Npc_clawscanner#Strider_Scout_Issue (npc_clawscanner strider scout fix)
- https://developer.valvesoftware.com/wiki/Ambient_generic:_stop_and_toggle_fix (Fixes for stopping/toggling ambient_generic)
- https://developer.valvesoftware.com/wiki/Func_clip_vphysics ("Start Disabled" keyvalue fix)
- https://developer.valvesoftware.com/wiki/Importing_CSS_Weapons_Into_HL2 (CS:S viewmodel chirality)
//-------------------------------------------------------------------------------------------------------------------------
Direct contributions:
- https://github.com/mapbase-source/source-sdk-2013/pull/3 ("playvideo" command playback fix from Avanate)
- https://github.com/mapbase-source/source-sdk-2013/pull/5 (Custom VScript implementation by ReDucTor; was placed into feature branch before being merged in a subsequent PR)
- https://github.com/mapbase-source/source-sdk-2013/pull/60 (Adjustment by RoyaleNoir to one of Saul's VDC changes)
- https://github.com/mapbase-source/source-sdk-2013/pull/84 (CS:S viewmodel chirality from 1upD)
- https://github.com/mapbase-source/source-sdk-2013/pull/116 (vgui_movie_display mute keyvalue from Alivebyte/rzkid)
- https://github.com/mapbase-source/source-sdk-2013/pull/140 (logic_substring entity and icon created by moofemp)
- https://github.com/mapbase-source/source-sdk-2013/pull/143 (Propper features for VBSP from Matty-64)
- https://github.com/mapbase-source/source-sdk-2013/pull/174 (Fix for multiply defined symbols in later toolsets from und)
- https://github.com/mapbase-source/source-sdk-2013/issues/201 (env_projectedtexture shadow filter keyvalue from celisej567)
- https://github.com/mapbase-source/source-sdk-2013/pull/193 (RTB:R info_particle_system_coordinate by arbabf and Iridium77)
- https://github.com/mapbase-source/source-sdk-2013/pull/193 (Infinite prop_interactable cooldown by arbabf)
- https://github.com/mapbase-source/source-sdk-2013/pull/229 (Extended point_bugbait functionality by arbabf)
- https://github.com/mapbase-source/source-sdk-2013/pull/236 (Toggleable prop sprinting by Crimson-X1)
- https://github.com/mapbase-source/source-sdk-2013/pull/237 (Commander goal trace fix by Agrimar)
- https://github.com/mapbase-source/source-sdk-2013/pull/245 (ViewPunch random fix by Mr0maks)
- https://github.com/mapbase-source/source-sdk-2013/pull/248 (soundlevel_t conversation warning fix by Mechami)
- https://github.com/mapbase-source/source-sdk-2013/pull/266 ("OnPhysGunPull" output in CPhysicsProp by rlenhub)
- https://github.com/mapbase-source/source-sdk-2013/pull/292 (env_headcrabcanister random spawn type by arbabf)
- https://github.com/mapbase-source/source-sdk-2013/pull/294 (SDK_LightmappedGeneric editor blend swap fix by azzyr)
- https://github.com/mapbase-source/source-sdk-2013/pull/308 (BlurFilterY fix by Wikot235)
- https://github.com/mapbase-source/source-sdk-2013/pull/312 (Zombie improvements by Wikot235)
- https://github.com/mapbase-source/source-sdk-2013/pull/315 (env_flare crash fix by Wikot235)
- https://github.com/mapbase-source/source-sdk-2013/pull/324 (server-only info/func_null by SirYodaJedi)
- https://github.com/mapbase-source/source-sdk-2013/pull/333 (Cvar to transition levels while in MOVETYPE_NOCLIP by Wikot235)
- https://github.com/mapbase-source/source-sdk-2013/pull/342 (NaN particle cull radius fix by celisej567)
- https://github.com/mapbase-source/mapbase-game-src/pull/1 (Advanced video options duplicate field name fix by arbabf; This is asset-based and not reflected in the code)
- https://github.com/mapbase-source/mapbase-game-src/pull/2 (gameinfo.txt typo fix by CarePackage17; This is asset-based and not reflected in the code)
- https://github.com/mapbase-source/mapbase-game-src/pull/3 (HudMessage cutoff fix by arbabf; This is asset-based and not reflected in the code)
- Demo autorecord code provided by Klems
- cc_emit crash fix provided by 1upD
- Custom HL2 ammo crate models created by Rykah (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code)
- Combine lock hardware on door01_left.mdl created by Kralich (This is asset-based and not reflected in the code)
- npc_vehicledriver fixes provided by CrAzY
- npc_combine cover behavior patches provided by iohnnyboy
- logic_playmovie icon created by URAKOLOUY5 (This is asset-based and not reflected in the code)
- Dropship APC save/load fix provided by Cvoxulary
== Contributions from samisalreadytaken:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/47 (VScript utility/consistency changes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/59 (New VScript functions and singletons based on API documentation in later Source/Source 2 games)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/80 (More VScript changes, including support for extremely flexible client/server messaging)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/105 (VScript fixes and optimizations, Vector class extensions, custom convars/commands)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/114 (VScript fixes and extensions)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/122 (Minor VScript-related adjustments)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/148 (Minor fixup)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/167 (Security fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/168 (Squirrel update)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/169 (VScript VGUI)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/171 (VScript documentation sorting)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/173 (VScript fixes and optimizations)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/206 (Fix CScriptNetMsgHelper::WriteEntity())
=-- https://github.com/mapbase-source/source-sdk-2013/pull/213 (VScript HUD visibility control, optimizations for 3D skybox angles/fake worldportals)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/229 (VScript VGUI HUD viewport parenting, game_text and vgui_text_display VScript font fallback)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/260 (CScriptNetPropManager rewrite)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/261 (Misc VScript additions)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/279 (weapon_custom_scripted fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/332 (Fix OOB access)
== Contributions from z33ky:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/95 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/117 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/124 (Memory error fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/130 (Memory error fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/131 (env_projectedtexture target shadows fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/132 (Console error fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/152 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/159 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/162 (VS2019 exception specification fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/170 (HL2 non-Episodic build fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/322 (Small Mapbase fixes)
== Contributions from Petercov:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/182 (NPCs load dynamic interactions from all animation MDLs)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/184 (Projected texture horizontal FOV shadow fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/185 (Fix enemyfinders becoming visible when they wake)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/186 (Fix for brightly glowing teeth)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/183 (Enhanced custom weapons support)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/230 (Caption fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/231 (Sentence source bug fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/264 (Outputs for vgui_screen)
//-------------------------------------------------------------------------------------------------------------------------
Other sources:
- Various code from Source SDK 2013 pull requests on the GitHub repository (https://github.com/ValveSoftware/source-sdk-2013/pulls):
-- https://github.com/ValveSoftware/source-sdk-2013/pull/441 (Smooth scrape sound oversight fix)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/436 (VRAD debug counter fix + thread bump)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/416 (Ragdoll null pointer dereference fix)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/401 (func_rot_button "Starts locked" flag fix)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/391 (VBSP func_detail smoothing group fix)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/362 (npc_manhack npc_maker fix; Adjusted for formatting and save/restore in Mapbase)
-- https://github.com/Petercov/Source-PlusPlus/commit/ecdf50c48cd31dec4dbdb7fea2d0780e7f0dd8ec (used as a guide for porting the Alien Swarm SDK response system)
- https://github.com/momentum-mod/game/blob/1d066180b3bf74830c51e6914d46c40b0bea1fc2/mp/src/game/server/player.cpp#L6543 (spec_goto fix)
- Poison zombie barnacle crash fix implemented based on a snippet from HL2: Plus posted by Agent Agrimar on Discord (Mapbase makes the barnacle recognize it as poison just like poison headcrabs)
- https://gamebanana.com/skins/172192 (Airboat handling fix; This is asset-based and not reflected in the code)
- Vortigaunt LOS fix originally created by dky.tehkingd.u for HL2:CE
- https://combineoverwiki.net/wiki/File:Combine_main_symbol.svg ("icon_combine" instructor icon in "materials/vgui/hud/gameinstructor_hl2_1"; This is asset-based and not reflected in the code)
//-------------------------------------------------------------------------------------------------------------------------
If there is anything missing from this list, please contact Blixibon.
//=========================================================================================================================
Aside from the content list above, Mapbase has more descriptive and up-to-date credits on this wiki article:
https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits
Other relevant articles:
* https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Disclaimers
* https://github.com/mapbase-source/source-sdk-2013/wiki/Frequently-Asked-Questions-(FAQ)
//-------------------------------------------------------------------------------------------------------------------------
In memory of Holly Liberatore (moofemp)
//=========================================================================================================================
# Source SDK 2013
Source code for Source SDK 2013.

5
src/createmaptoolsprojects Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
pushd `dirname $0`
devtools/bin/vpc /hl2 /episodic +maptools /mksln maptools
popd

View File

@ -0,0 +1 @@
devtools\bin\vpc.exe +maptools /mksln maptools.sln

5
src/createshadersprojects Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
pushd `dirname $0`
devtools/bin/vpc /hl2 /episodic +shaders /mksln shaders
popd

View File

@ -0,0 +1 @@
devtools\bin\vpc.exe /hl2 /episodic +shaders /mksln shaders.sln

View File

@ -12,6 +12,9 @@
#include "filesystem_tools.h"
#include "tier1/strtools.h"
#include "utlmap.h"
#ifdef MAPBASE
#include "fmtstr.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@ -579,6 +582,34 @@ GDclass *GameData::BeginInstanceRemap( const char *pszClassName, const char *psz
return m_InstanceClass;
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Sets up for additional instance remap fixes from Mapbase
//-----------------------------------------------------------------------------
void GameData::SetupInstanceRemapParams( int iStartNodes, int iStartBrushSide, bool bRemapVecLines )
{
// Set the numer of nodes in the level
m_InstanceStartAINodes = iStartNodes;
// If we have a "nodeid" key, set it to ivNodeDest so it's properly recognized
// during AI node remapping
GDinputvariable *var = m_InstanceClass->VarForName( "nodeid" );
if ( var )
{
var->ForceSetType( ivNodeDest );
}
//---------------------------------------------
// Set the number of brush sides in the level
m_InstanceStartSide = iStartBrushSide;
//---------------------------------------------
m_bRemapVecLines = bRemapVecLines;
}
#endif
enum tRemapOperation
{
@ -586,6 +617,13 @@ enum tRemapOperation
REMAP_POSITION,
REMAP_ANGLE,
REMAP_ANGLE_NEGATIVE_PITCH,
#ifdef MAPBASE
// Remaps the node ID for instance/manifest AI node support
REMAP_NODE_ID,
// Remaps brush sides and sidelists
REMAP_SIDES,
#endif
};
@ -624,6 +662,12 @@ bool GameData::RemapKeyValue( const char *pszKey, const char *pszInValue, char *
RemapOperation.Insert( ivOrigin, REMAP_POSITION );
RemapOperation.Insert( ivAxis, REMAP_ANGLE );
RemapOperation.Insert( ivAngleNegativePitch, REMAP_ANGLE_NEGATIVE_PITCH );
#ifdef MAPBASE
RemapOperation.Insert( ivNodeDest, REMAP_NODE_ID );
RemapOperation.Insert( ivSide, REMAP_SIDES );
RemapOperation.Insert( ivSideList, REMAP_SIDES );
RemapOperation.Insert( ivVecLine, REMAP_POSITION );
#endif
}
if ( !m_InstanceClass )
@ -657,6 +701,12 @@ bool GameData::RemapKeyValue( const char *pszKey, const char *pszInValue, char *
case REMAP_POSITION:
{
#ifdef MAPBASE
// Only remap ivVecLine if the keyvalue is enabled
if (KVType == ivVecLine && !m_bRemapVecLines)
break;
#endif
Vector inPoint( 0.0f, 0.0f, 0.0f ), outPoint;
sscanf ( pszInValue, "%f %f %f", &inPoint.x, &inPoint.y, &inPoint.z );
@ -697,6 +747,54 @@ bool GameData::RemapKeyValue( const char *pszKey, const char *pszInValue, char *
sprintf( pszOutValue, "%g", -outAngles.x ); // just the pitch
}
break;
#ifdef MAPBASE
case REMAP_NODE_ID:
{
int value = atoi( pszInValue );
if (value == -1)
break;
//Warning( " %s %s: Remapped %i to %i", m_InstanceClass->GetName(), KVVar->GetName(), value, value + m_InstanceStartAINodes );
value += m_InstanceStartAINodes;
sprintf( pszOutValue, "%i", value );
}
break;
case REMAP_SIDES:
{
CUtlStringList sideList;
V_SplitString( pszInValue, " ", sideList );
// Convert sides
CUtlStringList newSideList;
for (int i = 0; i < sideList.Count(); i++)
{
int iSide = atoi( sideList[i] );
//Warning( " %s %s: Remapped %i to %i", m_InstanceClass->GetName(), KVVar->GetName(), iSide, iSide + m_InstanceStartSide );
iSide += m_InstanceStartSide;
newSideList.AddToTail( const_cast<char*>( CNumStr( iSide ).String() ) );
}
// Initial side
strcpy( pszOutValue, newSideList[0] );
// Start at 1 for subsequent sides
for (int i = 1; i < newSideList.Count(); i++)
{
// Any subsequent sides are spaced
sprintf( pszOutValue, "%s %s", pszOutValue, newSideList[i] );
}
//Warning("Old side list: \"%s\", new side list: \"%s\"\n", pszInValue, pszOutValue);
}
break;
#endif
}
return ( strcmpi( pszInValue, pszOutValue ) != 0 );
@ -715,7 +813,11 @@ bool GameData::RemapNameField( const char *pszInValue, char *pszOutValue, TNameF
{
strcpy( pszOutValue, pszInValue );
#ifdef MAPBASE
if ( pszInValue[ 0 ] && pszInValue[ 0 ] != '@' && pszInValue[ 0 ] != '!' )
#else
if ( pszInValue[ 0 ] && pszInValue[ 0 ] != '@' )
#endif
{ // ! at the start of a value means it is global and should not be remaped
switch( NameFixup )
{

View File

@ -14,6 +14,105 @@
#include "c_baseentity.h"
#include "basetypes.h"
#ifdef ASW_PROJECTED_TEXTURES
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvProjectedTexture : public C_BaseEntity
{
DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
void SetMaterial( IMaterial *pMaterial );
void SetLightColor( byte r, byte g, byte b, byte a );
void SetSize( float flSize );
void SetRotation( float flRotation );
virtual void OnDataChanged( DataUpdateType_t updateType );
void ShutDownLightHandle( void );
#ifdef MAPBASE
virtual void Simulate();
#else
virtual bool Simulate();
#endif
void UpdateLight( void );
C_EnvProjectedTexture();
~C_EnvProjectedTexture();
static void SetVisibleBBoxMinHeight( float flVisibleBBoxMinHeight ) { m_flVisibleBBoxMinHeight = flVisibleBBoxMinHeight; }
static float GetVisibleBBoxMinHeight( void ) { return m_flVisibleBBoxMinHeight; }
static C_EnvProjectedTexture *Create( );
private:
inline bool IsBBoxVisible( void );
bool IsBBoxVisible( Vector vecExtentsMin,
Vector vecExtentsMax );
ClientShadowHandle_t m_LightHandle;
bool m_bForceUpdate;
EHANDLE m_hTargetEntity;
#ifdef MAPBASE
bool m_bDontFollowTarget;
#endif
bool m_bState;
bool m_bAlwaysUpdate;
float m_flLightFOV;
#ifdef MAPBASE
float m_flLightHorFOV;
#endif
bool m_bEnableShadows;
bool m_bLightOnlyTarget;
bool m_bLightWorld;
bool m_bCameraSpace;
float m_flBrightnessScale;
color32 m_LightColor;
Vector m_CurrentLinearFloatLightColor;
float m_flCurrentLinearFloatLightAlpha;
#ifdef MAPBASE
float m_flCurrentBrightnessScale;
#endif
float m_flColorTransitionTime;
float m_flAmbient;
float m_flNearZ;
float m_flFarZ;
char m_SpotlightTextureName[ MAX_PATH ];
CTextureReference m_SpotlightTexture;
int m_nSpotlightTextureFrame;
int m_nShadowQuality;
#ifdef MAPBASE
float m_flConstantAtten;
float m_flLinearAtten;
float m_flQuadraticAtten;
float m_flShadowAtten;
float m_flShadowFilter;
bool m_bAlwaysDraw;
//bool m_bProjectedTextureVersion;
#endif
Vector m_vecExtentsMin;
Vector m_vecExtentsMax;
static float m_flVisibleBBoxMinHeight;
};
bool C_EnvProjectedTexture::IsBBoxVisible( void )
{
return IsBBoxVisible( GetAbsOrigin() + m_vecExtentsMin, GetAbsOrigin() + m_vecExtentsMax );
}
#else
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -62,4 +161,6 @@ public:
C_EnvProjectedTexture* GetEnvProjectedTextureList();
#endif
#endif // C_ENVPROJECTEDTEXTURE_H

View File

@ -54,6 +54,9 @@
#include "replay/replay_ragdoll.h"
#include "studio_stats.h"
#include "tier1/callqueue.h"
#ifdef MAPBASE
#include "viewrender.h"
#endif
#ifdef TF_CLIENT_DLL
#include "c_tf_player.h"
@ -258,6 +261,9 @@ LINK_ENTITY_TO_CLASS( client_ragdoll, C_ClientRagdoll );
BEGIN_DATADESC( C_ClientRagdoll )
DEFINE_FIELD( m_bFadeOut, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bImportant, FIELD_BOOLEAN ),
#ifdef MAPBASE
DEFINE_FIELD( m_flForcedRetireTime, FIELD_FLOAT ),
#endif
DEFINE_FIELD( m_iCurrentFriction, FIELD_INTEGER ),
DEFINE_FIELD( m_iMinFriction, FIELD_INTEGER ),
DEFINE_FIELD( m_iMaxFriction, FIELD_INTEGER ),
@ -280,6 +286,94 @@ BEGIN_DATADESC( C_ClientRagdoll )
END_DATADESC()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( C_ClientRagdoll, C_BaseAnimating, "Client-side ragdolls" )
DEFINE_SCRIPTFUNC_NAMED( SUB_Remove, "FadeOut", "Fades out the ragdoll and removes it from the client." )
// TODO: Proper shared ragdoll funcs?
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRagdollObject, "GetRagdollObject", "Gets the ragdoll object of the specified index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRagdollObjectCount, "GetRagdollObjectCount", "Gets the number of ragdoll objects on this ragdoll." )
END_SCRIPTDESC();
ScriptHook_t C_BaseAnimating::g_Hook_OnClientRagdoll;
ScriptHook_t C_BaseAnimating::g_Hook_FireEvent;
//ScriptHook_t C_BaseAnimating::g_Hook_BuildTransformations;
#endif
BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-side" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC_NAMED( ScriptGetPoseParameter, "GetPoseParameter", "Get the specified pose parameter's value" )
#endif
DEFINE_SCRIPTFUNC_NAMED( ScriptSetPoseParameter, "SetPoseParameter", "Set the specified pose parameter to the specified value" )
DEFINE_SCRIPTFUNC( IsSequenceFinished, "Ask whether the main sequence is done playing" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC_NAMED( ScriptLookupAttachment, "LookupAttachment", "Get the named attachement id" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentOrigin, "GetAttachmentOrigin", "Get the attachement id's origin vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentAngles, "GetAttachmentAngles", "Get the attachement id's angles as a p,y,r vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentMatrix, "GetAttachmentMatrix", "Get the attachement id's matrix transform" )
DEFINE_SCRIPTFUNC( LookupBone, "Get the named bone id" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoneTransform, "GetBoneTransform", "Get the transform for the specified bone" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetBoneTransform, "SetBoneTransform", "Set the transform for the specified bone" )
DEFINE_SCRIPTFUNC_NAMED( ScriptAttachEntityToBone, "AttachEntityToBone", "Attaches this entity to the specified target and bone. Also allows for optional local position offset" )
DEFINE_SCRIPTFUNC_NAMED( ScriptRemoveBoneAttachment, "RemoveBoneAttachment", "Removes the specified bone attachment" )
//DEFINE_SCRIPTFUNC( RemoveBoneAttachments, "Removes all bone attachments" )
DEFINE_SCRIPTFUNC( DestroyBoneAttachments, "Destroys all bone attachments" )
DEFINE_SCRIPTFUNC( GetNumBoneAttachments, "Gets the number of bone attachments" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoneAttachment, "GetBoneAttachment", "Gets the specified bone attachment" )
DEFINE_SCRIPTFUNC( SetBodygroup, "Sets a bodygroup")
DEFINE_SCRIPTFUNC( GetBodygroup, "Gets a bodygroup" )
DEFINE_SCRIPTFUNC( GetBodygroupName, "Gets a bodygroup name" )
DEFINE_SCRIPTFUNC( FindBodygroupByName, "Finds a bodygroup by name" )
DEFINE_SCRIPTFUNC( GetBodygroupCount, "Gets the number of models in a bodygroup" )
DEFINE_SCRIPTFUNC( GetNumBodyGroups, "Gets the number of bodygroups" )
DEFINE_SCRIPTFUNC( GetSequence, "Gets the current sequence" )
DEFINE_SCRIPTFUNC( SetSequence, "Sets the current sequence" )
DEFINE_SCRIPTFUNC( SequenceLoops, "Does the current sequence loop?" )
DEFINE_SCRIPTFUNC( LookupSequence, "Gets the index of the specified sequence name" )
DEFINE_SCRIPTFUNC( LookupActivity, "Gets the ID of the specified activity name" )
DEFINE_SCRIPTFUNC( GetSequenceName, "Gets the name of the specified sequence index" )
DEFINE_SCRIPTFUNC( GetSequenceActivityName, "Gets the activity name of the specified sequence index" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceMoveDist, "GetSequenceMoveDist", "Gets the move distance of the specified sequence" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceActivity, "GetSequenceActivity", "Gets the activity ID of the specified sequence index" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectWeightedSequence, "SelectWeightedSequence", "Selects a sequence for the specified activity ID" )
DEFINE_SCRIPTFUNC( GetPlaybackRate, "" )
DEFINE_SCRIPTFUNC( SetPlaybackRate, "" )
DEFINE_SCRIPTFUNC( GetCycle, "" )
DEFINE_SCRIPTFUNC( SetCycle, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSkin, "GetSkin", "Gets the model's skin" )
DEFINE_SCRIPTFUNC( SetSkin, "Sets the model's skin" )
DEFINE_SCRIPTFUNC( GetForceBone, "Gets the entity's force bone, which is used to determine which bone a ragdoll should apply its force to." )
DEFINE_SCRIPTFUNC( SetForceBone, "Sets the entity's force bone, which is used to determine which bone a ragdoll should apply its force to." )
DEFINE_SCRIPTFUNC( GetRagdollForce, "Gets the entity's ragdoll force, which is used to apply velocity to a ragdoll." )
DEFINE_SCRIPTFUNC( SetRagdollForce, "Sets the entity's ragdoll force, which is used to apply velocity to a ragdoll." )
DEFINE_SCRIPTFUNC_NAMED( ScriptBecomeRagdollOnClient, "BecomeRagdollOnClient", "" )
DEFINE_SCRIPTFUNC( IsRagdoll, "" )
BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_OnClientRagdoll, "OnClientRagdoll", FIELD_VOID, "Called when this entity turns into a client-side ragdoll." )
DEFINE_SCRIPTHOOK_PARAM( "ragdoll", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_FireEvent, "FireEvent", FIELD_BOOLEAN, "Called when handling animation events. Return false to cancel base handling." )
DEFINE_SCRIPTHOOK_PARAM( "origin", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "angles", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "event", FIELD_INTEGER )
DEFINE_SCRIPTHOOK_PARAM( "options", FIELD_CSTRING )
END_SCRIPTHOOK()
//BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_BuildTransformations, "BuildTransformations", FIELD_VOID, "Called when building bone transformations. Allows VScript to read/write any bone with Get/SetBoneTransform." )
//END_SCRIPTHOOK()
#endif
END_SCRIPTDESC();
C_ClientRagdoll::C_ClientRagdoll( bool bRestoring )
{
m_iCurrentFriction = 0;
@ -288,6 +382,9 @@ C_ClientRagdoll::C_ClientRagdoll( bool bRestoring )
m_bFadeOut = false;
m_bFadingOut = false;
m_bImportant = false;
#ifdef MAPBASE
m_flForcedRetireTime = 0.0f;
#endif
m_bNoModelParticles = false;
SetClassname("client_ragdoll");
@ -368,7 +465,11 @@ void C_ClientRagdoll::OnRestore( void )
if ( m_bFadeOut == true )
{
#ifdef MAPBASE
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant, m_flForcedRetireTime );
#else
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant );
#endif
}
NoteRagdollCreationTick( this );
@ -646,6 +747,24 @@ void C_ClientRagdoll::Release( void )
BaseClass::Release();
}
#ifdef MAPBASE_VSCRIPT
HSCRIPT C_ClientRagdoll::ScriptGetRagdollObject( int iIndex )
{
if (iIndex < 0 || iIndex > m_pRagdoll->RagdollBoneCount())
{
Warning("%s GetRagdollObject: Index %i not valid (%i objects)\n", GetDebugName(), iIndex, m_pRagdoll->RagdollBoneCount());
return NULL;
}
return g_pScriptVM->RegisterInstance( m_pRagdoll->GetElement(iIndex) );
}
int C_ClientRagdoll::ScriptGetRagdollObjectCount()
{
return m_pRagdoll->RagdollBoneCount();
}
#endif
//-----------------------------------------------------------------------------
// Incremented each frame in InvalidateModelBones. Models compare this value to what it
// was last time they setup their bones to determine if they need to re-setup their bones.
@ -683,6 +802,10 @@ C_BaseAnimating::C_BaseAnimating() :
m_nPrevSequence = -1;
m_nRestoreSequence = -1;
m_pRagdoll = NULL;
m_pClientsideRagdoll = NULL;
#ifdef MAPBASE
m_pServerRagdoll = NULL;
#endif
m_builtRagdoll = false;
m_hitboxBoneCacheHandle = 0;
int i;
@ -1446,6 +1569,115 @@ float C_BaseAnimating::ClampCycle( float flCycle, bool isLooping )
return flCycle;
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Purpose: Returns the world location and world angles of an attachment to vscript caller
// Input : attachment name
// Output : location and angles
//-----------------------------------------------------------------------------
const Vector& C_BaseAnimating::ScriptGetAttachmentOrigin( int iAttachment )
{
static Vector absOrigin;
static QAngle qa;
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
return absOrigin;
}
const Vector& C_BaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
{
static Vector absOrigin;
static Vector absAngles;
static QAngle qa;
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
absAngles.x = qa.x;
absAngles.y = qa.y;
absAngles.z = qa.z;
return absAngles;
}
HSCRIPT C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
{
static matrix3x4_t matrix;
C_BaseAnimating::GetAttachment( iAttachment, matrix );
return g_pScriptVM->RegisterInstance( &matrix );
}
void C_BaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
{
matrix3x4_t *matTransform = HScriptToClass<matrix3x4_t>( hTransform );
if (matTransform == NULL)
return;
GetBoneTransform( iBone, *matTransform );
}
void C_BaseAnimating::ScriptSetBoneTransform( int iBone, HSCRIPT hTransform )
{
matrix3x4_t *matTransform = HScriptToClass<matrix3x4_t>( hTransform );
if (matTransform == NULL)
return;
MatrixCopy( *matTransform, GetBoneForWrite( iBone ) );
}
void C_BaseAnimating::ScriptAttachEntityToBone( HSCRIPT attachTarget, int boneIndexAttached, const Vector &bonePosition, const QAngle &boneAngles )
{
C_BaseEntity *pTarget = ToEnt( attachTarget );
if (pTarget == NULL)
return;
AttachEntityToBone( pTarget->GetBaseAnimating(), boneIndexAttached, bonePosition, boneAngles );
}
void C_BaseAnimating::ScriptRemoveBoneAttachment( HSCRIPT boneAttachment )
{
C_BaseEntity *pTarget = ToEnt( boneAttachment );
if (pTarget == NULL)
return;
RemoveBoneAttachment( pTarget->GetBaseAnimating() );
}
HSCRIPT C_BaseAnimating::ScriptGetBoneAttachment( int i )
{
return ToHScript( GetBoneAttachment( i ) );
}
HSCRIPT C_BaseAnimating::ScriptBecomeRagdollOnClient()
{
C_BaseAnimating *pRagdoll = BecomeRagdollOnClient();
if (!pRagdoll)
return NULL;
return pRagdoll->GetScriptInstance();
}
float C_BaseAnimating::ScriptGetPoseParameter( const char* szName )
{
CStudioHdr* pHdr = GetModelPtr();
if (pHdr == NULL)
return 0.0f;
int iPoseParam = LookupPoseParameter( pHdr, szName );
return GetPoseParameter( iPoseParam );
}
#endif
void C_BaseAnimating::ScriptSetPoseParameter(const char* szName, float fValue)
{
CStudioHdr* pHdr = GetModelPtr();
if (pHdr == NULL)
return;
int iPoseParam = LookupPoseParameter(pHdr, szName);
SetPoseParameter(pHdr, iPoseParam, fValue);
}
void C_BaseAnimating::GetCachedBoneMatrix( int boneIndex, matrix3x4_t &out )
{
@ -1603,7 +1835,23 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater
}
}
#ifdef MAPBASE_VSCRIPT
//if (m_ScriptScope.IsInitialized() && g_Hook_BuildTransformations.CanRunInScope(m_ScriptScope))
//{
// int oldWritableBones = m_BoneAccessor.GetWritableBones();
// int oldReadableBones = m_BoneAccessor.GetReadableBones();
// m_BoneAccessor.SetWritableBones( BONE_USED_BY_ANYTHING );
// m_BoneAccessor.SetReadableBones( BONE_USED_BY_ANYTHING );
//
// // No parameters
// //ScriptVariant_t args[] = {};
// //ScriptVariant_t returnValue;
// g_Hook_BuildTransformations.Call( m_ScriptScope, NULL, NULL /*&returnValue, args*/ );
//
// m_BoneAccessor.SetWritableBones( oldWritableBones );
// m_BoneAccessor.SetReadableBones( oldReadableBones );
//}
#endif
}
//-----------------------------------------------------------------------------
@ -1809,6 +2057,10 @@ CollideType_t C_BaseAnimating::GetCollideType( void )
return BaseClass::GetCollideType();
}
#ifdef MAPBASE
ConVar ai_death_pose_enabled( "ai_death_pose_enabled", "1", FCVAR_NONE, "Toggles the death pose fix code, which cancels sequence transitions while a NPC is ragdolling." );
#endif
//-----------------------------------------------------------------------------
// Purpose: if the active sequence changes, keep track of the previous ones and decay them based on their decay rate
//-----------------------------------------------------------------------------
@ -1825,6 +2077,14 @@ void C_BaseAnimating::MaintainSequenceTransitions( IBoneSetup &boneSetup, float
return;
}
#ifdef MAPBASE
if ( IsAboutToRagdoll() && ai_death_pose_enabled.GetBool() )
{
m_nPrevNewSequenceParity = m_nNewSequenceParity;
return;
}
#endif
m_SequenceTransitioner.CheckForSequenceChange(
boneSetup.GetStudioHdr(),
GetSequence(),
@ -2636,14 +2896,29 @@ void C_BaseAnimating::CalculateIKLocks( float currentTime )
// debugoverlay->AddBoxOverlay( origin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );
float d = (pTarget->est.pos - origin).Length();
Vector vecDelta = (origin - pTarget->est.pos);
float d = vecDelta.Length();
if ( d >= flDist)
continue;
flDist = d;
pTarget->SetPos( origin );
pTarget->SetAngles( angles );
#ifdef MAPBASE
// For blending purposes, IK attachments should obey weight
if ( pTarget->est.flWeight < 1.0f )
{
Quaternion qTarget;
AngleQuaternion( angles, qTarget );
QuaternionSlerp( pTarget->est.q, qTarget, pTarget->est.flWeight, pTarget->est.q );
pTarget->SetPos( pTarget->est.pos + (vecDelta * pTarget->est.flWeight) );
}
else
#endif
{
pTarget->SetPos( origin );
pTarget->SetAngles( angles );
}
// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
}
@ -3191,6 +3466,17 @@ int C_BaseAnimating::DrawModel( int flags )
int drawn = 0;
#ifdef MAPBASE
if (m_iViewHideFlags > 0)
{
// Hide this entity if it's not supposed to be drawn in this view.
if (m_iViewHideFlags & (1 << CurrentViewID()))
{
return 0;
}
}
#endif
#ifdef TF_CLIENT_DLL
ValidateModelIndex();
#endif
@ -3694,7 +3980,11 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
flEventCycle,
gpGlobals->curtime );
}
#ifdef MAPBASE_VSCRIPT
if (ScriptHookFireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ) == false)
continue;
#endif
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
@ -3727,6 +4017,11 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
gpGlobals->curtime );
}
#ifdef MAPBASE_VSCRIPT
if (ScriptHookFireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ) == false)
continue;
#endif
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
}
@ -3734,6 +4029,26 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
m_flPrevEventCycle = flEventCycle;
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseAnimating::ScriptHookFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
if (m_ScriptScope.IsInitialized() && g_Hook_FireEvent.CanRunInScope(m_ScriptScope))
{
// origin, angles, event, options
ScriptVariant_t args[] = { origin, angles, event, options };
ScriptVariant_t returnValue = true;
g_Hook_FireEvent.Call( m_ScriptScope, &returnValue, args );
return returnValue.Get<bool>();
}
return true;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Parses a muzzle effect event and sends it out for drawing
// Input : *options - event parameters in text format
@ -3747,7 +4062,7 @@ bool C_BaseAnimating::DispatchMuzzleEffect( const char *options, bool isFirstPer
int weaponType = 0;
// Get the first parameter
p = nexttoken( token, p, ' ' );
p = nexttoken( token, sizeof( token ), p, ' ' );
// Find the weapon type
if ( token[0] )
@ -3791,7 +4106,7 @@ bool C_BaseAnimating::DispatchMuzzleEffect( const char *options, bool isFirstPer
}
// Get the second parameter
p = nexttoken( token, p, ' ' );
p = nexttoken( token, sizeof( token ), p, ' ' );
int attachmentIndex = -1;
@ -4085,18 +4400,33 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int
// Eject brass
case CL_EVENT_EJECTBRASS1:
if ( m_Attachments.Count() > 0 )
{
if ( MainViewOrigin().DistToSqr( GetAbsOrigin() ) < (256 * 256) )
// Check if we're a weapon, if we belong to the local player, and if the local player is in third person - if all are true, don't do a muzzleflash in this instance, because
// we're using the view models dispatch for smoothness.
if ( dynamic_cast< C_BaseCombatWeapon *>(this) != NULL )
{
Vector attachOrigin;
QAngle attachAngles;
if( GetAttachment( 2, attachOrigin, attachAngles ) )
C_BaseCombatWeapon *pWeapon = dynamic_cast< C_BaseCombatWeapon *>(this);
if ( pWeapon && pWeapon->GetOwner() == C_BasePlayer::GetLocalPlayer() && ::input->CAM_IsThirdPerson() )
break;
}
if ( ( prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) )
break;
if ( m_Attachments.Count() > 0 )
{
if ( MainViewOrigin().DistToSqr( GetAbsOrigin() ) < (256 * 256) )
{
tempents->EjectBrass( attachOrigin, attachAngles, GetAbsAngles(), atoi( options ) );
Vector attachOrigin;
QAngle attachAngles;
if( GetAttachment( 2, attachOrigin, attachAngles ) )
{
tempents->EjectBrass( attachOrigin, attachAngles, GetAbsAngles(), atoi( options ) );
}
}
}
break;
}
break;
@ -4110,6 +4440,36 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int
case AE_NPC_MUZZLEFLASH:
{
// Send out the effect for an NPC
#if defined ( HL2MP ) || defined ( SDK_DLL ) // works for the modified CSS weapons included in the new template sdk.
// HL2MP - Make third person muzzleflashes as reliable as the first person ones
// while in third person the view model dispatches the muzzleflash event - note: the weapon models dispatch them too, but not frequently.
if ( IsViewModel() )
{
C_BasePlayer *pPlayer = ToBasePlayer( dynamic_cast<C_BaseViewModel *>(this)->GetOwner() );
if ( pPlayer && pPlayer == C_BasePlayer::GetLocalPlayer())
{
if ( ::input->CAM_IsThirdPerson() )
{
// Dispatch on the weapon - the player model doesn't have the attachments in hl2mp.
C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
if ( !pWeapon )
break;
pWeapon->DispatchMuzzleEffect( options, false );
break;
}
}
}
// Check if we're a weapon, if we belong to the local player, and if the local player is in third person - if all are true, don't do a muzzleflash in this instance, because
// we're using the view models dispatch for smoothness.
if ( dynamic_cast< C_BaseCombatWeapon *>(this) != NULL )
{
C_BaseCombatWeapon *pWeapon = dynamic_cast< C_BaseCombatWeapon *>(this);
if ( pWeapon && pWeapon->GetOwner() == C_BasePlayer::GetLocalPlayer() && ::input->CAM_IsThirdPerson() )
break;
}
#endif
DispatchMuzzleEffect( options, false );
break;
}
@ -4169,11 +4529,11 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int
const char *p = options;
// Bodygroup Name
p = nexttoken(token, p, ' ');
p = nexttoken( token, sizeof( token ), p, ' ' );
Q_strncpy( szBodygroupName, token, sizeof(szBodygroupName) );
// Get the desired value
p = nexttoken(token, p, ' ');
p = nexttoken( token, sizeof( token ), p, ' ' );
value = token[0] ? atoi( token ) : 0;
int index_ = FindBodygroupByName( szBodygroupName );
@ -4184,6 +4544,22 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int
}
break;
#ifdef MAPBASE
case AE_VSCRIPT_RUN:
{
if (!RunScript( options ))
Warning( "%s failed to run AE_VSCRIPT_RUN on client with \"%s\"\n", GetDebugName(), options );
}
break;
case AE_VSCRIPT_RUN_FILE:
{
if (!RunScriptFile( options ))
Warning( "%s failed to run AE_VSCRIPT_RUN_FILE on client with \"%s\"\n", GetDebugName(), options );
}
break;
#endif
default:
break;
}
@ -4210,13 +4586,13 @@ void C_BaseAnimating::FireObsoleteEvent( const Vector& origin, const QAngle& ang
const char *p = options;
p = nexttoken(token, p, ' ');
p = nexttoken( token, sizeof( token ), p, ' ' );
Q_strncpy( effectFunc, token, sizeof(effectFunc) );
p = nexttoken(token, p, ' ');
p = nexttoken( token, sizeof( token ), p, ' ' );
iAttachment = token[0] ? atoi(token) : -1;
p = nexttoken(token, p, ' ');
p = nexttoken( token, sizeof( token ), p, ' ' );
iParam = token[0] ? atoi(token) : 0;
if ( iAttachment != -1 && m_Attachments.Count() >= iAttachment )
@ -4799,12 +5175,18 @@ bool C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matri
return bSuccess;
}
C_ClientRagdoll *C_BaseAnimating::CreateClientRagdoll( bool bRestoring )
{
//DevMsg( "Creating ragdoll at tick %d\n", gpGlobals->tickcount );
return new C_ClientRagdoll( bRestoring );
}
C_BaseAnimating *C_BaseAnimating::CreateRagdollCopy()
{
//Adrian: We now create a separate entity that becomes this entity's ragdoll.
//That way the server side version of this entity can go away.
//Plus we can hook save/restore code to these ragdolls so they don't fall on restore anymore.
C_ClientRagdoll *pRagdoll = new C_ClientRagdoll( false );
C_ClientRagdoll *pRagdoll = CreateClientRagdoll( false );
if ( pRagdoll == NULL )
return NULL;
@ -4855,6 +5237,14 @@ C_BaseAnimating *C_BaseAnimating::CreateRagdollCopy()
pRagdoll->m_nForceBone = m_nForceBone;
pRagdoll->SetNextClientThink( CLIENT_THINK_ALWAYS );
#ifdef MAPBASE
pRagdoll->m_iViewHideFlags = m_iViewHideFlags;
pRagdoll->m_fadeMinDist = m_fadeMinDist;
pRagdoll->m_fadeMaxDist = m_fadeMaxDist;
pRagdoll->m_flFadeScale = m_flFadeScale;
#endif
pRagdoll->SetModelName( AllocPooledString(pModelName) );
pRagdoll->SetModelScale( GetModelScale() );
return pRagdoll;
@ -4865,8 +5255,8 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
MoveToLastReceivedPosition( true );
GetAbsOrigin();
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
if ( pRagdoll )
m_pClientsideRagdoll = CreateRagdollCopy();
if ( m_pClientsideRagdoll )
{
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
@ -4878,19 +5268,29 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
if ( bInitBoneArrays )
{
bInitAsClient = pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
bInitAsClient = m_pClientsideRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
}
if ( !bInitAsClient || !bInitBoneArrays )
{
Warning( "C_BaseAnimating::BecomeRagdollOnClient failed. pRagdoll:%p bInitBoneArrays:%d bInitAsClient:%d\n",
pRagdoll, bInitBoneArrays, bInitAsClient );
pRagdoll->Release();
m_pClientsideRagdoll, bInitBoneArrays, bInitAsClient );
m_pClientsideRagdoll->Release();
return NULL;
}
#ifdef MAPBASE_VSCRIPT
// Hook for ragdolling
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
{
// ragdoll
ScriptVariant_t args[] = { ScriptVariant_t( m_pClientsideRagdoll->GetScriptInstance() ) };
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
}
#endif
}
return pRagdoll;
return m_pClientsideRagdoll;
}
bool C_BaseAnimating::InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints )
@ -5359,6 +5759,11 @@ void C_BaseAnimating::StudioFrameAdvance()
if ( flNewCycle < 0.0f || flNewCycle >= 1.0f )
{
if (flNewCycle >= 1.0f)
{
ReachedEndOfSequence();
}
if ( IsSequenceLooping( hdr, GetSequence() ) )
{
flNewCycle -= (int)(flNewCycle);

View File

@ -38,6 +38,7 @@ class C_BaseClientShader
*/
class IRagdoll;
class C_ClientRagdoll;
class CIKContext;
class CIKState;
class ConVar;
@ -79,7 +80,7 @@ public:
QAngle m_angRotation;
Vector m_vOriginVelocity;
int m_nLastFramecount : 31;
int m_bAnglesComputed : 1;
bool m_bAnglesComputed : 1;
};
@ -95,6 +96,7 @@ public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
DECLARE_ENT_SCRIPTDESC();
enum
{
@ -166,6 +168,17 @@ public:
virtual void FireObsoleteEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual const char* ModifyEventParticles( const char* token ) { return token; }
#ifdef MAPBASE_VSCRIPT
bool ScriptHookFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
#endif
#if defined ( SDK_DLL ) || defined ( HL2MP )
virtual void ResetEventsParity() { m_nPrevResetEventsParity = -1; } // used to force animation events to function on players so the muzzleflashes and other events occur
// so new functions don't have to be made to parse the models like CSS does in ProcessMuzzleFlashEvent
// allows the multiplayer world weapon models to declare the muzzleflashes, and other effects like sp
// without the need to script it and add extra parsing code.
#endif
// Parses and distributes muzzle flash events
virtual bool DispatchMuzzleEffect( const char *options, bool isFirstPerson );
@ -292,6 +305,7 @@ public:
bool IsRagdoll() const;
bool IsAboutToRagdoll() const;
virtual C_BaseAnimating *BecomeRagdollOnClient();
virtual C_ClientRagdoll *CreateClientRagdoll( bool bRestoring = false );
C_BaseAnimating *CreateRagdollCopy();
bool InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints=false );
void IgniteRagdoll( C_BaseAnimating *pSource );
@ -345,6 +359,8 @@ public:
void ClientSideAnimationChanged();
virtual unsigned int ComputeClientSideAnimationFlags();
virtual void ReachedEndOfSequence() { return; }
virtual void ResetClientsideFrame( void ) { SetCycle( 0 ); }
void SetCycle( float flCycle );
@ -450,6 +466,41 @@ public:
virtual bool IsViewModel() const;
virtual void UpdateOnRemove( void );
#ifdef MAPBASE_VSCRIPT
int ScriptLookupAttachment( const char *pAttachmentName ) { return LookupAttachment( pAttachmentName ); }
const Vector& ScriptGetAttachmentOrigin(int iAttachment);
const Vector& ScriptGetAttachmentAngles(int iAttachment);
HSCRIPT ScriptGetAttachmentMatrix(int iAttachment);
void ScriptGetBoneTransform( int iBone, HSCRIPT hTransform );
void ScriptSetBoneTransform( int iBone, HSCRIPT hTransform );
void ScriptAttachEntityToBone( HSCRIPT attachTarget, int boneIndexAttached, const Vector &bonePosition, const QAngle &boneAngles );
void ScriptRemoveBoneAttachment( HSCRIPT boneAttachment );
HSCRIPT ScriptGetBoneAttachment( int i );
int ScriptGetSequenceActivity( int iSequence ) { return GetSequenceActivity( iSequence ); }
float ScriptGetSequenceMoveDist( int iSequence ) { return GetSequenceMoveDist( GetModelPtr(), iSequence ); }
int ScriptSelectWeightedSequence( int activity ) { return SelectWeightedSequence( (Activity)activity ); }
// For VScript
int ScriptGetSkin() { return GetSkin(); }
void SetSkin( int iSkin ) { m_nSkin = iSkin; }
int GetForceBone() { return m_nForceBone; }
void SetForceBone( int iBone ) { m_nForceBone = iBone; }
const Vector& GetRagdollForce() { return m_vecForce; }
void SetRagdollForce( const Vector &vecForce ) { m_vecForce = vecForce; }
HSCRIPT ScriptBecomeRagdollOnClient();
static ScriptHook_t g_Hook_OnClientRagdoll;
static ScriptHook_t g_Hook_FireEvent;
//static ScriptHook_t g_Hook_BuildTransformations; // UNDONE: Thread access issues
float ScriptGetPoseParameter(const char* szName);
#endif
void ScriptSetPoseParameter(const char* szName, float fValue);
protected:
// View models scale their attachment positions to account for FOV. To get the unmodified
// attachment position (like if you're rendering something else during the view model's DrawModel call),
@ -487,6 +538,10 @@ private:
public:
CRagdoll *m_pRagdoll;
C_BaseAnimating *m_pClientsideRagdoll; // From Alien Swarm SDK
#ifdef MAPBASE
C_BaseAnimating *m_pServerRagdoll; // Not from Alien Swarm SDK (note that this can exist without the entity having died)
#endif
// Texture group to use
int m_nSkin;
@ -660,6 +715,9 @@ public:
C_ClientRagdoll( bool bRestoring = true );
DECLARE_CLASS( C_ClientRagdoll, C_BaseAnimating );
DECLARE_DATADESC();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
// inherited from IPVSNotify
virtual void OnPVSStatusChanged( bool bInPVS );
@ -681,8 +739,17 @@ public:
void FadeOut( void );
virtual float LastBoneChangedTime();
#ifdef MAPBASE_VSCRIPT
HSCRIPT ScriptGetRagdollObject( int iIndex );
int ScriptGetRagdollObjectCount();
#endif
bool m_bFadeOut;
bool m_bImportant;
#ifdef MAPBASE
// Required to save/restore Alien Swarm SDK ragdoll LRU forced fade
float m_flForcedRetireTime;
#endif
float m_flEffectTime;
private:

View File

@ -35,6 +35,10 @@ C_BaseCombatCharacter::C_BaseCombatCharacter()
m_bGlowEnabled = false;
m_bOldGlowEnabled = false;
m_bClientSideGlowEnabled = false;
m_GlowColor.Init( 0.76f, 0.76f, 0.76f );
m_OldGlowColor = m_GlowColor;
m_GlowAlpha = 1.0f;
m_OldGlowAlpha = 1.0f;
#endif // GLOWS_ENABLE
}
@ -67,6 +71,8 @@ void C_BaseCombatCharacter::OnPreDataChanged( DataUpdateType_t updateType )
#ifdef GLOWS_ENABLE
m_bOldGlowEnabled = m_bGlowEnabled;
m_OldGlowColor = m_GlowColor;
m_OldGlowAlpha = m_GlowAlpha;
#endif // GLOWS_ENABLE
}
@ -78,7 +84,7 @@ void C_BaseCombatCharacter::OnDataChanged( DataUpdateType_t updateType )
BaseClass::OnDataChanged( updateType );
#ifdef GLOWS_ENABLE
if ( m_bOldGlowEnabled != m_bGlowEnabled )
if ( m_bOldGlowEnabled != m_bGlowEnabled || m_OldGlowColor != m_GlowColor || m_OldGlowAlpha != m_GlowAlpha )
{
UpdateGlowEffect();
}
@ -107,11 +113,13 @@ void C_BaseCombatCharacter::DoMuzzleFlash()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::GetGlowEffectColor( float *r, float *g, float *b )
void C_BaseCombatCharacter::GetGlowEffectColor( float *r, float *g, float *b, float *a )
{
*r = 0.76f;
*g = 0.76f;
*b = 0.76f;
*r = m_GlowColor.x;
*g = m_GlowColor.y;
*b = m_GlowColor.z;
if (a)
*a = m_GlowAlpha;
}
//-----------------------------------------------------------------------------
@ -144,10 +152,10 @@ void C_BaseCombatCharacter::UpdateGlowEffect( void )
// create a new effect
if ( m_bGlowEnabled || m_bClientSideGlowEnabled )
{
float r, g, b;
GetGlowEffectColor( &r, &g, &b );
float r, g, b, a;
GetGlowEffectColor( &r, &g, &b, &a );
m_pGlowEffect = new CGlowObject( this, Vector( r, g, b ), 1.0, true );
m_pGlowEffect = new CGlowObject( this, Vector( r, g, b ), a, true );
}
}
@ -178,6 +186,8 @@ BEGIN_RECV_TABLE(C_BaseCombatCharacter, DT_BaseCombatCharacter)
RecvPropArray3( RECVINFO_ARRAY(m_hMyWeapons), RecvPropEHandle( RECVINFO( m_hMyWeapons[0] ) ) ),
#ifdef GLOWS_ENABLE
RecvPropBool( RECVINFO( m_bGlowEnabled ) ),
RecvPropVector( RECVINFO( m_GlowColor ) ),
RecvPropFloat( RECVINFO( m_GlowAlpha ) ),
#endif // GLOWS_ENABLE
#ifdef INVASION_CLIENT_DLL
@ -195,3 +205,39 @@ BEGIN_PREDICTION_DATA( C_BaseCombatCharacter )
DEFINE_PRED_ARRAY( m_hMyWeapons, FIELD_EHANDLE, MAX_WEAPONS, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( C_BaseCombatCharacter, C_BaseAnimating, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAmmoCount, "GetAmmoCount", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetActiveWeapon, "GetActiveWeapon", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetWeapon, "GetWeapon", "" )
END_SCRIPTDESC();
int C_BaseCombatCharacter::ScriptGetAmmoCount( int i )
{
Assert( i == -1 || i < MAX_AMMO_SLOTS );
if ( i < 0 || i >= MAX_AMMO_SLOTS )
return NULL;
return GetAmmoCount( i );
}
HSCRIPT C_BaseCombatCharacter::ScriptGetActiveWeapon()
{
return ToHScript( GetActiveWeapon() );
}
HSCRIPT C_BaseCombatCharacter::ScriptGetWeapon( int i )
{
Assert( i >= 0 && i < MAX_WEAPONS );
if ( i < 0 || i >= MAX_WEAPONS )
return NULL;
return ToHScript( GetWeapon(i) );
}
#endif

View File

@ -29,6 +29,9 @@ class C_BaseCombatCharacter : public C_BaseFlex
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
C_BaseCombatCharacter( void );
virtual ~C_BaseCombatCharacter( void );
@ -96,13 +99,19 @@ public:
#ifdef GLOWS_ENABLE
CGlowObject *GetGlowObject( void ){ return m_pGlowEffect; }
virtual void GetGlowEffectColor( float *r, float *g, float *b );
virtual void GetGlowEffectColor( float *r, float *g, float *b, float *a = NULL );
// void EnableGlowEffect( float r, float g, float b );
void SetClientSideGlowEnabled( bool bEnabled ){ m_bClientSideGlowEnabled = bEnabled; UpdateGlowEffect(); }
bool IsClientSideGlowEnabled( void ){ return m_bClientSideGlowEnabled; }
#endif // GLOWS_ENABLE
#ifdef MAPBASE_VSCRIPT
int ScriptGetAmmoCount( int i );
HSCRIPT ScriptGetActiveWeapon();
HSCRIPT ScriptGetWeapon( int i );
#endif
public:
float m_flNextAttack;
@ -129,6 +138,10 @@ private:
bool m_bGlowEnabled; // networked value
bool m_bOldGlowEnabled;
CGlowObject *m_pGlowEffect;
Vector m_GlowColor;
Vector m_OldGlowColor;
float m_GlowAlpha;
int m_OldGlowAlpha;
#endif // GLOWS_ENABLE
private:

View File

@ -16,6 +16,9 @@
#include "tier1/KeyValues.h"
#include "toolframework/itoolframework.h"
#include "toolframework_client.h"
#ifdef MAPBASE
#include "viewrender.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@ -82,6 +85,24 @@ static inline bool ShouldDrawLocalPlayerViewModel( void )
{
#if defined( PORTAL )
return false;
#elif MAPBASE
// We shouldn't draw the viewmodel externally.
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if (localplayer)
{
if (localplayer->m_bDrawPlayerModelExternally)
{
// If this isn't the main view, draw the weapon.
view_id_t viewID = CurrentViewID();
if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)
return false;
}
// Since we already have the local player, check its own ShouldDrawThisPlayer() to avoid extra checks
return !localplayer->ShouldDrawThisPlayer();
}
else
return false;
#else
return !C_BasePlayer::ShouldDrawLocalPlayer();
#endif
@ -104,9 +125,15 @@ void C_BaseCombatWeapon::OnRestore()
int C_BaseCombatWeapon::GetWorldModelIndex( void )
{
#ifdef MAPBASE
int iIndex = GetOwner() ? m_iWorldModelIndex.Get() : m_iDroppedModelIndex.Get();
#else
int iIndex = m_iWorldModelIndex.Get();
#endif
if ( GameRules() )
{
const char *pBaseName = modelinfo->GetModelName( modelinfo->GetModel( m_iWorldModelIndex ) );
const char *pBaseName = modelinfo->GetModelName( modelinfo->GetModel( iIndex ) );
const char *pTranslatedName = GameRules()->TranslateEffectForVisionFilter( "weapons", pBaseName );
if ( pTranslatedName != pBaseName )
@ -115,7 +142,7 @@ int C_BaseCombatWeapon::GetWorldModelIndex( void )
}
}
return m_iWorldModelIndex;
return iIndex;
}
//-----------------------------------------------------------------------------
@ -156,11 +183,8 @@ void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
}
else // weapon carried by other player or not at all
{
int overrideModelIndex = CalcOverrideModelIndex();
if( overrideModelIndex != -1 && overrideModelIndex != GetModelIndex() )
{
SetModelIndex( overrideModelIndex );
}
// See comment below
EnsureCorrectRenderingModel();
}
if ( updateType == DATA_UPDATE_CREATED )
@ -435,6 +459,12 @@ bool C_BaseCombatWeapon::ShouldDraw( void )
if ( !ShouldDrawLocalPlayerViewModel() )
return true;
#ifdef MAPBASE
// We're drawing this in non-main views, handle it in DrawModel()
if ( pLocalPlayer->m_bDrawPlayerModelExternally )
return true;
#endif
// don't draw active weapon if not in some kind of 3rd person mode, the viewmodel will do that
return false;
}
@ -481,15 +511,44 @@ int C_BaseCombatWeapon::DrawModel( int flags )
// check if local player chases owner of this weapon in first person
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer && localplayer->IsObserver() && GetOwner() )
if ( localplayer )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
#ifdef MAPBASE
if (localplayer->m_bDrawPlayerModelExternally)
{
// If this isn't the main view, draw the weapon.
view_id_t viewID = CurrentViewID();
if ( (!localplayer->InFirstPersonView() || (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)) && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)) )
{
// TODO: Is this inefficient?
int nModelIndex = GetModelIndex();
int nWorldModelIndex = GetWorldModelIndex();
if (nModelIndex != nWorldModelIndex)
{
SetModelIndex(nWorldModelIndex);
}
int iDraw = BaseClass::DrawModel(flags);
if (nModelIndex != nWorldModelIndex)
{
SetModelIndex(nModelIndex);
}
return iDraw;
}
}
#endif
if ( localplayer->IsObserver() && GetOwner() )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return false;
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return false;
}
}
return BaseClass::DrawModel( flags );
@ -534,6 +593,36 @@ bool C_BaseCombatWeapon::PredictionErrorShouldResetLatchedForAllPredictables( vo
return BaseClass::PredictionErrorShouldResetLatchedForAllPredictables();
}
//-----------------------------------------------------------------------------
// If the local player is visible (thirdperson mode, tf2 taunts, etc., then make sure that we are using the
// w_ (world) model not the v_ (view) model or else the model can flicker, etc.
// Otherwise, if we're not the local player, always use the world model
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::EnsureCorrectRenderingModel()
{
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer &&
localplayer == GetOwner() &&
!ShouldDrawUsingViewModel() )
{
return;
}
// BRJ 10/14/02
// FIXME: Remove when Yahn's client-side prediction is done
// It's a hacky workaround for the model indices fighting
// (GetRenderBounds uses the model index, which is for the view model)
SetModelIndex( GetWorldModelIndex() );
// Validate our current sequence just in case ( in theory the view and weapon models should have the same sequences for sequences that overlap at least )
CStudioHdr *pStudioHdr = GetModelPtr();
if ( pStudioHdr &&
GetSequence() >= pStudioHdr->GetNumSeq() )
{
SetSequence( 0 );
}
}
//-----------------------------------------------------------------------------
// tool recording
//-----------------------------------------------------------------------------

View File

@ -40,6 +40,14 @@
#include "cdll_bounded_cvars.h"
#include "inetchannelinfo.h"
#include "proto_version.h"
#ifdef MAPBASE
#include "viewrender.h"
#endif
#ifdef MAPBASE_VSCRIPT
#include "vscript_client.h"
#endif
#include "gamestringpool.h"
#ifdef TF_CLIENT_DLL
#include "c_tf_player.h"
@ -424,6 +432,148 @@ BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ),
END_RECV_TABLE()
#ifdef MAPBASE_VSCRIPT
ScriptHook_t C_BaseEntity::g_Hook_UpdateOnRemove;
ScriptHook_t C_BaseEntity::g_Hook_ModifyEmitSoundParams;
#endif
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRight, "GetRightVector", "Get the right vector of the entity" )
DEFINE_SCRIPTFUNC_NAMED( GetTeamNumber, "GetTeam", "Gets this entity's team" )
#endif
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLeft, "GetLeftVector", SCRIPT_HIDE )
DEFINE_SCRIPTFUNC_NAMED( GetTeamNumber, "GetTeamNumber", SCRIPT_HIDE )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetUp, "GetUpVector", "Get the up vector of the entity" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC( ValidateScriptScope, "Ensure that an entity's script scope has been created" )
DEFINE_SCRIPTFUNC( GetOrCreatePrivateScriptScope, "Create and retrieve the script-side data associated with an entity" )
DEFINE_SCRIPTFUNC( GetScriptScope, "Retrieve the script-side data associated with an entity" )
DEFINE_SCRIPTFUNC( GetHealth, "" )
DEFINE_SCRIPTFUNC( GetMaxHealth, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopSound, "StopSound", "Stops a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptEmitSound, "EmitSound", "Plays a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( VScriptPrecacheScriptSound, "PrecacheSoundScript", "Precache a sound for later playing." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSoundDuration, "GetSoundDuration", "Returns float duration of the sound. Takes soundname and optional actormodelname." )
DEFINE_SCRIPTFUNC( GetClassname, "" )
DEFINE_SCRIPTFUNC_NAMED( GetEntityName, "GetName", "" )
DEFINE_SCRIPTFUNC_NAMED( SetAbsOrigin, "SetOrigin", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetForward, "SetForwardVector", "Set the orientation of the entity to have this forward vector" )
DEFINE_SCRIPTFUNC( GetLocalOrigin, "GetLocalOrigin" )
DEFINE_SCRIPTFUNC( SetLocalOrigin, "SetLocalOrigin" )
DEFINE_SCRIPTFUNC( GetLocalAngles, "GetLocalAngles" )
DEFINE_SCRIPTFUNC( SetLocalAngles, "SetLocalAngles" )
DEFINE_SCRIPTFUNC_NAMED( WorldSpaceCenter, "GetCenter", "Get vector to center of object - absolute coords" )
DEFINE_SCRIPTFUNC_NAMED( ScriptEyePosition, "EyePosition", "Get vector to eye position - absolute coords" )
DEFINE_SCRIPTFUNC_NAMED( ScriptEyeAngles, "EyeAngles", "Get eye pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( GetAbsAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( SetAbsAngles, "SetAngles", "Set entity pitch, yaw, roll" )
DEFINE_SCRIPTFUNC( SetSize, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMins, "GetBoundingMins", "Get a vector containing min bounds, centered on object" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMaxs, "GetBoundingMaxs", "Get a vector containing max bounds, centered on object" )
DEFINE_SCRIPTFUNC_NAMED( ScriptEntityToWorldTransform, "EntityToWorldTransform", "Get the entity's transform" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetPhysicsObject, "GetPhysicsObject", "Get the entity's physics object if it has one" )
DEFINE_SCRIPTFUNC_NAMED( ScriptPhysicsInitNormal, "PhysicsInitNormal", "Initializes the entity's physics object with the specified solid type, solid flags, and whether to start asleep" )
DEFINE_SCRIPTFUNC_NAMED( ScriptPhysicsDestroyObject, "PhysicsDestroyObject", "Destroys the entity's physics object" )
DEFINE_SCRIPTFUNC( GetWaterLevel, "Get current level of water submergence" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetParent, "SetParent", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetMoveParent, "GetMoveParent", "If in hierarchy, retrieves the entity's parent" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRootMoveParent, "GetRootMoveParent", "If in hierarchy, walks up the hierarchy to find the root parent" )
DEFINE_SCRIPTFUNC_NAMED( ScriptFirstMoveChild, "FirstMoveChild", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptNextMovePeer, "NextMovePeer", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptFollowEntity, "FollowEntity", "Begin following the specified entity. This makes this entity non-solid, parents it to the target entity, and teleports it to the specified entity's origin. The second parameter is whether or not to use bonemerging while following." )
DEFINE_SCRIPTFUNC( StopFollowingEntity, "Stops following an entity if we're following one." )
DEFINE_SCRIPTFUNC( IsFollowingEntity, "Returns true if this entity is following another entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFollowedEntity, "GetFollowedEntity", "Get the entity we're following." )
DEFINE_SCRIPTFUNC_NAMED( GetScriptOwnerEntity, "GetOwner", "Gets this entity's owner" )
DEFINE_SCRIPTFUNC_NAMED( SetScriptOwnerEntity, "SetOwner", "Sets this entity's owner" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetGroundEntity, "GetGroundEntity", "Get the entity we're standing on." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetGroundEntity, "SetGroundEntity", "Set the entity we're standing on." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorVector, "GetRenderColorVector", "Get the render color as a vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorR, "GetRenderColorR", "Get the render color's R value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorG, "GetRenderColorG", "Get the render color's G value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorB, "GetRenderColorB", "Get the render color's B value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAlpha, "GetRenderAlpha", "Get the render color's alpha value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorVector, "SetRenderColorVector", "Set the render color as a vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColor, "SetRenderColor", "Set the render color" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorR, "SetRenderColorR", "Set the render color's R value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorG, "SetRenderColorG", "Set the render color's G value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorB, "SetRenderColorB", "Set the render color's B value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetAlpha, "SetRenderAlpha", "Set the render color's alpha value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRenderMode, "GetRenderMode", "Get render mode" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetRenderMode, "SetRenderMode", "Set render mode" )
DEFINE_SCRIPTFUNC( GetEffects, "Get effects" )
DEFINE_SCRIPTFUNC( AddEffects, "Add effect(s)" )
DEFINE_SCRIPTFUNC( RemoveEffects, "Remove effect(s)" )
DEFINE_SCRIPTFUNC( ClearEffects, "Clear effect(s)" )
DEFINE_SCRIPTFUNC( SetEffects, "Set effect(s)" )
DEFINE_SCRIPTFUNC( IsEffectActive, "Check if an effect is active" )
DEFINE_SCRIPTFUNC( GetFlags, "Get flags" )
DEFINE_SCRIPTFUNC( AddFlag, "Add flag" )
DEFINE_SCRIPTFUNC( RemoveFlag, "Remove flag" )
DEFINE_SCRIPTFUNC( GetEFlags, "Get Eflags" )
DEFINE_SCRIPTFUNC( AddEFlags, "Add Eflags" )
DEFINE_SCRIPTFUNC( RemoveEFlags, "Remove Eflags" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetMoveType, "GetMoveType", "Get the move type" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetMoveType, "SetMoveType", "Set the move type" )
DEFINE_SCRIPTFUNC( GetCollisionGroup, "Get the collision group" )
DEFINE_SCRIPTFUNC( SetCollisionGroup, "Set the collision group" )
DEFINE_SCRIPTFUNC( GetSolidFlags, "Get solid flags" )
DEFINE_SCRIPTFUNC( AddSolidFlags, "Add solid flags" )
DEFINE_SCRIPTFUNC( RemoveSolidFlags, "Remove solid flags" )
DEFINE_SCRIPTFUNC( IsPlayer, "Returns true if this entity is a player." )
DEFINE_SCRIPTFUNC( IsNPC, "Returns true if this entity is a NPC." )
//DEFINE_SCRIPTFUNC( IsCombatCharacter, "Returns true if this entity is a combat character (player or NPC)." )
DEFINE_SCRIPTFUNC_NAMED( IsBaseCombatWeapon, "IsWeapon", "Returns true if this entity is a weapon." )
DEFINE_SCRIPTFUNC( IsWorld, "Returns true if this entity is the world." )
DEFINE_SCRIPTFUNC( SetModel, "Set client-only entity model" )
//DEFINE_SCRIPTFUNC_NAMED( ScriptInitializeAsClientEntity, "InitializeAsClientEntity", "" )
DEFINE_SCRIPTFUNC_NAMED( Remove, "Destroy", "Remove clientside entity" )
DEFINE_SCRIPTFUNC_NAMED( GetEntityIndex, "entindex", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
DEFINE_SIMPLE_SCRIPTHOOK( C_BaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." )
BEGIN_SCRIPTHOOK( C_BaseEntity::g_Hook_ModifyEmitSoundParams, "ModifyEmitSoundParams", FIELD_VOID, "Called every time a sound is emitted on this entity, allowing for its parameters to be modified." )
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
END_SCRIPTHOOK()
#endif // MAPBASE_VSCRIPT
END_SCRIPTDESC();
#ifndef NO_ENTITY_PREDICTION
BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_PredictableId )
@ -455,6 +605,10 @@ BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
RecvPropInt(RECVINFO(m_nRenderMode)),
RecvPropInt(RECVINFO(m_nRenderFX)),
RecvPropInt(RECVINFO(m_clrRender)),
#ifdef MAPBASE
RecvPropInt(RECVINFO(m_iViewHideFlags)),
RecvPropBool(RECVINFO(m_bDisableFlashlight)),
#endif
RecvPropInt(RECVINFO(m_iTeamNum)),
RecvPropInt(RECVINFO(m_CollisionGroup)),
RecvPropFloat(RECVINFO(m_flElasticity)),
@ -464,6 +618,8 @@ BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
RecvPropInt( RECVINFO( m_iParentAttachment ) ),
RecvPropString(RECVINFO(m_iName)),
RecvPropInt( "movetype", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveType ),
RecvPropInt( "movecollide", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveCollide ),
RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
@ -1120,6 +1276,8 @@ bool C_BaseEntity::Init( int entnum, int iSerialNum )
m_nCreationTick = gpGlobals->tickcount;
m_hScriptInstance = NULL;
return true;
}
@ -1197,6 +1355,7 @@ void C_BaseEntity::Term()
g_Predictables.RemoveFromPredictablesList( GetClientHandle() );
}
// If it's play simulated, remove from simulation list if the player still exists...
if ( IsPlayerSimulated() && C_BasePlayer::GetLocalPlayer() )
{
@ -1233,6 +1392,27 @@ void C_BaseEntity::Term()
RemoveFromLeafSystem();
RemoveFromAimEntsList();
if ( m_hScriptInstance )
{
#ifdef MAPBASE_VSCRIPT
if ( m_ScriptScope.IsInitialized() && g_Hook_UpdateOnRemove.CanRunInScope( m_ScriptScope ) )
{
g_Hook_UpdateOnRemove.Call( m_ScriptScope, NULL, NULL );
}
#endif
g_pScriptVM->RemoveInstance( m_hScriptInstance );
m_hScriptInstance = NULL;
#ifdef MAPBASE_VSCRIPT
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.PurgeAndDeleteElements();
#endif
}
}
@ -1569,6 +1749,11 @@ bool C_BaseEntity::ShouldReceiveProjectedTextures( int flags )
if ( IsEffectActive( EF_NODRAW ) )
return false;
#ifdef MAPBASE
if ( m_bDisableFlashlight )
return false;
#endif
if( flags & SHADOW_FLAGS_FLASHLIGHT )
{
if ( GetRenderMode() > kRenderNormal && GetRenderColor().a == 0 )
@ -2003,6 +2188,17 @@ int C_BaseEntity::DrawModel( int flags )
return drawn;
}
#ifdef MAPBASE
if (m_iViewHideFlags > 0)
{
// Hide this entity if it's not supposed to be drawn in this view.
if (m_iViewHideFlags & (1 << CurrentViewID()))
{
return 0;
}
}
#endif
int modelType = modelinfo->GetModelType( model );
switch ( modelType )
{
@ -4782,9 +4978,15 @@ C_BaseEntity *C_BaseEntity::Instance( int iEnt )
}
#if defined( WIN32 ) && _MSC_VER <= 1920
#if _MSC_VER < 1900
#pragma warning( push )
#include <typeinfo.h>
#pragma warning( pop )
#else
#include <typeinfo>
#endif
#endif
//-----------------------------------------------------------------------------
@ -6017,6 +6219,9 @@ BEGIN_DATADESC_NO_BASE( C_BaseEntity )
DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ),
DEFINE_ARRAY( m_rgflCoordinateFrame, FIELD_FLOAT, 12 ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore)
DEFINE_FIELD( m_fFlags, FIELD_INTEGER ),
#ifdef MAPBASE_VSCRIPT
DEFINE_FIELD( m_iszScriptId, FIELD_STRING ),
#endif
END_DATADESC()
//-----------------------------------------------------------------------------
@ -6475,6 +6680,187 @@ int C_BaseEntity::GetCreationTick() const
return m_nCreationTick;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
HSCRIPT C_BaseEntity::GetScriptInstance()
{
if (!m_hScriptInstance)
{
if (m_iszScriptId == NULL_STRING)
{
char* szName = (char*)stackalloc(1024);
g_pScriptVM->GenerateUniqueKey((m_iName != NULL_STRING) ? STRING(GetEntityName()) : GetClassname(), szName, 1024);
m_iszScriptId = AllocPooledString(szName);
}
m_hScriptInstance = g_pScriptVM->RegisterInstance(GetScriptDesc(), this);
g_pScriptVM->SetInstanceUniqeId(m_hScriptInstance, STRING(m_iszScriptId));
}
return m_hScriptInstance;
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Using my edict, cook up a unique VScript scope that's private to me, and
// persistent.
//-----------------------------------------------------------------------------
bool C_BaseEntity::ValidateScriptScope()
{
if (!m_ScriptScope.IsInitialized())
{
if (scriptmanager == NULL)
{
ExecuteOnce(DevMsg("Cannot execute script because scripting is disabled (-scripting)\n"));
return false;
}
if (g_pScriptVM == NULL)
{
ExecuteOnce(DevMsg(" Cannot execute script because there is no available VM\n"));
return false;
}
// Force instance creation
GetScriptInstance();
EHANDLE hThis;
hThis.Set(this);
bool bResult = m_ScriptScope.Init(STRING(m_iszScriptId));
if (!bResult)
{
DevMsg("%s couldn't create ScriptScope!\n", GetDebugName());
return false;
}
g_pScriptVM->SetValue(m_ScriptScope, "self", GetScriptInstance());
}
return true;
}
//-----------------------------------------------------------------------------
// Returns true if the function was located and called. false otherwise.
// NOTE: Assumes the function takes no parameters at the moment.
//-----------------------------------------------------------------------------
bool C_BaseEntity::CallScriptFunction( const char* pFunctionName, ScriptVariant_t* pFunctionReturn )
{
if (!ValidateScriptScope())
{
DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n");
return false;
}
HSCRIPT hFunc = m_ScriptScope.LookupFunction(pFunctionName);
if (hFunc)
{
m_ScriptScope.Call(hFunc, pFunctionReturn);
m_ScriptScope.ReleaseFunction(hFunc);
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Gets a function handle
//-----------------------------------------------------------------------------
HSCRIPT C_BaseEntity::LookupScriptFunction( const char* pFunctionName )
{
if (!m_ScriptScope.IsInitialized())
{
return NULL;
}
return m_ScriptScope.LookupFunction(pFunctionName);
}
//-----------------------------------------------------------------------------
// Calls and releases a function handle (ASSUMES SCRIPT SCOPE AND FUNCTION ARE VALID!)
//-----------------------------------------------------------------------------
bool C_BaseEntity::CallScriptFunctionHandle( HSCRIPT hFunc, ScriptVariant_t* pFunctionReturn )
{
m_ScriptScope.Call(hFunc, pFunctionReturn);
m_ScriptScope.ReleaseFunction(hFunc);
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Load, compile, and run a script file from disk.
// Input : *pScriptFile - The filename of the script file.
// bUseRootScope - If true, runs this script in the root scope, not
// in this entity's private scope.
//-----------------------------------------------------------------------------
bool C_BaseEntity::RunScriptFile( const char* pScriptFile, bool bUseRootScope )
{
if (!ValidateScriptScope())
{
DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n");
return false;
}
if (bUseRootScope)
{
return VScriptRunScript(pScriptFile);
}
else
{
return VScriptRunScript(pScriptFile, m_ScriptScope, true);
}
}
//-----------------------------------------------------------------------------
// Purpose: Compile and execute a discrete string of script source code
// Input : *pScriptText - A string containing script code to compile and run
//-----------------------------------------------------------------------------
bool C_BaseEntity::RunScript( const char* pScriptText, const char* pDebugFilename )
{
if (!ValidateScriptScope())
{
DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n");
return false;
}
if (m_ScriptScope.Run(pScriptText, pDebugFilename) == SCRIPT_ERROR)
{
DevWarning(" Entity %s encountered an error in RunScript()\n", GetDebugName());
}
return true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
HSCRIPT C_BaseEntity::ScriptGetMoveParent( void )
{
return ToHScript( GetMoveParent() );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
HSCRIPT C_BaseEntity::ScriptGetRootMoveParent()
{
return ToHScript( GetRootMoveParent() );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
HSCRIPT C_BaseEntity::ScriptFirstMoveChild( void )
{
return ToHScript( FirstMoveChild() );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
HSCRIPT C_BaseEntity::ScriptNextMovePeer( void )
{
return ToHScript( NextMovePeer() );
}
#endif
//------------------------------------------------------------------------------
void CC_CL_Find_Ent( const CCommand& args )
{

View File

@ -36,6 +36,9 @@
#include "toolframework/itoolentity.h"
#include "tier0/threadtools.h"
#include "vscript/ivscript.h"
#include "vscript_shared.h"
class C_Team;
class IPhysicsObject;
class IClientVehicle;
@ -159,6 +162,15 @@ struct thinkfunc_t
int m_nLastThinkTick;
};
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
float m_flNextThink;
HSCRIPT m_hfnThink;
unsigned m_iContextHash;
};
#endif
#define CREATE_PREDICTED_ENTITY( className ) \
C_BaseEntity::CreatePredictedEntityByName( className, __FILE__, __LINE__ );
@ -184,6 +196,8 @@ public:
DECLARE_DATADESC();
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
// script description
DECLARE_ENT_SCRIPTDESC();
C_BaseEntity();
virtual ~C_BaseEntity();
@ -257,6 +271,40 @@ public:
string_t m_iClassname;
#ifdef MAPBASE_VSCRIPT
// VSCRIPT
bool ValidateScriptScope();
bool CallScriptFunction( const char* pFunctionName, ScriptVariant_t* pFunctionReturn );
HSCRIPT GetOrCreatePrivateScriptScope();
HSCRIPT GetScriptScope() { return m_ScriptScope; }
HSCRIPT LookupScriptFunction(const char* pFunctionName);
bool CallScriptFunctionHandle(HSCRIPT hFunc, ScriptVariant_t* pFunctionReturn);
bool RunScriptFile( const char* pScriptFile, bool bUseRootScope = false );
bool RunScript( const char* pScriptText, const char* pDebugFilename = "C_BaseEntity::RunScript" );
#endif
HSCRIPT GetScriptOwnerEntity();
virtual void SetScriptOwnerEntity(HSCRIPT pOwner);
#ifdef MAPBASE_VSCRIPT
HSCRIPT ScriptGetGroundEntity();
void ScriptSetGroundEntity( HSCRIPT hGroundEnt );
#endif
HSCRIPT GetScriptInstance();
HSCRIPT m_hScriptInstance;
string_t m_iszScriptId;
#ifdef MAPBASE_VSCRIPT
CScriptScope m_ScriptScope;
static ScriptHook_t g_Hook_UpdateOnRemove;
static ScriptHook_t g_Hook_ModifyEmitSoundParams;
#endif
// IClientUnknown overrides.
public:
@ -358,6 +406,11 @@ public:
bool IsMarkedForDeletion( void );
virtual int entindex( void ) const;
#ifdef MAPBASE_VSCRIPT
// "I don't know why but wrapping entindex() works, while calling it directly crashes."
inline int GetEntityIndex() const { return entindex(); }
#endif
// This works for client-only entities and returns the GetEntryIndex() of the entity's handle,
// so the sound system can get an IClientEntity from it.
@ -863,6 +916,7 @@ public:
void SetSize( const Vector &vecMin, const Vector &vecMax ); // UTIL_SetSize( pev, mins, maxs );
char const *GetClassname( void );
char const *GetDebugName( void );
virtual const char *GetPlayerName() const { return NULL; }
static int PrecacheModel( const char *name );
static bool PrecacheSound( const char *name );
static void PrefetchSound( const char *name );
@ -1005,6 +1059,7 @@ public:
/////////////////
virtual bool IsPlayer( void ) const { return false; };
virtual bool IsBot( void ) const { return ((GetFlags() & FL_FAKECLIENT) == FL_FAKECLIENT) ? true : false; }
virtual bool IsBaseCombatCharacter( void ) { return false; };
virtual C_BaseCombatCharacter *MyCombatCharacterPointer( void ) { return NULL; }
virtual bool IsNPC( void ) { return false; }
@ -1022,6 +1077,11 @@ public:
virtual Vector EyePosition( void );
virtual const QAngle& EyeAngles( void ); // Direction of eyes
virtual const QAngle& LocalEyeAngles( void ); // Direction of eyes in local space (pl.v_angle)
#ifdef MAPBASE
// Created for script_intro and info_player_view_proxy
virtual void GetEyePosition( Vector &vecOrigin, QAngle &angAngles ) { vecOrigin = EyePosition(); angAngles = EyeAngles(); }
#endif
// position of ears
virtual Vector EarPosition( void );
@ -1115,10 +1175,70 @@ public:
bool IsFollowingEntity();
CBaseEntity *GetFollowedEntity();
#ifdef MAPBASE_VSCRIPT
void ScriptFollowEntity( HSCRIPT hBaseEntity, bool bBoneMerge );
HSCRIPT ScriptGetFollowedEntity();
#endif
// For shadows rendering the correct body + sequence...
virtual int GetBody() { return 0; }
virtual int GetSkin() { return 0; }
const Vector& ScriptGetForward(void) { static Vector vecForward; GetVectors(&vecForward, NULL, NULL); return vecForward; }
#ifdef MAPBASE_VSCRIPT
const Vector& ScriptGetRight(void) { static Vector vecRight; GetVectors(NULL, &vecRight, NULL); return vecRight; }
#endif
const Vector& ScriptGetLeft(void) { static Vector vecRight; GetVectors(NULL, &vecRight, NULL); return vecRight; }
const Vector& ScriptGetUp(void) { static Vector vecUp; GetVectors(NULL, NULL, &vecUp); return vecUp; }
#ifdef MAPBASE_VSCRIPT
const char* ScriptGetModelName( void ) const { return STRING(GetModelName()); }
void ScriptStopSound(const char* soundname);
void ScriptEmitSound(const char* soundname);
float ScriptSoundDuration(const char* soundname, const char* actormodel);
void VScriptPrecacheScriptSound(const char* soundname);
const Vector& ScriptEyePosition(void) { static Vector vec; vec = EyePosition(); return vec; }
const QAngle& ScriptEyeAngles(void) { static QAngle ang; ang = EyeAngles(); return ang; }
void ScriptSetForward( const Vector& v ) { QAngle angles; VectorAngles( v, angles ); SetAbsAngles( angles ); }
const Vector& ScriptGetBoundingMins( void ) { return m_Collision.OBBMins(); }
const Vector& ScriptGetBoundingMaxs( void ) { return m_Collision.OBBMaxs(); }
HSCRIPT ScriptEntityToWorldTransform( void );
HSCRIPT ScriptGetPhysicsObject( void );
void ScriptPhysicsInitNormal( int nSolidType, int nSolidFlags, bool createAsleep );
void ScriptPhysicsDestroyObject() { VPhysicsDestroyObject(); }
void ScriptSetParent( HSCRIPT hParent, const char *szAttachment );
HSCRIPT ScriptGetMoveParent( void );
HSCRIPT ScriptGetRootMoveParent();
HSCRIPT ScriptFirstMoveChild( void );
HSCRIPT ScriptNextMovePeer( void );
const Vector& ScriptGetColorVector();
int ScriptGetColorR() { return m_clrRender.GetR(); }
int ScriptGetColorG() { return m_clrRender.GetG(); }
int ScriptGetColorB() { return m_clrRender.GetB(); }
int ScriptGetAlpha() { return m_clrRender.GetA(); }
void ScriptSetColorVector( const Vector& vecColor );
void ScriptSetColor( int r, int g, int b );
void ScriptSetColorR( int iVal ) { SetRenderColorR( iVal ); }
void ScriptSetColorG( int iVal ) { SetRenderColorG( iVal ); }
void ScriptSetColorB( int iVal ) { SetRenderColorB( iVal ); }
void ScriptSetAlpha( int iVal ) { SetRenderColorA( iVal ); }
int ScriptGetRenderMode() { return GetRenderMode(); }
void ScriptSetRenderMode( int nRenderMode ) { SetRenderMode( (RenderMode_t)nRenderMode ); }
int ScriptGetMoveType() { return GetMoveType(); }
void ScriptSetMoveType( int iMoveType ) { SetMoveType( (MoveType_t)iMoveType ); }
#endif
// Stubs on client
void NetworkStateManualMode( bool activate ) { }
void NetworkStateChanged() { }
@ -1159,7 +1279,7 @@ public:
#ifdef _DEBUG
void FunctionCheck( void *pFunction, const char *name );
ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name )
ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, const char *name )
{
//COMPILE_TIME_ASSERT( sizeof(func) == 4 );
m_pfnTouch = func;
@ -1279,6 +1399,7 @@ public:
void SetRenderMode( RenderMode_t nRenderMode, bool bForceUpdate = false );
RenderMode_t GetRenderMode() const;
const char* GetEntityName();
public:
// Determine what entity this corresponds to
@ -1293,6 +1414,11 @@ public:
CNetworkColor32( m_clrRender );
#ifdef MAPBASE
int m_iViewHideFlags;
bool m_bDisableFlashlight;
#endif
private:
// Model for rendering
@ -1432,6 +1558,15 @@ protected:
CUtlVector< thinkfunc_t > m_aThinkFunctions;
int m_iCurrentThinkContext;
#ifdef MAPBASE_VSCRIPT
public:
void ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float time );
void ScriptContextThink();
private:
CUtlVector< scriptthinkfunc_t* > m_ScriptThinkFuncs;
public:
#endif
// Object eye position
Vector m_vecViewOffset;
@ -1660,6 +1795,8 @@ private:
// The owner!
EHANDLE m_hOwnerEntity;
EHANDLE m_hEffectEntity;
char m_iName[MAX_PATH];
// This is a random seed used by the networking code to allow client - side prediction code
// randon number generators to spit out the same random numbers on both sides for a particular
@ -2218,6 +2355,12 @@ inline bool C_BaseEntity::ShouldRecordInTools() const
#endif
}
inline const char *C_BaseEntity::GetEntityName()
{
return m_iName;
}
C_BaseEntity *CreateEntityByName( const char *className );
#endif // C_BASEENTITY_H

View File

@ -1476,7 +1476,7 @@ bool C_BaseFlex::ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool can
// expression -
// duration -
//-----------------------------------------------------------------------------
void C_BaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget, bool bClientSide )
void C_BaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget, bool bClientSide, C_SceneEntity* pSceneEntity)
{
if ( !scene || !event )
{
@ -1501,6 +1501,7 @@ void C_BaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseE
info.m_hTarget = pTarget;
info.m_bStarted = false;
info.m_bClientSide = bClientSide;
info.m_hSceneEntity = pSceneEntity;
if (StartSceneEvent( &info, scene, event, actor, pTarget ))
{

View File

@ -213,7 +213,7 @@ public:
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
// Add the event to the queue for this actor
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false );
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false, C_SceneEntity* pSceneEntity = NULL);
// Remove the event from the queue for this actor
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,460 @@
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client handler for instruction players how to play
//
//=============================================================================//
#ifndef _C_BASELESSON_H_
#define _C_BASELESSON_H_
#include "GameEventListener.h"
#include "hud_locator_target.h"
#define DECLARE_LESSON( _lessonClassName, _baseLessonClassName ) \
typedef _baseLessonClassName BaseClass;\
typedef _lessonClassName ThisClass;\
_lessonClassName( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity )\
: _baseLessonClassName( pchName, bIsDefaultHolder, bIsOpenOpportunity )\
{\
Init();\
}
enum LessonInstanceType
{
LESSON_INSTANCE_MULTIPLE,
LESSON_INSTANCE_SINGLE_OPEN,
LESSON_INSTANCE_FIXED_REPLACE,
LESSON_INSTANCE_SINGLE_ACTIVE,
LESSON_INSTANCE_TYPE_TOTAL
};
// This is used to solve a problem where bots can take the place of a player, where on or the other don't have valid entities on the client at the same time
#define MAX_DELAYED_PLAYER_SWAPS 8
struct delayed_player_swap_t
{
CHandle<C_BaseEntity> *phHandleToChange;
int iNewUserID;
delayed_player_swap_t( void )
{
phHandleToChange = NULL;
iNewUserID = -1;
}
};
abstract_class CBaseLesson : public CGameEventListener
{
public:
CBaseLesson( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity );
virtual ~CBaseLesson( void );
void AddPrerequisite( const char *pchLessonName );
const CGameInstructorSymbol& GetNameSymbol( void ) const { return m_stringName; }
const char * GetName( void ) const { return m_stringName.String(); }
int GetPriority( void ) const { return m_iPriority; }
const char * GetCloseReason( void ) const { return m_stringCloseReason.String(); }
void SetCloseReason( const char *pchReason ) { m_stringCloseReason = pchReason; }
CBaseLesson* GetRoot( void ) const { return m_pRoot; }
void SetRoot( CBaseLesson *pRoot );
const CUtlVector < CBaseLesson * >* GetChildren( void ) const { return &m_OpenOpportunities; }
float GetInitTime( void ) { return m_fInitTime; }
void SetStartTime( void ) { m_fStartTime = gpGlobals->curtime; }
void ResetStartTime( void ) { m_fStartTime = 0.0f; m_bHasPlayedSound = false; }
bool ShouldShowSpew( void );
bool NoPriority( void ) const;
bool IsDefaultHolder( void ) const { return m_bIsDefaultHolder; }
bool IsOpenOpportunity( void ) const { return m_bIsOpenOpportunity; }
bool IsLocked( void ) const;
bool CanOpenWhenDead( void ) const { return m_bCanOpenWhenDead; }
bool IsInstructing( void ) const { return ( m_fStartTime > 0.0f ); }
bool IsLearned( void ) const;
bool PrerequisitesHaveBeenMet( void ) const;
bool IsTimedOut( void );
int InstanceType( void ) const { return m_iInstanceType; }
const CGameInstructorSymbol& GetReplaceKeySymbol( void ) const { return m_stringReplaceKey; }
const char* GetReplaceKey( void ) const { return m_stringReplaceKey.String(); }
int GetFixedInstancesMax( void ) const { return m_iFixedInstancesMax; }
bool ShouldReplaceOnlyWhenStopped( void ) const { return m_bReplaceOnlyWhenStopped; }
void SetInstanceActive( bool bInstanceActive ) { m_bInstanceActive = bInstanceActive; }
bool IsInstanceActive( void ) const { return m_bInstanceActive; }
void ResetDisplaysAndSuccesses( void );
bool IncDisplayCount( void );
bool IncSuccessCount( void );
void SetDisplayCount( int iDisplayCount ) { m_iDisplayCount = iDisplayCount; }
void SetSuccessCount( int iSuccessCount ) { m_iSuccessCount = iSuccessCount; }
int GetDisplayCount( void ) const { return m_iDisplayCount; }
int GetSuccessCount( void ) const { return m_iSuccessCount; }
int GetDisplayLimit( void ) const { return m_iDisplayLimit; }
int GetSuccessLimit( void ) const { return m_iSuccessLimit; }
void Init( void ); // NOT virtual, each constructor calls their own
virtual void InitPrerequisites( void ) {};
virtual void Start( void ) = 0;
virtual void Stop( void ) = 0;
virtual void OnOpen( void ) {};
virtual void Update( void ) {};
virtual void UpdateInactive( void ) {};
virtual bool ShouldDisplay( void ) const { return true; }
virtual bool IsVisible( void ) const { return true; }
virtual bool WasDisplayed( void ) const { return m_bWasDisplayed ? true : false; }
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID ) {}
virtual void TakePlaceOf( CBaseLesson *pLesson );
const char *GetGroup() { return m_szLessonGroup.String(); }
void SetEnabled( bool bEnabled ) { m_bDisabled = !bEnabled; }
protected:
void MarkSucceeded( void );
void CloseOpportunity( const char *pchReason );
bool DoDelayedPlayerSwaps( void ) const;
private:
CBaseLesson *m_pRoot;
CUtlVector < CBaseLesson * > m_OpenOpportunities;
CUtlVector < const CBaseLesson * > m_Prerequisites;
CGameInstructorSymbol m_stringCloseReason;
CGameInstructorSymbol m_stringName;
bool m_bInstanceActive : 1;
bool m_bSuccessCounted : 1;
bool m_bIsDefaultHolder : 1;
bool m_bIsOpenOpportunity : 1;
protected:
LessonInstanceType m_iInstanceType;
int m_iPriority;
CGameInstructorSymbol m_stringReplaceKey;
int m_iFixedInstancesMax;
bool m_bReplaceOnlyWhenStopped;
int m_iTeam;
bool m_bOnlyKeyboard;
bool m_bOnlyGamepad;
int m_iDisplayLimit;
int m_iDisplayCount;
bool m_bWasDisplayed;
int m_iSuccessLimit;
int m_iSuccessCount;
float m_fLockDuration;
float m_fTimeout;
float m_fInitTime;
float m_fStartTime;
float m_fLockTime;
float m_fUpdateInterval;
bool m_bHasPlayedSound;
CGameInstructorSymbol m_szStartSound;
CGameInstructorSymbol m_szLessonGroup;
bool m_bCanOpenWhenDead;
bool m_bBumpWithTimeoutWhenLearned;
bool m_bCanTimeoutWhileInactive;
bool m_bDisabled;
// Right now we can only queue up 4 swaps...
// this number can be increased if more entity handle scripted variables are added
mutable delayed_player_swap_t m_pDelayedPlayerSwap[ MAX_DELAYED_PLAYER_SWAPS ];
mutable int m_iNumDelayedPlayerSwaps;
public:
// Colors for console spew in verbose mode
static Color m_rgbaVerboseHeader;
static Color m_rgbaVerbosePlain;
static Color m_rgbaVerboseName;
static Color m_rgbaVerboseOpen;
static Color m_rgbaVerboseClose;
static Color m_rgbaVerboseSuccess;
static Color m_rgbaVerboseUpdate;
};
class CTextLesson : public CBaseLesson
{
public:
DECLARE_LESSON( CTextLesson, CBaseLesson );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void Start( void );
virtual void Stop( void );
protected:
CGameInstructorSymbol m_szDisplayText;
CGameInstructorSymbol m_szDisplayParamText;
CGameInstructorSymbol m_szBinding;
CGameInstructorSymbol m_szGamepadBinding;
};
class CIconLesson : public CTextLesson
{
public:
DECLARE_LESSON( CIconLesson, CTextLesson );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void Start( void );
virtual void Stop( void );
virtual void Update( void );
virtual void UpdateInactive( void );
virtual bool ShouldDisplay( void ) const;
virtual bool IsVisible( void ) const;
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID );
virtual void TakePlaceOf( CBaseLesson *pLesson );
void SetLocatorBinding( CLocatorTarget * pLocatorTarget );
const char *GetCaptionColorString() { return m_szCaptionColor.String(); }
bool IsPresentComplete( void );
void PresentStart( void );
void PresentEnd( void );
private:
virtual void UpdateLocatorTarget( CLocatorTarget *pLocatorTarget, C_BaseEntity *pIconTarget );
#ifdef MAPBASE
Vector GetIconTargetPosition( C_BaseEntity *pIconTarget );
#endif
protected:
CHandle<C_BaseEntity> m_hIconTarget;
CGameInstructorSymbol m_szVguiTargetName;
CGameInstructorSymbol m_szVguiTargetLookup;
int m_nVguiTargetEdge;
float m_flUpOffset;
float m_flRelativeUpOffset;
float m_fFixedPositionX;
float m_fFixedPositionY;
int m_hLocatorTarget;
int m_iFlags;
float m_fRange;
float m_fCurrentDistance;
float m_fOnScreenStartTime;
float m_fUpdateDistanceTime;
CGameInstructorSymbol m_szOnscreenIcon;
CGameInstructorSymbol m_szOffscreenIcon;
CGameInstructorSymbol m_szCaptionColor;
bool m_bFixedPosition;
bool m_bNoIconTarget;
bool m_bAllowNodrawTarget;
bool m_bVisible;
bool m_bShowWhenOccluded;
bool m_bNoOffscreen;
bool m_bForceCaption;
#ifdef MAPBASE
int m_iIconTargetPos;
enum
{
ICON_TARGET_EYE_POSITION,
ICON_TARGET_ORIGIN,
ICON_TARGET_CENTER,
};
CGameInstructorSymbol m_szHudHint;
#endif
};
enum LessonAction
{
LESSON_ACTION_NONE,
LESSON_ACTION_SCOPE_IN,
LESSON_ACTION_SCOPE_OUT,
LESSON_ACTION_CLOSE,
LESSON_ACTION_SUCCESS,
LESSON_ACTION_LOCK,
LESSON_ACTION_PRESENT_COMPLETE,
LESSON_ACTION_PRESENT_START,
LESSON_ACTION_PRESENT_END,
LESSON_ACTION_REFERENCE_OPEN,
LESSON_ACTION_SET,
LESSON_ACTION_ADD,
LESSON_ACTION_SUBTRACT,
LESSON_ACTION_MULTIPLY,
LESSON_ACTION_IS,
LESSON_ACTION_LESS_THAN,
LESSON_ACTION_HAS_PREFIX,
LESSON_ACTION_HAS_BIT,
LESSON_ACTION_BIT_COUNT_IS,
LESSON_ACTION_BIT_COUNT_LESS_THAN,
LESSON_ACTION_GET_DISTANCE,
LESSON_ACTION_GET_ANGULAR_DISTANCE,
LESSON_ACTION_GET_PLAYER_DISPLAY_NAME,
LESSON_ACTION_CLASSNAME_IS,
LESSON_ACTION_MODELNAME_IS,
LESSON_ACTION_TEAM_IS,
LESSON_ACTION_HEALTH_LESS_THAN,
LESSON_ACTION_HEALTH_PERCENTAGE_LESS_THAN,
LESSON_ACTION_GET_ACTIVE_WEAPON,
LESSON_ACTION_WEAPON_IS,
LESSON_ACTION_WEAPON_HAS,
LESSON_ACTION_GET_ACTIVE_WEAPON_SLOT,
LESSON_ACTION_GET_WEAPON_SLOT,
LESSON_ACTION_GET_WEAPON_IN_SLOT,
LESSON_ACTION_CLIP_PERCENTAGE_LESS_THAN,
LESSON_ACTION_WEAPON_AMMO_LOW,
LESSON_ACTION_WEAPON_AMMO_FULL,
LESSON_ACTION_WEAPON_AMMO_EMPTY,
LESSON_ACTION_WEAPON_CAN_USE,
LESSON_ACTION_USE_TARGET_IS,
LESSON_ACTION_GET_USE_TARGET,
LESSON_ACTION_GET_POTENTIAL_USE_TARGET,
// Enum continued in Mod_LessonAction
LESSON_ACTION_MOD_START,
};
struct LessonElement_t
{
int iVariable;
int iParamVarIndex;
int iAction;
_fieldtypes paramType;
CGameInstructorSymbol szParam;
bool bNot : 1;
bool bOptionalParam : 1;
LessonElement_t( int p_iVariable, int p_iAction, bool p_bNot, bool p_bOptionalParam, const char *pchParam, int p_iParamVarIndex, _fieldtypes p_paramType )
{
iVariable = p_iVariable;
iAction = p_iAction;
bNot = p_bNot;
bOptionalParam = p_bOptionalParam;
szParam = pchParam;
iParamVarIndex = p_iParamVarIndex;
paramType = p_paramType;
}
LessonElement_t( const LessonElement_t &p_LessonElement )
{
iVariable = p_LessonElement.iVariable;
iAction = p_LessonElement.iAction;
bNot = p_LessonElement.bNot;
bOptionalParam = p_LessonElement.bOptionalParam;
szParam = p_LessonElement.szParam;
iParamVarIndex = p_LessonElement.iParamVarIndex;
paramType = p_LessonElement.paramType;
}
};
struct LessonEvent_t
{
CUtlVector< LessonElement_t > elements;
CGameInstructorSymbol szEventName;
};
class CScriptedIconLesson : public CIconLesson
{
public:
DECLARE_LESSON( CScriptedIconLesson, CIconLesson )
virtual ~CScriptedIconLesson( void );
static void PreReadLessonsFromFile( void );
static void Mod_PreReadLessonsFromFile( void );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void InitPrerequisites( void );
virtual void OnOpen( void );
virtual void Update( void );
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID );
virtual void FireGameEvent( IGameEvent *event );
virtual void ProcessOpenGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
virtual void ProcessCloseGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
virtual void ProcessSuccessGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
CUtlVector< LessonEvent_t >& GetOpenEvents( void ) { return m_OpenEvents; }
CUtlVector< LessonEvent_t >& GetCloseEvents( void ) { return m_CloseEvents; }
CUtlVector< LessonEvent_t >& GetSuccessEvents( void ) { return m_SuccessEvents; }
CUtlVector< LessonEvent_t >& GetOnOpenEvents( void ) { return m_OnOpenEvents; }
CUtlVector< LessonEvent_t >& GetUpdateEvents( void ) { return m_UpdateEvents; }
bool ProcessElements( IGameEvent *event, const CUtlVector< LessonElement_t > *pElements );
private:
void InitElementsFromKeys( CUtlVector< LessonElement_t > *pLessonElements, KeyValues *pKey );
void InitElementsFromElements( CUtlVector< LessonElement_t > *pLessonElements, const CUtlVector< LessonElement_t > *pLessonElements2 );
void InitFromKeys( KeyValues *pKey );
bool ProcessElement( IGameEvent *event, const LessonElement_t *pLessonElement, bool bInFailedScope );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, float &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, int &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, bool &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, CGameInstructorSymbol *pchVar, const CGameInstructorSymbol *pchParamName, const char *pchParam );
// Implemented per mod so they can have custom actions
bool Mod_ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam, bool &bModHandled );
LessonEvent_t * AddOpenEvent( void );
LessonEvent_t * AddCloseEvent( void );
LessonEvent_t * AddSuccessEvent( void );
LessonEvent_t * AddOnOpenEvent( void );
LessonEvent_t * AddUpdateEvent( void );
private:
static CUtlDict< int, int > LessonActionMap;
EHANDLE m_hLocalPlayer;
float m_fOutput;
CHandle<C_BaseEntity> m_hEntity1;
CHandle<C_BaseEntity> m_hEntity2;
CGameInstructorSymbol m_szString1;
CGameInstructorSymbol m_szString2;
int m_iInteger1;
int m_iInteger2;
float m_fFloat1;
float m_fFloat2;
CUtlVector< CGameInstructorSymbol > m_PrerequisiteNames;
CUtlVector< LessonEvent_t > m_OpenEvents;
CUtlVector< LessonEvent_t > m_CloseEvents;
CUtlVector< LessonEvent_t > m_SuccessEvents;
CUtlVector< LessonEvent_t > m_OnOpenEvents;
CUtlVector< LessonEvent_t > m_UpdateEvents;
float m_fUpdateEventTime;
CScriptedIconLesson *m_pDefaultHolder;
int m_iScopeDepth;
// Need this to get offsets to scripted variables
friend class LessonVariableInfo;
friend int LessonActionFromString( const char *pchName );
};
#endif // _C_BASELESSON_H_

View File

@ -58,6 +58,10 @@
#include "econ_wearable.h"
#endif
#ifdef MAPBASE
#include "viewrender.h"
#endif
// NVNT haptics system interface
#include "haptics/ihaptics.h"
@ -136,6 +140,16 @@ void RecvProxy_LocalVelocityZ( const CRecvProxyData *pData, void *pStruct, void
void RecvProxy_ObserverTarget( const CRecvProxyData *pData, void *pStruct, void *pOut );
void RecvProxy_ObserverMode ( const CRecvProxyData *pData, void *pStruct, void *pOut );
#ifdef MAPBASE
// Needs to shift bits back
void RecvProxy_ShiftPlayerSpawnflags( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_BasePlayer *pPlayer = (C_BasePlayer *)pStruct;
pPlayer->m_spawnflags = (pData->m_Value.m_Int) << 16;
}
#endif
// -------------------------------------------------------------------------------- //
// RecvTable for CPlayerState.
// -------------------------------------------------------------------------------- //
@ -184,6 +198,11 @@ BEGIN_RECV_TABLE_NOBASE( CPlayerLocalData, DT_Local )
// 3d skybox data
RecvPropInt(RECVINFO(m_skybox3d.scale)),
RecvPropVector(RECVINFO(m_skybox3d.origin)),
#ifdef MAPBASE
RecvPropVector(RECVINFO(m_skybox3d.angles)),
RecvPropEHandle(RECVINFO(m_skybox3d.skycamera)),
RecvPropInt( RECVINFO( m_skybox3d.skycolor ), 0, RecvProxy_IntToColor32 ),
#endif
RecvPropInt(RECVINFO(m_skybox3d.area)),
// 3d skybox fog data
@ -196,6 +215,9 @@ BEGIN_RECV_TABLE_NOBASE( CPlayerLocalData, DT_Local )
RecvPropFloat( RECVINFO( m_skybox3d.fog.start ) ),
RecvPropFloat( RECVINFO( m_skybox3d.fog.end ) ),
RecvPropFloat( RECVINFO( m_skybox3d.fog.maxdensity ) ),
#ifdef MAPBASE
RecvPropFloat( RECVINFO( m_skybox3d.fog.farz ) ),
#endif
// fog data
RecvPropEHandle( RECVINFO( m_PlayerFog.m_hCtrl ) ),
@ -214,6 +236,14 @@ BEGIN_RECV_TABLE_NOBASE( CPlayerLocalData, DT_Local )
RecvPropInt( RECVINFO( m_audio.entIndex ) ),
RecvPropString( RECVINFO( m_szScriptOverlayMaterial ) ),
//Tony; tonemap stuff! -- TODO! Optimize this with bit sizes from env_tonemap_controller.
RecvPropFloat ( RECVINFO( m_TonemapParams.m_flTonemapScale ) ),
RecvPropFloat ( RECVINFO( m_TonemapParams.m_flTonemapRate ) ),
RecvPropFloat ( RECVINFO( m_TonemapParams.m_flBloomScale ) ),
RecvPropFloat ( RECVINFO( m_TonemapParams.m_flAutoExposureMin ) ),
RecvPropFloat ( RECVINFO( m_TonemapParams.m_flAutoExposureMax ) ),
END_RECV_TABLE()
// -------------------------------------------------------------------------------- //
@ -256,6 +286,15 @@ END_RECV_TABLE()
RecvPropInt ( RECVINFO( m_nWaterLevel ) ),
RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )),
#ifdef MAPBASE
// Transmitted from the server for internal player spawnflags.
// See baseplayer_shared.h for more details.
RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ),
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
RecvPropBool ( RECVINFO( m_bInTriggerFall ) ),
#endif
END_RECV_TABLE()
@ -304,6 +343,11 @@ END_RECV_TABLE()
RecvPropString( RECVINFO(m_szLastPlaceName) ),
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropEHandle( RECVINFO( m_hPostProcessCtrl ) ), // Send to everybody - for spectating
RecvPropEHandle( RECVINFO( m_hColorCorrectionCtrl ) ), // Send to everybody - for spectating
#endif
#if defined USES_ECON_ITEMS
RecvPropUtlVector( RECVINFO_UTLVECTOR( m_hMyWearables ), MAX_WEARABLES_SENT_FROM_SERVER, RecvPropEHandle(NULL, 0, 0) ),
#endif
@ -410,7 +454,10 @@ BEGIN_PREDICTION_DATA( C_BasePlayer )
END_PREDICTION_DATA()
// link this in each derived player class, like the server!!
#if 0
LINK_ENTITY_TO_CLASS( player, C_BasePlayer );
#endif
// -------------------------------------------------------------------------------- //
// Functions.
@ -464,6 +511,13 @@ C_BasePlayer::~C_BasePlayer()
if ( this == s_pLocalPlayer )
{
s_pLocalPlayer = NULL;
#ifdef MAPBASE_VSCRIPT
if ( g_pScriptVM )
{
g_pScriptVM->SetValue( "player", SCRIPT_VARIANT_NULL );
}
#endif
}
delete m_pFlashlight;
@ -834,6 +888,14 @@ void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType )
// changed level, which would cause the snd_soundmixer to be left modified.
ConVar *pVar = (ConVar *)cvar->FindVar( "snd_soundmixer" );
pVar->Revert();
#ifdef MAPBASE_VSCRIPT
// Moved here from LevelInitPostEntity, which is executed before local player is spawned.
if ( g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
#endif
}
}
@ -996,6 +1058,16 @@ void C_BasePlayer::OnRestore()
input->ClearInputButton( IN_ATTACK | IN_ATTACK2 );
// GetButtonBits() has to be called for the above to take effect
input->GetButtonBits( 0 );
#ifdef MAPBASE_VSCRIPT
// HACK: (03/25/09) Then the player goes across a transition it doesn't spawn and register
// it's instance. We're hacking around this for now, but this will go away when we get around to
// having entities cross transitions and keep their script state.
if ( g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
#endif
}
// For ammo history icons to current value so they don't flash on level transtions
@ -1105,14 +1177,32 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
// If we're in vgui mode *and* we're holding down mouse buttons,
// stay in vgui mode even if we're outside the screen bounds
#ifdef VGUI_SCREEN_FIX
if (m_pCurrentVguiScreen.Get() && (pCmd->buttons & (IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT)))
{
SetVGuiScreenButtonState( m_pCurrentVguiScreen.Get(), pCmd->buttons );
// Kill all attack inputs if we're in vgui screen mode
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT);
#ifdef MAPBASE
pCmd->buttons |= IN_VGUIMODE;
#endif // MAPBASE
return;
}
#else
if (m_pCurrentVguiScreen.Get() && (pCmd->buttons & (IN_ATTACK | IN_ATTACK2)) )
{
SetVGuiScreenButtonState( m_pCurrentVguiScreen.Get(), pCmd->buttons );
// Kill all attack inputs if we're in vgui screen mode
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
#ifdef MAPBASE
pCmd->buttons &= ~(IN_USE | IN_ATTACK3);
pCmd->buttons |= IN_VGUIMODE;
#endif // MAPBASE
return;
}
#endif
// We're not in vgui input mode if we're moving, or have hit a key
// that will make us move...
@ -1174,6 +1264,10 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
// Kill all attack inputs if we're in vgui screen mode
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
#ifdef MAPBASE
pCmd->buttons &= ~(IN_USE | IN_ATTACK3);
pCmd->buttons |= IN_VGUIMODE;
#endif // MAPBASE
}
}
@ -1234,7 +1328,12 @@ bool C_BasePlayer::CreateMove( float flInputSampleTime, CUserCmd *pCmd )
m_vecOldViewAngles = pCmd->viewangles;
// Check to see if we're in vgui input mode...
#ifdef VGUI_SCREEN_FIX
if(pCmd->buttons & IN_VALIDVGUIINPUT)
DetermineVguiInputMode( pCmd );
#else
DetermineVguiInputMode( pCmd );
#endif
return true;
}
@ -1330,6 +1429,10 @@ void C_BasePlayer::AddEntity( void )
// Add in lighting effects
CreateLightEffects();
#ifdef MAPBASE
SetLocalAnglesDim( X_INDEX, 0 );
#endif
}
extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
@ -1436,11 +1539,35 @@ bool C_BasePlayer::ShouldInterpolate()
bool C_BasePlayer::ShouldDraw()
{
#ifdef MAPBASE
// We have to "always draw" a player with m_bDrawPlayerModelExternally in order to show up in whatever rendering list all of the views use,
// but we can't put this in ShouldDrawThisPlayer() because we would have no way of knowing if it stomps the other checks that draw the player model anyway.
// As a result, we have to put it here in the central ShouldDraw() function. DrawModel() makes sure we only draw in non-main views and nothing's drawing the model anyway.
return (ShouldDrawThisPlayer() || m_bDrawPlayerModelExternally) && BaseClass::ShouldDraw();
#else
return ShouldDrawThisPlayer() && BaseClass::ShouldDraw();
#endif
}
int C_BasePlayer::DrawModel( int flags )
{
#ifdef MAPBASE
if (m_bDrawPlayerModelExternally)
{
// Draw the player in any view except the main or "intro" view, both of which are default first-person views.
// HACKHACK: Also don't draw in shadow depth textures if the player's flashlight is on, as that causes the playermodel to block it.
view_id_t viewID = CurrentViewID();
if (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || (viewID == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT)))
{
// Make sure the player model wouldn't draw anyway...
if (!ShouldDrawThisPlayer())
return 0;
}
return BaseClass::DrawModel( flags );
}
#endif
#ifndef PORTAL
// In Portal this check is already performed as part of
// C_Portal_Player::DrawModel()
@ -1449,9 +1576,42 @@ int C_BasePlayer::DrawModel( int flags )
return 0;
}
#endif
return BaseClass::DrawModel( flags );
}
#ifdef MAPBASE
ConVar cl_player_allow_thirdperson_projtex( "cl_player_allow_thirdperson_projtex", "1", FCVAR_NONE, "Allows players to receive projected textures if they're non-local or in third person." );
ConVar cl_player_allow_thirdperson_rttshadows( "cl_player_allow_thirdperson_rttshadows", "0", FCVAR_NONE, "Allows players to cast RTT shadows if they're non-local or in third person." );
ConVar cl_player_allow_firstperson_projtex( "cl_player_allow_firstperson_projtex", "1", FCVAR_NONE, "Allows players to receive projected textures even if they're in first person." );
ConVar cl_player_allow_firstperson_rttshadows( "cl_player_allow_firstperson_rttshadows", "0", FCVAR_NONE, "Allows players to cast RTT shadows even if they're in first person." );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ShadowType_t C_BasePlayer::ShadowCastType()
{
if ( (!IsLocalPlayer() || ShouldDraw()) ? !cl_player_allow_thirdperson_rttshadows.GetBool() : !cl_player_allow_firstperson_rttshadows.GetBool() )
return SHADOWS_NONE;
if ( !IsVisible() )
return SHADOWS_NONE;
return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
}
//-----------------------------------------------------------------------------
// Should this object receive shadows?
//-----------------------------------------------------------------------------
bool C_BasePlayer::ShouldReceiveProjectedTextures( int flags )
{
if ( (!IsLocalPlayer() || ShouldDraw()) ? !cl_player_allow_thirdperson_projtex.GetBool() : !cl_player_allow_firstperson_projtex.GetBool() )
return false;
return BaseClass::ShouldReceiveProjectedTextures( flags );
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -1573,7 +1733,14 @@ void C_BasePlayer::CalcChaseCamView(Vector& eyeOrigin, QAngle& eyeAngles, float&
}
}
if ( target && !target->IsPlayer() && target->IsNextBot() )
// SDK TODO
if ( target && target->IsBaseTrain() )
{
// if this is a train, we want to be back a little further so we can see more of it
flMaxDistance *= 2.5f;
m_flObserverChaseDistance = flMaxDistance;
}
else if ( target && !target->IsPlayer() && target->IsNextBot() )
{
// if this is a boss, we want to be back a little further so we can see more of it
flMaxDistance *= 2.5f;
@ -1906,6 +2073,12 @@ void C_BasePlayer::ThirdPersonSwitch( bool bThirdperson )
}
}
}
else
{
CBaseCombatWeapon *pWeapon = GetActiveWeapon();
if ( pWeapon )
pWeapon->ThirdPersonSwitch( bThirdperson );
}
}
@ -2869,6 +3042,24 @@ void C_BasePlayer::UpdateFogBlend( void )
}
}
#ifdef MAPBASE // From Alien Swarm SDK
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
C_PostProcessController* C_BasePlayer::GetActivePostProcessController() const
{
return m_hPostProcessCtrl.Get();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
C_ColorCorrection* C_BasePlayer::GetActiveColorCorrection() const
{
return m_hColorCorrectionCtrl.Get();
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

View File

@ -23,6 +23,10 @@
#include "hintsystem.h"
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "c_env_fog_controller.h"
#ifdef MAPBASE // From Alien Swarm SDK
#include "c_postprocesscontroller.h"
#include "c_colorcorrection.h"
#endif
#include "igameevents.h"
#include "GameEventListener.h"
@ -37,6 +41,7 @@ class C_BaseViewModel;
class C_FuncLadder;
class CFlashlightEffect;
class C_EconWearable;
class C_PostProcessController;
extern int g_nKillCamMode;
extern int g_nKillCamTarget1;
@ -183,7 +188,7 @@ public:
// Flashlight
void Flashlight( void );
void UpdateFlashlight( void );
virtual void UpdateFlashlight( void );
// Weapon selection code
virtual bool IsAllowedToSwitchWeapons( void ) { return !IsObserver(); }
@ -202,6 +207,11 @@ public:
void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; }
float MaxSpeed() const { return m_flMaxspeed; }
#ifdef MAPBASE
// See c_baseplayer.cpp
virtual ShadowType_t ShadowCastType();
virtual bool ShouldReceiveProjectedTextures( int flags );
#else
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }
@ -209,6 +219,7 @@ public:
{
return false;
}
#endif
bool IsLocalPlayer( void ) const;
@ -380,6 +391,11 @@ public:
void UpdateFogController( void );
void UpdateFogBlend( void );
#ifdef MAPBASE // From Alien Swarm SDK
C_PostProcessController* GetActivePostProcessController() const;
C_ColorCorrection* GetActiveColorCorrection() const;
#endif
float GetFOVTime( void ){ return m_flFOVTime; }
virtual void OnAchievementAchieved( int iAchievement ) {}
@ -447,20 +463,35 @@ public:
float m_flConstraintWidth;
float m_flConstraintSpeedFactor;
#ifdef MAPBASE
// Transmitted from the server for internal player spawnflags.
// See baseplayer_shared.h for more details.
int m_spawnflags;
inline bool HasSpawnFlags( int flags ) { return (m_spawnflags & flags) != 0; }
inline void RemoveSpawnFlags( int flags ) { m_spawnflags &= ~flags; }
inline void AddSpawnFlags( int flags ) { m_spawnflags |= flags; }
// Allows the player's model to draw on non-main views, like monitors or mirrors.
bool m_bDrawPlayerModelExternally;
bool m_bInTriggerFall;
#endif
protected:
void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcVehicleView(IClientVehicle *pVehicle, Vector& eyeOrigin, QAngle& eyeAngles,
float& zNear, float& zFar, float& fov );
//Tony; made all of these virtual so mods can override.
virtual void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual void CalcVehicleView(IClientVehicle *pVehicle, Vector& eyeOrigin, QAngle& eyeAngles, float& zNear, float& zFar, float& fov );
virtual void CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual Vector GetChaseCamViewOffset( CBaseEntity *target );
void CalcChaseCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual void CalcChaseCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual void CalcInEyeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual float GetDeathCamInterpolationTime();
virtual void CalcDeathCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcRoamingView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov);
virtual void CalcRoamingView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov);
virtual void CalcFreezeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
// Check to see if we're in vgui input mode...
@ -633,6 +664,11 @@ private:
// One for left and one for right side of step
StepSoundCache_t m_StepSoundCache[ 2 ];
#ifdef MAPBASE // From Alien Swarm SDK
CNetworkHandle( C_PostProcessController, m_hPostProcessCtrl ); // active postprocessing controller
CNetworkHandle( C_ColorCorrection, m_hColorCorrectionCtrl ); // active FXVolume color correction
#endif
public:
const char *GetLastKnownPlaceName( void ) const { return m_szLastPlaceName; } // return the last nav place name the player occupied

View File

@ -35,7 +35,7 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef CSTRIKE_DLL
#if defined(CSTRIKE_DLL) || defined (MAPBASE)
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
#endif
@ -197,7 +197,7 @@ bool C_BaseViewModel::Interpolate( float currentTime )
bool C_BaseViewModel::ShouldFlipViewModel()
{
#ifdef CSTRIKE_DLL
#if defined(CSTRIKE_DLL) || defined (MAPBASE)
// If cl_righthand is set, then we want them all right-handed.
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
if ( pWeapon )

View File

@ -6,6 +6,7 @@
//===========================================================================//
#include "cbase.h"
#include "c_colorcorrection.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "colorcorrectionmgr.h"
@ -17,45 +18,27 @@
static ConVar mat_colcorrection_disableentities( "mat_colcorrection_disableentities", "0", FCVAR_NONE, "Disable map color-correction entities" );
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ColorCorrection();
virtual ~C_ColorCorrection();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink();
private:
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_flCurWeight;
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled;
ClientCCHandle_t m_CCHandle;
};
#ifdef MAPBASE // From Alien Swarm SDK
static ConVar mat_colcorrection_forceentitiesclientside( "mat_colcorrection_forceentitiesclientside", "0", FCVAR_CHEAT, "Forces color correction entities to be updated on the client" );
#endif
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrection, DT_ColorCorrection, CColorCorrection)
RecvPropVector( RECVINFO(m_vecOrigin) ),
RecvPropFloat( RECVINFO(m_minFalloff) ),
RecvPropFloat( RECVINFO(m_maxFalloff) ),
RecvPropFloat( RECVINFO(m_flCurWeight) ),
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropFloat( RECVINFO(m_flMaxWeight) ),
RecvPropFloat( RECVINFO(m_flFadeInDuration) ),
RecvPropFloat( RECVINFO(m_flFadeOutDuration) ),
#endif
RecvPropString( RECVINFO(m_netLookupFilename) ),
RecvPropBool( RECVINFO(m_bEnabled) ),
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropBool( RECVINFO(m_bMaster) ),
RecvPropBool( RECVINFO(m_bClientSide) ),
RecvPropBool( RECVINFO(m_bExclusive) )
#endif
END_RECV_TABLE()
@ -65,14 +48,43 @@ END_RECV_TABLE()
//------------------------------------------------------------------------------
C_ColorCorrection::C_ColorCorrection()
{
#ifdef MAPBASE // From Alien Swarm SDK
m_minFalloff = -1.0f;
m_maxFalloff = -1.0f;
m_flFadeInDuration = 0.0f;
m_flFadeOutDuration = 0.0f;
m_flCurWeight = 0.0f;
m_flMaxWeight = 1.0f;
m_netLookupFilename[0] = '\0';
m_bEnabled = false;
m_bMaster = false;
m_bExclusive = false;
#endif
m_CCHandle = INVALID_CLIENT_CCHANDLE;
#ifdef MAPBASE // From Alien Swarm SDK
m_bFadingIn = false;
m_flFadeStartWeight = 0.0f;
m_flFadeStartTime = 0.0f;
m_flFadeDuration = 0.0f;
#endif
}
C_ColorCorrection::~C_ColorCorrection()
{
#ifdef MAPBASE // From Alien Swarm SDK
g_pColorCorrectionMgr->RemoveColorCorrectionEntity( this, m_CCHandle );
#else
g_pColorCorrectionMgr->RemoveColorCorrection( m_CCHandle );
#endif
}
#ifdef MAPBASE // From Alien Swarm SDK
bool C_ColorCorrection::IsClientSide() const
{
return m_bClientSide || mat_colcorrection_forceentitiesclientside.GetBool();
}
#endif
//------------------------------------------------------------------------------
// Purpose :
@ -87,11 +99,21 @@ void C_ColorCorrection::OnDataChanged(DataUpdateType_t updateType)
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
#ifdef MAPBASE // From Alien Swarm SDK
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_netLookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionEntity( this, name, m_netLookupFilename );
#else
char filename[MAX_PATH];
Q_strncpy( filename, m_netLookupFilename, MAX_PATH );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrection( filename );
SetNextClientThink( ( m_CCHandle != INVALID_CLIENT_CCHANDLE ) ? CLIENT_THINK_ALWAYS : CLIENT_THINK_NEVER );
#endif
}
}
}
@ -104,6 +126,129 @@ bool C_ColorCorrection::ShouldDraw()
return false;
}
#ifdef MAPBASE // From Alien Swarm SDK
void C_ColorCorrection::Update( C_BasePlayer *pPlayer, float ccScale )
{
Assert( m_CCHandle != INVALID_CLIENT_CCHANDLE );
if ( mat_colcorrection_disableentities.GetInt() )
{
// Allow the colorcorrectionui panel (or user) to turn off color-correction entities
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
// fade weight on client
if ( IsClientSide() )
{
m_flCurWeight = Lerp( GetFadeRatio(), m_flFadeStartWeight, m_bFadingIn ? m_flMaxWeight : 0.0f );
}
if( !m_bEnabled && m_flCurWeight == 0.0f )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
Vector playerOrigin = pPlayer->GetAbsOrigin();
float weight = 0;
if ( ( m_minFalloff != -1 ) && ( m_maxFalloff != -1 ) && m_minFalloff != m_maxFalloff )
{
float dist = (playerOrigin - m_vecOrigin).Length();
weight = (dist-m_minFalloff) / (m_maxFalloff-m_minFalloff);
if ( weight<0.0f ) weight = 0.0f;
if ( weight>1.0f ) weight = 1.0f;
}
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_flCurWeight * ( 1.0 - weight ) * ccScale, m_bExclusive );
}
void C_ColorCorrection::EnableOnClient( bool bEnable, bool bSkipFade )
{
if ( !IsClientSide() )
{
return;
}
m_bFadingIn = bEnable;
// initialize countdown timer
m_flFadeStartWeight = m_flCurWeight;
float flFadeTimeScale = 1.0f;
if ( m_flMaxWeight != 0.0f )
{
flFadeTimeScale = m_flCurWeight / m_flMaxWeight;
}
if ( m_bFadingIn )
{
flFadeTimeScale = 1.0f - flFadeTimeScale;
}
if ( bSkipFade )
{
flFadeTimeScale = 0.0f;
}
StartFade( flFadeTimeScale * ( m_bFadingIn ? m_flFadeInDuration : m_flFadeOutDuration ) );
// update the clientside weight once here, in case the fade duration is 0
m_flCurWeight = Lerp( GetFadeRatio(), m_flFadeStartWeight, m_bFadingIn ? m_flMaxWeight : 0.0f );
}
Vector C_ColorCorrection::GetOrigin()
{
return m_vecOrigin;
}
float C_ColorCorrection::GetMinFalloff()
{
return m_minFalloff;
}
float C_ColorCorrection::GetMaxFalloff()
{
return m_maxFalloff;
}
void C_ColorCorrection::SetWeight( float fWeight )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, fWeight, false );
}
void C_ColorCorrection::StartFade( float flDuration )
{
m_flFadeStartTime = gpGlobals->curtime;
m_flFadeDuration = MAX( flDuration, 0.0f );
}
float C_ColorCorrection::GetFadeRatio() const
{
float flRatio = 1.0f;
if ( m_flFadeDuration != 0.0f )
{
flRatio = ( gpGlobals->curtime - m_flFadeStartTime ) / m_flFadeDuration;
flRatio = clamp( flRatio, 0.0f, 1.0f );
}
return flRatio;
}
bool C_ColorCorrection::IsFadeTimeElapsed() const
{
return ( ( gpGlobals->curtime - m_flFadeStartTime ) > m_flFadeDuration ) ||
( ( gpGlobals->curtime - m_flFadeStartTime ) < 0.0f );
}
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}
#else
void C_ColorCorrection::ClientThink()
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
@ -141,6 +286,7 @@ void C_ColorCorrection::ClientThink()
BaseClass::ClientThink();
}
#endif

View File

@ -0,0 +1,88 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Note that this header exists in the Alien Swarm SDK, but not in stock Source SDK 2013.
// Although technically a new Mapbase file, it only serves to move otherwise identical code,
// so most code and repo conventions will pretend it was always there.
//
// --------------------------------------------------------------------
//
// Purpose: Color correction entity with simple radial falloff
//
//=============================================================================//
#ifndef C_COLORCORRECTION_H
#define C_COLORCORRECTION_H
#ifdef _WIN32
#pragma once
#endif
#include "colorcorrectionmgr.h"
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ColorCorrection();
virtual ~C_ColorCorrection();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
#ifdef MAPBASE // From Alien Swarm SDK
virtual void Update(C_BasePlayer *pPlayer, float ccScale);
bool IsMaster() const { return m_bMaster; }
bool IsClientSide() const;
bool IsExclusive() const { return m_bExclusive; }
void EnableOnClient( bool bEnable, bool bSkipFade = false );
Vector GetOrigin();
float GetMinFalloff();
float GetMaxFalloff();
void SetWeight( float fWeight );
protected:
void StartFade( float flDuration );
float GetFadeRatio() const;
bool IsFadeTimeElapsed() const;
#else
void ClientThink();
private:
#endif
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_flCurWeight;
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled;
#ifdef MAPBASE // From Alien Swarm SDK
float m_flFadeInDuration;
float m_flFadeOutDuration;
float m_flMaxWeight;
bool m_bMaster;
bool m_bClientSide;
bool m_bExclusive;
bool m_bFadingIn;
float m_flFadeStartWeight;
float m_flFadeStartTime;
float m_flFadeDuration;
#endif
ClientCCHandle_t m_CCHandle;
};
#endif

View File

@ -36,9 +36,26 @@ public:
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
#ifdef MAPBASE // From Alien Swarm SDK
void Update( C_BasePlayer *pPlayer, float ccScale );
void StartTouch( C_BaseEntity *pOther );
void EndTouch( C_BaseEntity *pOther );
#else
void ClientThink();
#endif
private:
#ifdef MAPBASE // From Alien Swarm SDK
float m_LastEnterWeight;
float m_LastEnterTime;
float m_LastExitWeight;
float m_LastExitTime;
bool m_bEnabled;
float m_MaxWeight;
float m_FadeDuration;
#endif
float m_Weight;
char m_lookupFilename[MAX_PATH];
@ -46,6 +63,11 @@ private:
};
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrectionVolume, DT_ColorCorrectionVolume, CColorCorrectionVolume)
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropFloat( RECVINFO( m_MaxWeight ) ),
RecvPropFloat( RECVINFO( m_FadeDuration ) ),
#endif
RecvPropFloat( RECVINFO(m_Weight) ),
RecvPropString( RECVINFO(m_lookupFilename) ),
END_RECV_TABLE()
@ -82,11 +104,21 @@ void C_ColorCorrectionVolume::OnDataChanged(DataUpdateType_t updateType)
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
#ifdef MAPBASE // From Alien Swarm SDK
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_lookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionVolume( this, name, m_lookupFilename );
#else
char filename[MAX_PATH];
Q_strncpy( filename, m_lookupFilename, MAX_PATH );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrection( filename );
SetNextClientThink( ( m_CCHandle != INVALID_CLIENT_CCHANDLE ) ? CLIENT_THINK_ALWAYS : CLIENT_THINK_NEVER );
#endif
}
}
}
@ -99,11 +131,95 @@ bool C_ColorCorrectionVolume::ShouldDraw()
return false;
}
#ifdef MAPBASE // From Alien Swarm SDK
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::StartTouch( CBaseEntity *pEntity )
{
m_LastEnterTime = gpGlobals->curtime;
m_LastEnterWeight = m_Weight;
}
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::EndTouch( CBaseEntity *pEntity )
{
m_LastExitTime = gpGlobals->curtime;
m_LastExitWeight = m_Weight;
}
void C_ColorCorrectionVolume::Update( C_BasePlayer *pPlayer, float ccScale )
{
if ( pPlayer )
{
bool isTouching = CollisionProp()->IsPointInBounds( pPlayer->EyePosition() );
bool wasTouching = m_LastEnterTime > m_LastExitTime;
if ( isTouching && !wasTouching )
{
StartTouch( pPlayer );
}
else if ( !isTouching && wasTouching )
{
EndTouch( pPlayer );
}
}
if( !m_bEnabled )
{
m_Weight = 0.0f;
}
else
{
if( m_LastEnterTime > m_LastExitTime )
{
// we most recently entered the volume
if( m_Weight < 1.0f )
{
float dt = gpGlobals->curtime - m_LastEnterTime;
float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = weight;
}
}
else
{
// we most recently exitted the volume
if( m_Weight > 0.0f )
{
float dt = gpGlobals->curtime - m_LastExitTime;
float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = 1.0f - weight;
}
}
}
// Vector entityPosition = GetAbsOrigin();
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight * ccScale );
}
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}
#else
void C_ColorCorrectionVolume::ClientThink()
{
Vector entityPosition = GetAbsOrigin();
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight );
}
#endif

View File

@ -6,6 +6,7 @@
//
//=============================================================================//
#include "cbase.h"
#include "c_effects.h"
#include "c_tracer.h"
#include "view.h"
#include "initializer.h"
@ -22,6 +23,7 @@
#include "collisionutils.h"
#include "tier0/vprof.h"
#include "viewrender.h"
#include "raytrace.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@ -35,6 +37,15 @@ float g_flSplashLifetime = 0.5f;
float g_flSplashAlpha = 0.3f;
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
ConVar r_RainParticleDensity( "r_RainParticleDensity", "1", FCVAR_NONE, "Density of Particle Rain 0-1" );
#ifdef MAPBASE
ConVar r_RainParticleClampOffset_Rain( "r_RainParticleClampOffset_Rain", "120", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Rain' type." );
ConVar r_RainParticleClampOffset_Ash( "r_RainParticleClampOffset_Ash", "300", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Ash' type." );
ConVar r_RainParticleClampOffset_RainStorm( "r_RainParticleClampOffset_RainStorm", "112", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Rain Storm' type." );
ConVar r_RainParticleClampOffset_Snow( "r_RainParticleClampOffset_Snow", "300", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Snow' type." );
ConVar r_RainParticleClampDebug( "r_RainParticleClampDebug", "0", FCVAR_NONE, "Enables debug code for precipitation particle system clamping" );
#endif
float GUST_INTERVAL_MIN = 1;
float GUST_INTERVAL_MAX = 2;
@ -60,151 +71,14 @@ CLIENTEFFECT_MATERIAL( "particle/rain" )
CLIENTEFFECT_MATERIAL( "particle/snow" )
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Precipitation particle type
//-----------------------------------------------------------------------------
class CPrecipitationParticle
{
public:
Vector m_Pos;
Vector m_Velocity;
float m_SpawnTime; // Note: Tweak with this to change lifetime
float m_Mass;
float m_Ramp;
float m_flCurLifetime;
float m_flMaxLifetime;
};
class CClient_Precipitation;
static CUtlVector<CClient_Precipitation*> g_Precipitations;
//===========
// Snow fall
//===========
class CSnowFallManager;
static CSnowFallManager *s_pSnowFallMgr = NULL;
bool SnowFallManagerCreate( CClient_Precipitation *pSnowEntity );
void SnowFallManagerDestroy( void );
class AshDebrisEffect : public CSimpleEmitter
{
public:
AshDebrisEffect( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
static AshDebrisEffect* Create( const char *pDebugName );
virtual float UpdateAlpha( const SimpleParticle *pParticle );
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta );
private:
AshDebrisEffect( const AshDebrisEffect & );
};
//-----------------------------------------------------------------------------
// Precipitation base entity
//-----------------------------------------------------------------------------
class CClient_Precipitation : public C_BaseEntity
{
class CPrecipitationEffect;
friend class CClient_Precipitation::CPrecipitationEffect;
public:
DECLARE_CLASS( CClient_Precipitation, C_BaseEntity );
DECLARE_CLIENTCLASS();
CClient_Precipitation();
virtual ~CClient_Precipitation();
// Inherited from C_BaseEntity
virtual void Precache( );
void Render();
private:
// Creates a single particle
CPrecipitationParticle* CreateParticle();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink();
void Simulate( float dt );
// Renders the particle
void RenderParticle( CPrecipitationParticle* pParticle, CMeshBuilder &mb );
void CreateWaterSplashes();
// Emits the actual particles
void EmitParticles( float fTimeDelta );
// Computes where we're gonna emit
bool ComputeEmissionArea( Vector& origin, Vector2D& size );
// Gets the tracer width and speed
float GetWidth() const;
float GetLength() const;
float GetSpeed() const;
// Gets the remaining lifetime of the particle
float GetRemainingLifetime( CPrecipitationParticle* pParticle ) const;
// Computes the wind vector
static void ComputeWindVector( );
// simulation methods
bool SimulateRain( CPrecipitationParticle* pParticle, float dt );
bool SimulateSnow( CPrecipitationParticle* pParticle, float dt );
void CreateAshParticle( void );
void CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity );
// Information helpful in creating and rendering particles
IMaterial *m_MatHandle; // material used
float m_Color[4]; // precip color
float m_Lifetime; // Precip lifetime
float m_InitialRamp; // Initial ramp value
float m_Speed; // Precip speed
float m_Width; // Tracer width
float m_Remainder; // particles we should render next time
PrecipitationType_t m_nPrecipType; // Precip type
float m_flHalfScreenWidth; // Precalculated each frame.
float m_flDensity;
// Some state used in rendering and simulation
// Used to modify the rain density and wind from the console
static ConVar s_raindensity;
static ConVar s_rainwidth;
static ConVar s_rainlength;
static ConVar s_rainspeed;
static Vector s_WindVector; // Stores the wind speed vector
CUtlLinkedList<CPrecipitationParticle> m_Particles;
CUtlVector<Vector> m_Splashes;
CSmartPtr<AshDebrisEffect> m_pAshEmitter;
TimedEvent m_tAshParticleTimer;
TimedEvent m_tAshParticleTraceTimer;
bool m_bActiveAshEmitter;
Vector m_vAshSpawnOrigin;
int m_iAshCount;
private:
CClient_Precipitation( const CClient_Precipitation & ); // not defined, not accessible
};
CUtlVector< RayTracingEnvironment* > g_RayTraceEnvironments;
// Just receive the normal data table stuff
IMPLEMENT_CLIENTCLASS_DT(CClient_Precipitation, DT_Precipitation, CPrecipitation)
RecvPropInt( RECVINFO( m_nPrecipType ) )
RecvPropInt( RECVINFO( m_nPrecipType ) ),
#ifdef MAPBASE
RecvPropInt( RECVINFO( m_spawnflags ) ),
#endif
END_RECV_TABLE()
static ConVar r_SnowEnable( "r_SnowEnable", "1", FCVAR_CHEAT, "Snow Enable" );
@ -396,6 +270,12 @@ inline bool CClient_Precipitation::SimulateSnow( CPrecipitationParticle* pPartic
void CClient_Precipitation::Simulate( float dt )
{
if ( IsParticleRainType(m_nPrecipType) )
{
CreateParticlePrecip();
return;
}
// NOTE: When client-side prechaching works, we need to remove this
Precache();
@ -472,6 +352,9 @@ inline void CClient_Precipitation::RenderParticle( CPrecipitationParticle* pPart
float scale;
Vector start, delta;
if ( IsParticleRainType(m_nPrecipType) )
return;
if ( m_nPrecipType == PRECIPITATION_TYPE_ASH )
return;
@ -562,6 +445,9 @@ void CClient_Precipitation::Render()
if ( !r_DrawRain.GetInt() )
return;
if ( IsParticleRainType(m_nPrecipType) )
return;
// Don't render in monitors or in reflections or refractions.
if ( CurrentViewID() == VIEW_MONITOR )
return;
@ -632,6 +518,11 @@ CClient_Precipitation::CClient_Precipitation() : m_Remainder(0.0f)
m_nPrecipType = PRECIPITATION_TYPE_RAIN;
m_MatHandle = INVALID_MATERIAL_HANDLE;
m_flHalfScreenWidth = 1;
m_pParticlePrecipInnerNear = NULL;
m_pParticlePrecipInnerFar = NULL;
m_pParticlePrecipOuter = NULL;
m_bActiveParticlePrecipEmitter = false;
g_Precipitations.AddToTail( this );
}
@ -1011,6 +902,397 @@ void CClient_Precipitation::CreateAshParticle( void )
}
}
void CClient_Precipitation::PrecacheParticlePrecip( void )
{
if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLEASH )
{
PrecacheParticleSystem( "ash" );
PrecacheParticleSystem( "ash_outer" );
}
else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLESNOW )
{
PrecacheParticleSystem( "snow" );
PrecacheParticleSystem( "snow_outer" );
}
else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLERAINSTORM )
{
PrecacheParticleSystem( "rain_storm" );
PrecacheParticleSystem( "rain_storm_screen" );
PrecacheParticleSystem( "rain_storm_outer" );
}
else //default to rain
{
PrecacheParticleSystem( "rain" );
PrecacheParticleSystem( "rain_outer" );
}
}
void CClient_Precipitation::CreateParticlePrecip( void )
{
if ( !m_bParticlePrecipInitialized )
{
PrecacheParticlePrecip();
InitializeParticlePrecip();
}
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer == NULL )
return;
// Make sure the emitter is setup
if ( !m_bActiveParticlePrecipEmitter )
{
//Update 8 times per second.
m_tParticlePrecipTraceTimer.Init( 8 );
DestroyInnerParticlePrecip();
DestroyOuterParticlePrecip();
m_bActiveParticlePrecipEmitter = true;
}
UpdateParticlePrecip( pPlayer );
}
#ifdef MAPBASE
void CClient_Precipitation::ClampParticlePosition( Vector &vPlayerPos, Vector &vOffsetPos, Vector &vOffsetPosNear, Vector &vOffsetPosFar )
{
Vector mins, maxs;
modelinfo->GetModelBounds( GetModel(), mins, maxs );
// Account for precipitation height
maxs.z += 180;
Vector vecOrigin; //= WorldSpaceCenter();
VectorLerp( mins, maxs, 0.5f, vecOrigin );
maxs -= vecOrigin;
mins -= vecOrigin;
//float flMax = r_RainParticleClampOffset.GetFloat();
float flMax = 0;
switch (m_nPrecipType)
{
case PRECIPITATION_TYPE_PARTICLERAIN:
flMax = r_RainParticleClampOffset_Rain.GetFloat();
break;
case PRECIPITATION_TYPE_PARTICLEASH:
flMax = r_RainParticleClampOffset_Ash.GetFloat();
break;
case PRECIPITATION_TYPE_PARTICLERAINSTORM:
flMax = r_RainParticleClampOffset_RainStorm.GetFloat();
break;
case PRECIPITATION_TYPE_PARTICLESNOW:
flMax = r_RainParticleClampOffset_Snow.GetFloat();
break;
}
Vector addend( flMax, flMax, 0 );
mins += addend;
maxs -= addend;
if (flMax > 0)
{
// Unless this is extruding outwards, make sure the offset isn't inverting the bounds.
// This means precipitation triggers with bounds less than offset*2 will turn into a thin line
// and the involved precipitation will pretty much be spatial at all times, which is okay.
mins.x = clamp( mins.x, -FLT_MAX, -1 );
mins.y = clamp( mins.y, -FLT_MAX, -1 );
maxs.x = clamp( maxs.x, 1, FLT_MAX );
maxs.y = clamp( maxs.y, 1, FLT_MAX );
}
if (r_RainParticleClampDebug.GetBool())
debugoverlay->AddBoxOverlay( vecOrigin, mins, maxs, vec3_angle, 255, 0, 0, 128, 0.15f );
maxs += vecOrigin;
mins += vecOrigin;
CalcClosestPointOnAABB( mins, maxs, vPlayerPos, vPlayerPos );
CalcClosestPointOnAABB( mins, maxs, vOffsetPos, vOffsetPos );
CalcClosestPointOnAABB( mins, maxs, vOffsetPosNear, vOffsetPosNear );
CalcClosestPointOnAABB( mins, maxs, vOffsetPosFar, vOffsetPosFar );
}
#endif
void CClient_Precipitation::UpdateParticlePrecip( C_BasePlayer *pPlayer )
{
if ( !pPlayer )
return;
Vector vForward;
Vector vRight;
pPlayer->GetVectors( &vForward, &vRight, NULL );
vForward.z = 0.0f;
vForward.NormalizeInPlace();
Vector vForward45Right = vForward + vRight;
Vector vForward45Left = vForward - vRight;
vForward45Right.NormalizeInPlace();
vForward45Left.NormalizeInPlace();
fltx4 TMax = ReplicateX4( 320.0f );
SubFloat( TMax, 3 ) = FLT_MAX;
float curTime = gpGlobals->frametime;
while ( m_tParticlePrecipTraceTimer.NextEvent( curTime ) )
{
Vector vPlayerPos = pPlayer->EyePosition();
Vector vOffsetPos = vPlayerPos + Vector ( 0, 0, 180 );
Vector vOffsetPosNear = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * 32 );
Vector vOffsetPosFar = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * 100 );
#ifdef MAPBASE
if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP)
{
ClampParticlePosition( vPlayerPos, vOffsetPos, vOffsetPosNear, vOffsetPosFar );
}
#endif
Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity;
// Get the rain volume Ray Tracing Environment. Currently hard coded to 0, should have this lookup
RayTracingEnvironment *RtEnv = g_RayTraceEnvironments.Element( 0 );
// Our 4 Rays are forward, off to the left and right, and directly up.
// Use the first three to determine if there's generally visible rain where we're looking.
// The forth, straight up, tells us if we're standing inside a rain volume
// (based on the normal that we hit or if we miss entirely)
FourRays frRays;
FourVectors fvDirection;
fvDirection = FourVectors( vForward, vForward45Left, vForward45Right, Vector( 0, 0, 1 ) );
frRays.direction = fvDirection;
frRays.origin.DuplicateVector( vPlayerPos );
RayTracingResult Result;
RtEnv->Trace4Rays( frRays, Four_Zeros, TMax, &Result );
i32x4 in4HitIds = LoadAlignedIntSIMD( Result.HitIds );
fltx4 fl4HitIds = SignedIntConvertToFltSIMD ( in4HitIds );
fltx4 fl4Tolerance = ReplicateX4( 300.0f );
// ignore upwards test for tolerance, as we may be below an area which is raining, but with it not visible in front of us
//SubFloat( fl4Tolerance, 3 ) = 0.0f;
bool bInside = ( Result.HitIds[3] != -1 && Result.surface_normal.Vec( 3 ).z < 0.0f );
bool bNearby = ( IsAnyNegative ( CmpGeSIMD ( fl4HitIds, Four_Zeros ) ) && IsAnyNegative( CmpGeSIMD( fl4Tolerance, Result.HitDistance ) ) );
if ( bInside || bNearby )
{
//We can see a rain volume, but it's farther than 180 units away, only use far effect.
if ( !bInside && SubFloat( FindLowestSIMD3( Result.HitDistance ), 0 ) >= m_flParticleInnerDist )
{
// Kill the inner rain if it's previously been in use
if ( m_pParticlePrecipInnerNear != NULL )
{
DestroyInnerParticlePrecip();
}
// Update if we've already got systems, otherwise, create them.
if ( m_pParticlePrecipOuter != NULL )
{
m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos );
m_pParticlePrecipOuter->SetControlPoint( 3, vDensity );
}
else
{
DispatchOuterParticlePrecip( pPlayer, vForward );
}
}
else //We're close enough to use the near effect.
{
// Update if we've already got systems, otherwise, create them.
#ifdef MAPBASE
// The outer can now be suppressed without interfering with other functionality
if ( m_pParticlePrecipOuter != NULL )
{
m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos );
m_pParticlePrecipOuter->SetControlPoint( 3, vDensity );
}
if ( m_pParticlePrecipInnerNear != NULL && m_pParticlePrecipInnerFar != NULL )
{
m_pParticlePrecipInnerNear->SetControlPoint( 1, vOffsetPosNear );
m_pParticlePrecipInnerFar->SetControlPoint( 1, vOffsetPosFar );
m_pParticlePrecipInnerNear->SetControlPoint( 3, vDensity );
m_pParticlePrecipInnerFar->SetControlPoint( 3, vDensity );
}
#else
if ( m_pParticlePrecipInnerNear != NULL && m_pParticlePrecipInnerFar != NULL && m_pParticlePrecipOuter != NULL )
{
m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos );
m_pParticlePrecipInnerNear->SetControlPoint( 1, vOffsetPosNear );
m_pParticlePrecipInnerFar->SetControlPoint( 1, vOffsetPosFar );
m_pParticlePrecipInnerNear->SetControlPoint( 3, vDensity );
m_pParticlePrecipInnerFar->SetControlPoint( 3, vDensity );
m_pParticlePrecipOuter->SetControlPoint( 3, vDensity );
}
#endif
else
{
DispatchInnerParticlePrecip( pPlayer, vForward );
}
}
}
else // No rain in the area, kill any leftover systems.
{
DestroyInnerParticlePrecip();
DestroyOuterParticlePrecip();
}
}
}
void CClient_Precipitation::InitializeParticlePrecip( void )
{
//Set up which type of precipitation particle we'll use
if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLEASH )
{
m_pParticleInnerNearDef = "ash";
m_pParticleInnerFarDef = "ash";
m_pParticleOuterDef = "ash_outer";
m_flParticleInnerDist = 280.0;
}
else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLESNOW )
{
m_pParticleInnerNearDef = "snow";
m_pParticleInnerFarDef = "snow";
m_pParticleOuterDef = "snow_outer";
m_flParticleInnerDist = 280.0;
}
else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLERAINSTORM )
{
m_pParticleInnerNearDef = "rain_storm";
m_pParticleInnerFarDef = "rain_storm_screen";
m_pParticleOuterDef = "rain_storm_outer";
m_flParticleInnerDist = 0.0;
}
else //default to rain
{
m_pParticleInnerNearDef = "rain";
m_pParticleInnerFarDef = "rain";
m_pParticleOuterDef = "rain_outer";
m_flParticleInnerDist = 180.0;
}
Assert( m_pParticleInnerFarDef != NULL );
//We'll want to change this if/when we add more raytrace environments.
g_RayTraceEnvironments.PurgeAndDeleteElements();
// Sets up ray tracing environments for all func_precipitations and func_precipitation_blockers
RayTracingEnvironment *rtEnvRainEmission = new RayTracingEnvironment();
g_RayTraceEnvironments.AddToTail( rtEnvRainEmission );
RayTracingEnvironment *rtEnvRainBlocker = new RayTracingEnvironment();
g_RayTraceEnvironments.AddToTail( rtEnvRainBlocker );
rtEnvRainEmission->Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS; // save some ram
rtEnvRainBlocker->Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS; // save some ram
int nTriCount = 1;
for ( int i=0; i<g_Precipitations.Count(); ++i )
{
CClient_Precipitation *volume = g_Precipitations[i];
vcollide_t *pCollide = modelinfo->GetVCollide( volume->GetModelIndex() );
if ( !pCollide || pCollide->solidCount <= 0 )
continue;
Vector *outVerts;
int vertCount = physcollision->CreateDebugMesh( pCollide->solids[0], &outVerts );
if ( vertCount )
{
for ( int j = 0; j < vertCount; j += 3 )
{
rtEnvRainEmission->AddTriangle( nTriCount++, outVerts[j], outVerts[j + 1], outVerts[j + 2], Vector( 1, 1, 1 ) );
}
}
physcollision->DestroyDebugMesh( vertCount, outVerts );
}
rtEnvRainEmission->SetupAccelerationStructure();
m_bParticlePrecipInitialized = true;
}
void CClient_Precipitation::DestroyInnerParticlePrecip( void )
{
if ( m_pParticlePrecipInnerFar != NULL )
{
m_pParticlePrecipInnerFar->StopEmission();
m_pParticlePrecipInnerFar = NULL;
}
if ( m_pParticlePrecipInnerNear != NULL )
{
m_pParticlePrecipInnerNear->StopEmission();
m_pParticlePrecipInnerNear = NULL;
}
}
void CClient_Precipitation::DestroyOuterParticlePrecip( void )
{
if ( m_pParticlePrecipOuter != NULL )
{
m_pParticlePrecipOuter->StopEmission();
m_pParticlePrecipOuter = NULL;
}
}
void CClient_Precipitation::DispatchOuterParticlePrecip( C_BasePlayer *pPlayer, Vector vForward )
{
DestroyOuterParticlePrecip();
#ifdef MAPBASE
if (m_spawnflags & SF_PRECIP_PARTICLE_NO_OUTER)
return;
#endif
Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity;
Vector vPlayerPos = pPlayer->EyePosition();
m_pParticlePrecipOuter = ParticleProp()->Create( m_pParticleOuterDef, PATTACH_ABSORIGIN_FOLLOW );
m_pParticlePrecipOuter->SetControlPointEntity( 2, pPlayer );
m_pParticlePrecipOuter->SetControlPoint( 1, vPlayerPos + Vector (0, 0, 180 ) );
m_pParticlePrecipOuter->SetControlPoint( 3, vDensity );
}
void CClient_Precipitation::DispatchInnerParticlePrecip( C_BasePlayer *pPlayer, Vector vForward )
{
DestroyInnerParticlePrecip();
DestroyOuterParticlePrecip();
Vector vPlayerPos = pPlayer->EyePosition();
Vector vOffsetPos = vPlayerPos + Vector ( 0, 0, 180 );
Vector vOffsetPosNear = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * 32 );
Vector vOffsetPosFar = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * m_flParticleInnerDist ); // 100.0
Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity;
#ifdef MAPBASE
if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP)
{
ClampParticlePosition( vPlayerPos, vOffsetPos, vOffsetPosNear, vOffsetPosFar );
}
#endif
#ifdef MAPBASE
if (!(m_spawnflags & SF_PRECIP_PARTICLE_NO_OUTER))
#endif
{
m_pParticlePrecipOuter = ParticleProp()->Create( m_pParticleOuterDef, PATTACH_ABSORIGIN_FOLLOW );
m_pParticlePrecipOuter->SetControlPointEntity( 2, pPlayer );
m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos );
m_pParticlePrecipOuter->SetControlPoint( 3, vDensity );
}
m_pParticlePrecipInnerNear = ParticleProp()->Create( m_pParticleInnerNearDef, PATTACH_ABSORIGIN_FOLLOW );
m_pParticlePrecipInnerFar = ParticleProp()->Create( m_pParticleInnerFarDef, PATTACH_ABSORIGIN_FOLLOW );
m_pParticlePrecipInnerNear->SetControlPointEntity( 2, pPlayer );
m_pParticlePrecipInnerFar->SetControlPointEntity( 2, pPlayer );
m_pParticlePrecipInnerNear->SetControlPoint( 1, vOffsetPosNear );
m_pParticlePrecipInnerFar->SetControlPoint( 1, vOffsetPosFar );
m_pParticlePrecipInnerNear->SetControlPoint( 3, vDensity );
m_pParticlePrecipInnerFar->SetControlPoint( 3, vDensity );
}
void CClient_Precipitation::CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity )
{
// Create the particle
@ -1206,6 +1488,12 @@ BEGIN_RECV_TABLE_NOBASE(CEnvWindShared, DT_EnvWindShared)
RecvPropFloat (RECVINFO(m_flStartTime)),
RecvPropFloat (RECVINFO(m_flGustDuration)),
// RecvPropInt (RECVINFO(m_iszGustSound)),
#ifdef MAPBASE
RecvPropFloat (RECVINFO(m_windRadius)),
RecvPropFloat (RECVINFO(m_windRadiusInner)),
RecvPropVector (RECVINFO(m_location)),
RecvPropFloat (RECVINFO(m_flTreeSwayScale)),
#endif
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT( C_EnvWind, DT_EnvWind, CEnvWind )
@ -1540,8 +1828,12 @@ public:
pParticle->m_vecVelocity *= flSpeed;
#ifdef MAPBASE
Vector vecWindVelocity = GetWindspeedAtLocation( pParticle->m_Pos );
#else
Vector vecWindVelocity;
GetWindspeedAtTime( gpGlobals->curtime, vecWindVelocity );
#endif
pParticle->m_vecVelocity += ( vecWindVelocity * r_SnowWindScale.GetFloat() );
}

View File

@ -10,9 +10,182 @@
#pragma once
#endif
#include "cbase.h"
#include "precipitation_shared.h"
// Draw rain effects.
void DrawPrecipitation();
//-----------------------------------------------------------------------------
// Precipitation particle type
//-----------------------------------------------------------------------------
class CPrecipitationParticle
{
public:
Vector m_Pos;
Vector m_Velocity;
float m_SpawnTime; // Note: Tweak with this to change lifetime
float m_Mass;
float m_Ramp;
float m_flCurLifetime;
float m_flMaxLifetime;
};
class CClient_Precipitation;
static CUtlVector<CClient_Precipitation*> g_Precipitations;
//===========
// Snow fall
//===========
class CSnowFallManager;
static CSnowFallManager *s_pSnowFallMgr = NULL;
bool SnowFallManagerCreate( CClient_Precipitation *pSnowEntity );
void SnowFallManagerDestroy( void );
class AshDebrisEffect : public CSimpleEmitter
{
public:
AshDebrisEffect( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
static AshDebrisEffect* Create( const char *pDebugName );
virtual float UpdateAlpha( const SimpleParticle *pParticle );
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta );
private:
AshDebrisEffect( const AshDebrisEffect & );
};
//-----------------------------------------------------------------------------
// Precipitation base entity
//-----------------------------------------------------------------------------
class CClient_Precipitation : public C_BaseEntity
{
class CPrecipitationEffect;
friend class CClient_Precipitation::CPrecipitationEffect;
public:
DECLARE_CLASS( CClient_Precipitation, C_BaseEntity );
DECLARE_CLIENTCLASS();
CClient_Precipitation();
virtual ~CClient_Precipitation();
// Inherited from C_BaseEntity
virtual void Precache( );
void Render();
private:
// Creates a single particle
CPrecipitationParticle* CreateParticle();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink();
void Simulate( float dt );
// Renders the particle
void RenderParticle( CPrecipitationParticle* pParticle, CMeshBuilder &mb );
void CreateWaterSplashes();
// Emits the actual particles
void EmitParticles( float fTimeDelta );
// Computes where we're gonna emit
bool ComputeEmissionArea( Vector& origin, Vector2D& size );
// Gets the tracer width and speed
float GetWidth() const;
float GetLength() const;
float GetSpeed() const;
// Gets the remaining lifetime of the particle
float GetRemainingLifetime( CPrecipitationParticle* pParticle ) const;
// Computes the wind vector
static void ComputeWindVector( );
// simulation methods
bool SimulateRain( CPrecipitationParticle* pParticle, float dt );
bool SimulateSnow( CPrecipitationParticle* pParticle, float dt );
void PrecacheParticlePrecip( void );
void CreateParticlePrecip( void );
void InitializeParticlePrecip( void );
void DispatchOuterParticlePrecip( C_BasePlayer *pPlayer, Vector vForward );
void DispatchInnerParticlePrecip( C_BasePlayer *pPlayer, Vector vForward );
void DestroyOuterParticlePrecip( void );
void DestroyInnerParticlePrecip( void );
void UpdateParticlePrecip( C_BasePlayer *pPlayer );
private:
void CreateAshParticle( void );
void CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity );
#ifdef MAPBASE
void ClampParticlePosition( Vector &vPlayerPos, Vector &vOffsetPos, Vector &vOffsetPosNear, Vector &vOffsetPosFar );
#endif
// Information helpful in creating and rendering particles
IMaterial *m_MatHandle; // material used
float m_Color[4]; // precip color
float m_Lifetime; // Precip lifetime
float m_InitialRamp; // Initial ramp value
float m_Speed; // Precip speed
float m_Width; // Tracer width
float m_Remainder; // particles we should render next time
PrecipitationType_t m_nPrecipType; // Precip type
float m_flHalfScreenWidth; // Precalculated each frame.
float m_flDensity;
#ifdef MAPBASE
int m_spawnflags;
#endif
// Some state used in rendering and simulation
// Used to modify the rain density and wind from the console
static ConVar s_raindensity;
static ConVar s_rainwidth;
static ConVar s_rainlength;
static ConVar s_rainspeed;
static Vector s_WindVector; // Stores the wind speed vector
CUtlLinkedList<CPrecipitationParticle> m_Particles;
CUtlVector<Vector> m_Splashes;
CSmartPtr<AshDebrisEffect> m_pAshEmitter;
TimedEvent m_tAshParticleTimer;
TimedEvent m_tAshParticleTraceTimer;
bool m_bActiveAshEmitter;
Vector m_vAshSpawnOrigin;
int m_iAshCount;
protected:
float m_flParticleInnerDist; //The distance at which to start drawing the inner system
char *m_pParticleInnerNearDef; //Name of the first inner system
char *m_pParticleInnerFarDef; //Name of the second inner system
char *m_pParticleOuterDef; //Name of the outer system
HPARTICLEFFECT m_pParticlePrecipInnerNear;
HPARTICLEFFECT m_pParticlePrecipInnerFar;
HPARTICLEFFECT m_pParticlePrecipOuter;
TimedEvent m_tParticlePrecipTraceTimer;
bool m_bActiveParticlePrecipEmitter;
bool m_bParticlePrecipInitialized;
private:
CClient_Precipitation( const CClient_Precipitation & ); // not defined, not accessible
};
#endif // C_EFFECTS_H

View File

@ -0,0 +1,88 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose: Depth of field controller entity
//
//=============================================================================
#include "cbase.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
extern bool g_bDOFEnabled;
extern float g_flDOFNearBlurDepth;
extern float g_flDOFNearFocusDepth;
extern float g_flDOFFarFocusDepth;
extern float g_flDOFFarBlurDepth;
extern float g_flDOFNearBlurRadius;
extern float g_flDOFFarBlurRadius;
EHANDLE g_hDOFControllerInUse = NULL;
class C_EnvDOFController : public C_BaseEntity
{
DECLARE_CLASS( C_EnvDOFController, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_EnvDOFController();
~C_EnvDOFController();
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
bool m_bDOFEnabled;
float m_flNearBlurDepth;
float m_flNearFocusDepth;
float m_flFarFocusDepth;
float m_flFarBlurDepth;
float m_flNearBlurRadius;
float m_flFarBlurRadius;
private:
C_EnvDOFController( const C_EnvDOFController & );
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvDOFController, DT_EnvDOFController, CEnvDOFController )
RecvPropInt( RECVINFO(m_bDOFEnabled) ),
RecvPropFloat( RECVINFO(m_flNearBlurDepth) ),
RecvPropFloat( RECVINFO(m_flNearFocusDepth) ),
RecvPropFloat( RECVINFO(m_flFarFocusDepth) ),
RecvPropFloat( RECVINFO(m_flFarBlurDepth) ),
RecvPropFloat( RECVINFO(m_flNearBlurRadius) ),
RecvPropFloat( RECVINFO(m_flFarBlurRadius) )
END_RECV_TABLE()
C_EnvDOFController::C_EnvDOFController()
: m_bDOFEnabled( true ),
m_flNearBlurDepth( 20.0f ),
m_flNearFocusDepth( 100.0f ),
m_flFarFocusDepth( 250.0f ),
m_flFarBlurDepth( 1000.0f ),
m_flNearBlurRadius( 0.0f ), // no near blur by default
m_flFarBlurRadius( 5.0f )
{
}
C_EnvDOFController::~C_EnvDOFController()
{
if ( g_hDOFControllerInUse == this )
{
g_bDOFEnabled = false;
}
}
void C_EnvDOFController::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
g_bDOFEnabled = m_bDOFEnabled && ( ( m_flNearBlurRadius > 0.0f ) || ( m_flFarBlurRadius > 0.0f ) );
g_flDOFNearBlurDepth = m_flNearBlurDepth;
g_flDOFNearFocusDepth = m_flNearFocusDepth;
g_flDOFFarFocusDepth = m_flFarFocusDepth;
g_flDOFFarBlurDepth = m_flFarBlurDepth;
g_flDOFNearBlurRadius = m_flNearBlurRadius;
g_flDOFFarBlurRadius = m_flFarBlurRadius;
g_hDOFControllerInUse = this;
}

View File

@ -0,0 +1,348 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Sunlight shadow control entity.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseplayer.h"
#include "tier0/vprof.h"
#ifdef MAPBASE
#include "materialsystem/itexture.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar cl_sunlight_ortho_size;
extern ConVar cl_sunlight_depthbias;
ConVar cl_globallight_freeze( "cl_globallight_freeze", "0" );
#ifdef MAPBASE
// I imagine these values might've been designed for the ASW view.
// You can set these as KV anyway.
ConVar cl_globallight_xoffset( "cl_globallight_xoffset", "0" );
ConVar cl_globallight_yoffset( "cl_globallight_yoffset", "0" );
static ConVar cl_globallight_slopescaledepthbias_shadowmap( "cl_globallight_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
static ConVar cl_globallight_shadowfiltersize( "cl_globallight_shadowfiltersize", "0.1", FCVAR_CHEAT );
static ConVar cl_globallight_depthbias_shadowmap( "cl_globallight_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
static ConVar cl_globallight_depthres( "cl_globallight_depthres", "8192", FCVAR_CHEAT );
#else
ConVar cl_globallight_xoffset( "cl_globallight_xoffset", "-800" );
ConVar cl_globallight_yoffset( "cl_globallight_yoffset", "1600" );
#endif
//------------------------------------------------------------------------------
// Purpose : Sunlights shadow control entity
//------------------------------------------------------------------------------
class C_GlobalLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_GlobalLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
virtual ~C_GlobalLight();
void OnDataChanged( DataUpdateType_t updateType );
void Spawn();
bool ShouldDraw();
void ClientThink();
private:
Vector m_shadowDirection;
bool m_bEnabled;
char m_TextureName[ MAX_PATH ];
#ifdef MAPBASE
int m_nSpotlightTextureFrame;
#endif
CTextureReference m_SpotlightTexture;
color32 m_LightColor;
#ifdef MAPBASE
float m_flBrightnessScale;
float m_flCurrentBrightnessScale;
#endif
Vector m_CurrentLinearFloatLightColor;
float m_flCurrentLinearFloatLightAlpha;
float m_flColorTransitionTime;
float m_flSunDistance;
float m_flFOV;
float m_flNearZ;
float m_flNorthOffset;
#ifdef MAPBASE
float m_flEastOffset;
float m_flForwardOffset;
float m_flOrthoSize;
#endif
bool m_bEnableShadows;
bool m_bOldEnableShadows;
static ClientShadowHandle_t m_LocalFlashlightHandle;
};
ClientShadowHandle_t C_GlobalLight::m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
IMPLEMENT_CLIENTCLASS_DT(C_GlobalLight, DT_GlobalLight, CGlobalLight)
RecvPropVector(RECVINFO(m_shadowDirection)),
RecvPropBool(RECVINFO(m_bEnabled)),
RecvPropString(RECVINFO(m_TextureName)),
#ifdef MAPBASE
RecvPropInt(RECVINFO(m_nSpotlightTextureFrame)),
#endif
/*RecvPropInt(RECVINFO(m_LightColor), 0, RecvProxy_Int32ToColor32),*/
RecvPropInt(RECVINFO(m_LightColor), 0, RecvProxy_IntToColor32),
#ifdef MAPBASE
RecvPropFloat(RECVINFO(m_flBrightnessScale)),
#endif
RecvPropFloat(RECVINFO(m_flColorTransitionTime)),
RecvPropFloat(RECVINFO(m_flSunDistance)),
RecvPropFloat(RECVINFO(m_flFOV)),
RecvPropFloat(RECVINFO(m_flNearZ)),
RecvPropFloat(RECVINFO(m_flNorthOffset)),
#ifdef MAPBASE
RecvPropFloat(RECVINFO(m_flEastOffset)),
RecvPropFloat(RECVINFO(m_flForwardOffset)),
RecvPropFloat(RECVINFO(m_flOrthoSize)),
#endif
RecvPropBool(RECVINFO(m_bEnableShadows)),
END_RECV_TABLE()
C_GlobalLight::~C_GlobalLight()
{
if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
}
void C_GlobalLight::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
m_SpotlightTexture.Init( m_TextureName, TEXTURE_GROUP_OTHER, true );
}
#ifdef MAPBASE
else //if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
{
// It could've been changed via input
if( !FStrEq(m_SpotlightTexture->GetName(), m_TextureName) )
{
m_SpotlightTexture.Init( m_TextureName, TEXTURE_GROUP_OTHER, true );
}
}
#endif
BaseClass::OnDataChanged( updateType );
}
void C_GlobalLight::Spawn()
{
BaseClass::Spawn();
m_bOldEnableShadows = m_bEnableShadows;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_GlobalLight::ShouldDraw()
{
return false;
}
void C_GlobalLight::ClientThink()
{
VPROF("C_GlobalLight::ClientThink");
bool bSupressWorldLights = false;
if ( cl_globallight_freeze.GetBool() == true )
{
return;
}
if ( m_bEnabled )
{
Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
float flLinearFloatLightAlpha = m_LightColor.a;
#ifdef MAPBASE
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha || m_flCurrentBrightnessScale != m_flBrightnessScale )
{
if (m_flColorTransitionTime != 0.0f)
{
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
m_flCurrentBrightnessScale = Approach( m_flBrightnessScale, m_flCurrentBrightnessScale, flColorTransitionSpeed );
}
else
{
// Just do it instantly
m_CurrentLinearFloatLightColor.x = vLinearFloatLightColor.x;
m_CurrentLinearFloatLightColor.y = vLinearFloatLightColor.y;
m_CurrentLinearFloatLightColor.z = vLinearFloatLightColor.z;
m_flCurrentLinearFloatLightAlpha = flLinearFloatLightAlpha;
m_flCurrentBrightnessScale = m_flBrightnessScale;
}
}
#else
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
{
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
}
#endif
FlashlightState_t state;
Vector vDirection = m_shadowDirection;
VectorNormalize( vDirection );
//Vector vViewUp = Vector( 0.0f, 1.0f, 0.0f );
Vector vSunDirection2D = vDirection;
vSunDirection2D.z = 0.0f;
/*HACK_GETLOCALPLAYER_GUARD( "C_GlobalLight::ClientThink" );*/
if ( !C_BasePlayer::GetLocalPlayer() )
return;
Vector vPos;
QAngle EyeAngles;
float flZNear, flZFar, flFov;
C_BasePlayer::GetLocalPlayer()->CalcView( vPos, EyeAngles, flZNear, flZFar, flFov );
// Vector vPos = C_BasePlayer::GetLocalPlayer()->GetAbsOrigin();
// vPos = Vector( 0.0f, 0.0f, 500.0f );
vPos = ( vPos + vSunDirection2D * m_flNorthOffset ) - vDirection * m_flSunDistance;
#ifdef MAPBASE
vPos += Vector( m_flEastOffset + cl_globallight_xoffset.GetFloat(), m_flForwardOffset + cl_globallight_yoffset.GetFloat(), 0.0f );
#else
vPos += Vector( cl_globallight_xoffset.GetFloat(), cl_globallight_yoffset.GetFloat(), 0.0f );
#endif
QAngle angAngles;
VectorAngles( vDirection, angAngles );
Vector vForward, vRight, vUp;
AngleVectors( angAngles, &vForward, &vRight, &vUp );
state.m_fHorizontalFOVDegrees = m_flFOV;
state.m_fVerticalFOVDegrees = m_flFOV;
state.m_vecLightOrigin = vPos;
BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
state.m_fQuadraticAtten = 0.0f;
state.m_fLinearAtten = m_flSunDistance * 2.0f;
state.m_fConstantAtten = 0.0f;
state.m_FarZAtten = m_flSunDistance * 2.0f;
#ifdef MAPBASE
float flAlpha = m_flCurrentLinearFloatLightAlpha * (1.0f / 255.0f);
state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
#else
state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
#endif
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
state.m_NearZ = 4.0f;
state.m_FarZ = m_flSunDistance * 2.0f;
state.m_fBrightnessScale = 2.0f;
state.m_bGlobalLight = true;
#ifdef MAPBASE
float flOrthoSize = m_flOrthoSize;
#else
float flOrthoSize = 1000.0f;
#endif
if ( flOrthoSize > 0 )
{
state.m_bOrtho = true;
state.m_fOrthoLeft = -flOrthoSize;
state.m_fOrthoTop = -flOrthoSize;
state.m_fOrthoRight = flOrthoSize;
state.m_fOrthoBottom = flOrthoSize;
}
else
{
state.m_bOrtho = false;
}
#ifdef MAPBASE
//state.m_bDrawShadowFrustum = true; // Don't draw that huge debug thing
state.m_flShadowMapResolution = cl_globallight_depthres.GetFloat();
state.m_flShadowFilterSize = cl_globallight_shadowfiltersize.GetFloat();
state.m_flShadowSlopeScaleDepthBias = cl_globallight_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = cl_globallight_depthbias_shadowmap.GetFloat();
state.m_bEnableShadows = m_bEnableShadows;
state.m_pSpotlightTexture = m_SpotlightTexture;
state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
#else
state.m_bDrawShadowFrustum = true;
/*state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();;
state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();*/
state.m_bEnableShadows = m_bEnableShadows;
state.m_pSpotlightTexture = m_SpotlightTexture;
state.m_nSpotlightTextureFrame = 0;
#endif
state.m_nShadowQuality = 1; // Allow entity to affect shadow quality
// state.m_bShadowHighRes = true;
if ( m_bOldEnableShadows != m_bEnableShadows )
{
// If they change the shadow enable/disable, we need to make a new handle
if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
m_bOldEnableShadows = m_bEnableShadows;
}
if( m_LocalFlashlightHandle == CLIENTSHADOW_INVALID_HANDLE )
{
m_LocalFlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state );
}
else
{
g_pClientShadowMgr->UpdateFlashlightState( m_LocalFlashlightHandle, state );
g_pClientShadowMgr->UpdateProjectedTexture( m_LocalFlashlightHandle, true );
}
bSupressWorldLights = m_bEnableShadows;
}
else if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
g_pClientShadowMgr->SetShadowFromWorldLightsEnabled( !bSupressWorldLights );
BaseClass::ClientThink();
}

View File

@ -5,6 +5,13 @@
//=============================================================================
#include "cbase.h"
#ifdef ASW_PROJECTED_TEXTURES
#include "C_Env_Projected_Texture.h"
#include "vprof.h"
#endif
#ifdef MAPBASE
#include "materialsystem/itexture.h"
#endif
#include "shareddefs.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
@ -17,8 +24,480 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef ASW_PROJECTED_TEXTURES
extern ConVarRef mat_slopescaledepthbias_shadowmap;
extern ConVarRef mat_depthbias_shadowmap;
float C_EnvProjectedTexture::m_flVisibleBBoxMinHeight = -FLT_MAX;
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
#ifdef MAPBASE
RecvPropBool( RECVINFO( m_bDontFollowTarget )),
#endif
RecvPropBool( RECVINFO( m_bState ) ),
RecvPropBool( RECVINFO( m_bAlwaysUpdate ) ),
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
#ifdef MAPBASE
RecvPropFloat( RECVINFO( m_flLightHorFOV ) ),
#endif
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
RecvPropBool( RECVINFO( m_bLightWorld ) ),
RecvPropBool( RECVINFO( m_bCameraSpace ) ),
RecvPropFloat( RECVINFO( m_flBrightnessScale ) ),
RecvPropInt( RECVINFO( m_LightColor ), 0, RecvProxy_IntToColor32 ),
RecvPropFloat( RECVINFO( m_flColorTransitionTime ) ),
RecvPropFloat( RECVINFO( m_flAmbient ) ),
RecvPropString( RECVINFO( m_SpotlightTextureName ) ),
RecvPropInt( RECVINFO( m_nSpotlightTextureFrame ) ),
RecvPropFloat( RECVINFO( m_flNearZ ) ),
RecvPropFloat( RECVINFO( m_flFarZ ) ),
RecvPropInt( RECVINFO( m_nShadowQuality ) ),
#ifdef MAPBASE
RecvPropFloat( RECVINFO( m_flConstantAtten ) ),
RecvPropFloat( RECVINFO( m_flLinearAtten ) ),
RecvPropFloat( RECVINFO( m_flQuadraticAtten ) ),
RecvPropFloat( RECVINFO( m_flShadowAtten ) ),
RecvPropFloat( RECVINFO( m_flShadowFilter ) ),
RecvPropBool( RECVINFO( m_bAlwaysDraw ) ),
// Not needed on the client right now, change when it actually is needed
//RecvPropBool( RECVINFO( m_bProjectedTextureVersion ) ),
#endif
END_RECV_TABLE()
C_EnvProjectedTexture *C_EnvProjectedTexture::Create( )
{
C_EnvProjectedTexture *pEnt = new C_EnvProjectedTexture();
pEnt->m_flNearZ = 4.0f;
pEnt->m_flFarZ = 2000.0f;
// strcpy( pEnt->m_SpotlightTextureName, "particle/rj" );
pEnt->m_bLightWorld = true;
pEnt->m_bLightOnlyTarget = false;
pEnt->m_nShadowQuality = 1;
pEnt->m_flLightFOV = 10.0f;
#ifdef MAPBASE
pEnt->m_flLightHorFOV = 10.0f;
#endif
pEnt->m_LightColor.r = 255;
pEnt->m_LightColor.g = 255;
pEnt->m_LightColor.b = 255;
pEnt->m_LightColor.a = 255;
pEnt->m_bEnableShadows = false;
pEnt->m_flColorTransitionTime = 1.0f;
pEnt->m_bCameraSpace = false;
pEnt->SetAbsAngles( QAngle( 90, 0, 0 ) );
pEnt->m_bAlwaysUpdate = true;
pEnt->m_bState = true;
#ifdef MAPBASE
pEnt->m_bAlwaysDraw = false;
pEnt->m_flConstantAtten = 0.0f;
pEnt->m_flLinearAtten = 100.0f;
pEnt->m_flQuadraticAtten = 0.0f;
pEnt->m_flShadowAtten = 0.0f;
pEnt->m_flShadowFilter = 0.5f;
//pEnt->m_bProjectedTextureVersion = 1;
#endif
return pEnt;
}
C_EnvProjectedTexture::C_EnvProjectedTexture( void )
{
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
m_bForceUpdate = true;
#ifndef MAPBASE
AddToEntityList( ENTITY_LIST_SIMULATE );
#endif
}
C_EnvProjectedTexture::~C_EnvProjectedTexture( void )
{
ShutDownLightHandle();
}
void C_EnvProjectedTexture::ShutDownLightHandle( void )
{
// Clear out the light
if( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
g_pClientShadowMgr->DestroyFlashlight( m_LightHandle );
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
}
void C_EnvProjectedTexture::SetLightColor( byte r, byte g, byte b, byte a )
{
m_LightColor.r = r;
m_LightColor.g = g;
m_LightColor.b = b;
m_LightColor.a = a;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
m_SpotlightTexture.Init( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, true );
}
#ifdef MAPBASE
else //if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
{
// It could've been changed via input
if( !FStrEq(m_SpotlightTexture->GetName(), m_SpotlightTextureName) )
{
m_SpotlightTexture.Init( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, true );
}
}
#endif
m_bForceUpdate = true;
UpdateLight();
BaseClass::OnDataChanged( updateType );
}
static ConVar asw_perf_wtf("asw_perf_wtf", "0", FCVAR_DEVELOPMENTONLY, "Disable updating of projected shadow textures from UpdateLight" );
void C_EnvProjectedTexture::UpdateLight( void )
{
VPROF("C_EnvProjectedTexture::UpdateLight");
bool bVisible = true;
Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
float flLinearFloatLightAlpha = m_LightColor.a;
if ( m_bAlwaysUpdate )
{
m_bForceUpdate = true;
}
#ifdef MAPBASE
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha || m_flCurrentBrightnessScale != m_flBrightnessScale )
{
if (m_flColorTransitionTime != 0.0f)
{
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
m_flCurrentBrightnessScale = Approach( m_flBrightnessScale, m_flCurrentBrightnessScale, flColorTransitionSpeed );
}
else
{
// Just do it instantly
m_CurrentLinearFloatLightColor.x = vLinearFloatLightColor.x;
m_CurrentLinearFloatLightColor.y = vLinearFloatLightColor.y;
m_CurrentLinearFloatLightColor.z = vLinearFloatLightColor.z;
m_flCurrentLinearFloatLightAlpha = flLinearFloatLightAlpha;
m_flCurrentBrightnessScale = m_flBrightnessScale;
}
m_bForceUpdate = true;
}
#else
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
{
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
m_bForceUpdate = true;
}
#endif
if ( !m_bForceUpdate )
{
bVisible = IsBBoxVisible();
}
if ( m_bState == false || !bVisible )
{
// Spotlight's extents aren't in view
ShutDownLightHandle();
return;
}
if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
{
Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
FlashlightState_t state;
#ifdef MAPBASE
if ( m_hTargetEntity != NULL && !m_bDontFollowTarget )
#else
if ( m_hTargetEntity != NULL )
#endif
{
if ( m_bCameraSpace )
{
const QAngle &angles = GetLocalAngles();
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if( pPlayer )
{
const QAngle playerAngles = pPlayer->GetAbsAngles();
Vector vPlayerForward, vPlayerRight, vPlayerUp;
AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
matrix3x4_t mRotMatrix;
AngleMatrix( angles, mRotMatrix );
VectorITransform( vPlayerForward, mRotMatrix, vForward );
VectorITransform( vPlayerRight, mRotMatrix, vRight );
VectorITransform( vPlayerUp, mRotMatrix, vUp );
float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;
VectorNormalize( vForward );
VectorNormalize( vRight );
VectorNormalize( vUp );
}
}
else
{
vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
VectorNormalize( vForward );
// JasonM - unimplemented
Assert (0);
//Quaternion q = DirectionToOrientation( dir );
//
// JasonM - set up vRight, vUp
//
// VectorNormalize( vRight );
// VectorNormalize( vUp );
VectorVectors( vForward, vRight, vUp );
}
}
else
{
AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
}
#ifdef MAPBASE
float fHighFOV;
if( m_flLightFOV > m_flLightHorFOV )
fHighFOV = m_flLightFOV;
else
fHighFOV = m_flLightHorFOV;
state.m_fHorizontalFOVDegrees = m_flLightHorFOV;
#else
state.m_fHorizontalFOVDegrees = m_flLightFOV;
#endif
state.m_fVerticalFOVDegrees = m_flLightFOV;
state.m_vecLightOrigin = vPos;
BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
state.m_NearZ = m_flNearZ;
state.m_FarZ = m_flFarZ;
// quickly check the proposed light's bbox against the view frustum to determine whether we
// should bother to create it, if it doesn't exist, or cull it, if it does.
// get the half-widths of the near and far planes,
// based on the FOV which is in degrees. Remember that
// on planet Valve, x is forward, y left, and z up.
#ifdef MAPBASE
const float tanHalfAngle = tan( fHighFOV * ( M_PI/180.0f ) * 0.5f );
#else
const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f );
#endif
const float halfWidthNear = tanHalfAngle * m_flNearZ;
const float halfWidthFar = tanHalfAngle * m_flFarZ;
// now we can build coordinates in local space: the near rectangle is eg
// (0, -halfWidthNear, -halfWidthNear), (0, halfWidthNear, -halfWidthNear),
// (0, halfWidthNear, halfWidthNear), (0, -halfWidthNear, halfWidthNear)
VectorAligned vNearRect[4] = {
VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ, halfWidthNear, -halfWidthNear),
VectorAligned( m_flNearZ, halfWidthNear, halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear, halfWidthNear)
};
VectorAligned vFarRect[4] = {
VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ, halfWidthFar, -halfWidthFar),
VectorAligned( m_flFarZ, halfWidthFar, halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar, halfWidthFar)
};
matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos );
enum
{
kNEAR = 0,
kFAR = 1,
};
VectorAligned vOutRects[2][4];
for ( int i = 0 ; i < 4 ; ++i )
{
VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() );
}
for ( int i = 0 ; i < 4 ; ++i )
{
VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() );
}
// now take the min and max extents for the bbox, and see if it is visible.
Vector mins = **vOutRects;
Vector maxs = **vOutRects;
for ( int i = 1; i < 8 ; ++i )
{
VectorMin( mins, *(*vOutRects+i), mins );
VectorMax( maxs, *(*vOutRects+i), maxs );
}
#if 0 //for debugging the visibility frustum we just calculated
NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri
NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri
NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri
NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri
NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f );
#endif
bool bVisible = IsBBoxVisible( mins, maxs );
if (!bVisible)
{
// Spotlight's extents aren't in view
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
ShutDownLightHandle();
}
return;
}
float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );
#ifdef MAPBASE
state.m_fConstantAtten = m_flConstantAtten;
state.m_fLinearAtten = m_flLinearAtten;
state.m_fQuadraticAtten = m_flQuadraticAtten;
state.m_FarZAtten = m_flFarZ;
state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
state.m_flShadowAtten = m_flShadowAtten;
state.m_flShadowFilterSize = m_flShadowFilter;
#else
state.m_fQuadraticAtten = 0.0;
state.m_fLinearAtten = 100;
state.m_fConstantAtten = 0.0f;
state.m_FarZAtten = m_flFarZ;
state.m_fBrightnessScale = m_flBrightnessScale;
state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();
state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();
#endif
state.m_bEnableShadows = m_bEnableShadows;
state.m_pSpotlightTexture = m_SpotlightTexture;
state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality
#ifdef MAPBASE
state.m_bAlwaysDraw = m_bAlwaysDraw;
#endif
if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
{
m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
m_bForceUpdate = false;
}
}
else
{
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
m_bForceUpdate = false;
}
g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax );
m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
}
if( m_bLightOnlyTarget )
{
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
}
else
{
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
}
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate )
{
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
}
}
void C_EnvProjectedTexture::Simulate( void )
{
UpdateLight();
BaseClass::Simulate();
}
bool C_EnvProjectedTexture::IsBBoxVisible( Vector vecExtentsMin, Vector vecExtentsMax )
{
#ifdef MAPBASE
if (m_bAlwaysDraw)
return true;
#endif
// Z position clamped to the min height (but must be less than the max)
float flVisibleBBoxMinHeight = MIN( vecExtentsMax.z - 1.0f, m_flVisibleBBoxMinHeight );
vecExtentsMin.z = MAX( vecExtentsMin.z, flVisibleBBoxMinHeight );
// Check if the bbox is in the view
return !engine->CullBox( vecExtentsMin, vecExtentsMax );
}
#else
#ifndef MAPBASE
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT );
#else
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "4", FCVAR_CHEAT );
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
#endif
//-----------------------------------------------------------------------------
// Purpose:
@ -34,7 +513,11 @@ public:
virtual void Simulate();
#ifdef MAPBASE
void UpdateLight();
#else
void UpdateLight( bool bForceUpdate );
#endif
C_EnvProjectedTexture();
~C_EnvProjectedTexture();
@ -42,10 +525,16 @@ public:
private:
ClientShadowHandle_t m_LightHandle;
#ifdef MAPBASE
bool m_bForceUpdate;
#endif
EHANDLE m_hTargetEntity;
bool m_bState;
#ifdef MAPBASE
bool m_bAlwaysUpdate;
#endif
float m_flLightFOV;
bool m_bEnableShadows;
bool m_bLightOnlyTarget;
@ -63,6 +552,9 @@ private:
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
RecvPropBool( RECVINFO( m_bState ) ),
#ifdef MAPBASE
RecvPropBool( RECVINFO( m_bAlwaysUpdate ) ),
#endif
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
@ -103,12 +595,22 @@ void C_EnvProjectedTexture::ShutDownLightHandle( void )
//-----------------------------------------------------------------------------
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
{
#ifdef MAPBASE
m_bForceUpdate = true;
UpdateLight();
#else
UpdateLight( true );
#endif
BaseClass::OnDataChanged( updateType );
}
#ifndef MAPBASE
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
#else
void C_EnvProjectedTexture::UpdateLight()
#endif
{
#ifndef MAPBASE
if ( m_bState == false )
{
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
@ -118,7 +620,25 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
return;
}
#else
if ( m_bAlwaysUpdate )
{
m_bForceUpdate = true;
}
if ( m_bState == false )
{
// Spotlight's extents aren't in view
ShutDownLightHandle();
return;
}
#endif
#ifdef MAPBASE
if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
{
#endif
Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
FlashlightState_t state;
@ -153,8 +673,24 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
}
else
{
#ifndef MAPBASE
vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
VectorNormalize( vForward );
#else
// VXP: Fixing targeting
Vector vecToTarget;
QAngle vecAngles;
if (m_hTargetEntity == NULL)
{
vecAngles = GetAbsAngles();
}
else
{
vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
VectorAngles(vecToTarget, vecAngles);
}
AngleVectors(vecAngles, &vForward, &vRight, &vUp);
#endif
// JasonM - unimplemented
Assert (0);
@ -204,11 +740,19 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
}
else
{
#ifndef MAPBASE
if ( m_hTargetEntity != NULL || bForceUpdate == true )
{
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
}
#else
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
m_bForceUpdate = false;
#endif
}
#ifdef MAPBASE
}
#endif
if( m_bLightOnlyTarget )
{
@ -221,16 +765,29 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
#ifndef MAPBASE
if ( bForceUpdate == false )
{
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
}
#else
if ( !m_bForceUpdate )
{
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
}
#endif
}
void C_EnvProjectedTexture::Simulate( void )
{
#ifndef MAPBASE
UpdateLight( false );
#else
UpdateLight();
#endif
BaseClass::Simulate();
}
#endif

View File

@ -48,6 +48,9 @@ protected:
int m_iCachedDesiredOverlay;
int m_iCurrentOverlay;
float m_flCurrentOverlayTime;
#ifdef MAPBASE
int m_iOverlayIndex;
#endif
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOverlay )
@ -56,6 +59,9 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOve
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropInt( RECVINFO( m_iDesiredOverlay ) ),
RecvPropBool( RECVINFO( m_bIsActive ) ),
#ifdef MAPBASE
RecvPropInt( RECVINFO( m_iOverlayIndex ) ),
#endif
END_RECV_TABLE()
//-----------------------------------------------------------------------------
@ -77,7 +83,11 @@ void C_EnvScreenOverlay::PostDataUpdate( DataUpdateType_t updateType )
BaseClass::PostDataUpdate( updateType );
// If we have a start time now, start the overlays going
#ifdef MAPBASE
if ( m_bIsActive && m_flStartTime > 0 && (view->GetScreenOverlayMaterial() == NULL || (m_iOverlayIndex != -1 && view->GetIndexedScreenOverlayMaterial(m_iOverlayIndex) == NULL)) )
#else
if ( m_bIsActive && m_flStartTime > 0 && view->GetScreenOverlayMaterial() == NULL )
#endif
{
StartOverlays();
}
@ -111,7 +121,16 @@ void C_EnvScreenOverlay::StopOverlays( void )
if ( m_bWasActive && !m_bIsActive )
{
view->SetScreenOverlayMaterial( NULL );
#ifdef MAPBASE
if (m_iOverlayIndex != -1)
{
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, NULL );
}
else
#endif
{
view->SetScreenOverlayMaterial( NULL );
}
}
}
@ -163,7 +182,16 @@ void C_EnvScreenOverlay::StartCurrentOverlay( void )
IMaterial *pMaterial = materials->FindMaterial( m_iszOverlayNames[m_iCurrentOverlay], TEXTURE_GROUP_CLIENT_EFFECTS, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetScreenOverlayMaterial( pMaterial );
#ifdef MAPBASE
if (m_iOverlayIndex != -1)
{
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, pMaterial );
}
else
#endif
{
view->SetScreenOverlayMaterial( pMaterial );
}
}
else
{
@ -191,6 +219,11 @@ enum
SCREENEFFECT_EP2_ADVISOR_STUN,
SCREENEFFECT_EP1_INTRO,
SCREENEFFECT_EP2_GROGGY,
#ifdef MAPBASE
SCREENEFFECT_MAPBASE_CHROMATIC_BLUR = 100, // Overlays 3 different frames of red, green, and blue tints respectively with different offsets
SCREENEFFECT_MAPBASE_CHROMATIC_ABERRATION, // Similar to above, except it stretches frames in addition to offsetting them
#endif
};
// ============================================================================
@ -275,6 +308,21 @@ void C_EnvScreenEffect::ReceiveMessage( int classID, bf_read &msg )
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "ep2_groggy", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "ep2_groggy" );
}
#ifdef MAPBASE
else if ( m_nType == SCREENEFFECT_MAPBASE_CHROMATIC_BLUR || m_nType == SCREENEFFECT_MAPBASE_CHROMATIC_ABERRATION )
{
if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
return;
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 0 );
pKeys->SetInt( "stretch", m_nType == SCREENEFFECT_MAPBASE_CHROMATIC_ABERRATION );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "mapbase_chromatic_aberration", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "mapbase_chromatic_aberration" );
}
#endif
pKeys->deleteThis();
}
@ -321,6 +369,25 @@ void C_EnvScreenEffect::ReceiveMessage( int classID, bf_read &msg )
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "ep2_groggy", pKeys );
}
#ifdef MAPBASE
else if ( m_nType == SCREENEFFECT_MAPBASE_CHROMATIC_BLUR || m_nType == SCREENEFFECT_MAPBASE_CHROMATIC_ABERRATION )
{
if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
return;
// Create a keyvalue block to set these params
KeyValues *pKeys = new KeyValues( "keys" );
if ( pKeys == NULL )
return;
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 1 );
pKeys->SetInt( "stretch", m_nType == SCREENEFFECT_MAPBASE_CHROMATIC_ABERRATION );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "mapbase_chromatic_aberration", pKeys );
}
#endif
break;
}

View File

@ -88,8 +88,9 @@ void CDustEffect::RenderParticles( CParticleRenderIterator *pIterator )
void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
{
Vector vecWind;
#ifndef MAPBASE
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
#endif
CFuncDustParticle *pParticle = (CFuncDustParticle*)pIterator->GetFirst();
while ( pParticle )
@ -105,6 +106,9 @@ void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
}
else
{
#ifdef MAPBASE
vecWind = GetWindspeedAtLocation( pParticle->m_Pos );
#endif
for ( int i = 0 ; i < 2 ; i++ )
{
if ( pParticle->m_vVelocity[i] < vecWind[i] )

View File

@ -30,6 +30,9 @@ public:
// These are documented in the server-side entity.
public:
float m_fDisappearDist;
#ifdef MAPBASE
float m_fDisappearMaxDist;
#endif
};
@ -43,6 +46,9 @@ ConVar lod_TransitionDist("lod_TransitionDist", "800");
// Datatable..
IMPLEMENT_CLIENTCLASS_DT(C_Func_LOD, DT_Func_LOD, CFunc_LOD)
RecvPropFloat(RECVINFO(m_fDisappearDist)),
#ifdef MAPBASE
RecvPropFloat(RECVINFO(m_fDisappearMaxDist)),
#endif
END_RECV_TABLE()
@ -54,6 +60,9 @@ END_RECV_TABLE()
C_Func_LOD::C_Func_LOD()
{
m_fDisappearDist = 5000.0f;
#ifdef MAPBASE
m_fDisappearMaxDist = 0.0f;
#endif
}
//-----------------------------------------------------------------------------
@ -61,7 +70,11 @@ C_Func_LOD::C_Func_LOD()
//-----------------------------------------------------------------------------
unsigned char C_Func_LOD::GetClientSideFade()
{
#ifdef MAPBASE
return UTIL_ComputeEntityFade( this, m_fDisappearDist, m_fDisappearDist + (m_fDisappearMaxDist != 0 ? m_fDisappearMaxDist : lod_TransitionDist.GetFloat()), 1.0f );
#else
return UTIL_ComputeEntityFade( this, m_fDisappearDist, m_fDisappearDist + lod_TransitionDist.GetFloat(), 1.0f );
#endif
}

View File

@ -6,6 +6,9 @@
//===========================================================================//
#include "cbase.h"
#include "view_shared.h"
#ifdef MAPBASE
#include "viewrender.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@ -23,10 +26,27 @@ public:
virtual bool ShouldDraw();
#ifdef MAPBASE
virtual void OnDataChanged( DataUpdateType_t type );
ITexture *ReflectionRenderTarget();
ITexture *RefractionRenderTarget();
char m_iszReflectRenderTarget[64];
char m_iszRefractRenderTarget[64];
ITexture *m_pReflectRenderTarget;
ITexture *m_pRefractRenderTarget;
#endif
C_FuncReflectiveGlass *m_pNext;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncReflectiveGlass, DT_FuncReflectiveGlass, CFuncReflectiveGlass )
#ifdef MAPBASE
RecvPropString( RECVINFO( m_iszReflectRenderTarget ) ),
RecvPropString( RECVINFO( m_iszRefractRenderTarget ) ),
#endif
END_RECV_TABLE()
@ -47,6 +67,11 @@ C_FuncReflectiveGlass* GetReflectiveGlassList()
//-----------------------------------------------------------------------------
C_FuncReflectiveGlass::C_FuncReflectiveGlass()
{
#ifdef MAPBASE
m_iszReflectRenderTarget[0] = '\0';
m_iszRefractRenderTarget[0] = '\0';
#endif
g_ReflectiveGlassList.Insert( this );
}
@ -114,5 +139,111 @@ bool IsReflectiveGlassInView( const CViewSetup& view, cplane_t &plane )
return false;
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Iterates through reflective glass instead of just picking one
//-----------------------------------------------------------------------------
C_BaseEntity *NextReflectiveGlass( C_BaseEntity *pStart, const CViewSetup& view, cplane_t &plane,
const Frustum_t &frustum, ITexture **pRenderTargets )
{
// Early out if no cameras
C_FuncReflectiveGlass *pReflectiveGlass = NULL;
if (!pStart)
pReflectiveGlass = GetReflectiveGlassList();
else
pReflectiveGlass = ((C_FuncReflectiveGlass*)pStart)->m_pNext;
cplane_t localPlane;
Vector vecOrigin, vecWorld, vecDelta;
for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext )
{
if ( pReflectiveGlass->IsDormant() )
continue;
if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) )
continue;
Vector vecMins, vecMaxs;
pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs );
if ( R_CullBox( vecMins, vecMaxs, frustum ) )
continue;
const model_t *pModel = pReflectiveGlass->GetModel();
const matrix3x4_t& mat = pReflectiveGlass->EntityToWorldTransform();
int nCount = modelinfo->GetBrushModelPlaneCount( pModel );
for ( int i = 0; i < nCount; ++i )
{
modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin );
MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space
VectorTransform( vecOrigin, mat, vecWorld );
if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane
continue;
VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull
if ( vecDelta.Dot( plane.normal ) >= 0 )
continue;
if (pRenderTargets != NULL)
{
pRenderTargets[0] = pReflectiveGlass->ReflectionRenderTarget();
pRenderTargets[1] = pReflectiveGlass->RefractionRenderTarget();
}
return pReflectiveGlass;
}
}
return NULL;
}
void C_FuncReflectiveGlass::OnDataChanged( DataUpdateType_t type )
{
// Reset render textures
m_pReflectRenderTarget = NULL;
m_pRefractRenderTarget = NULL;
return BaseClass::OnDataChanged( type );
}
ITexture *C_FuncReflectiveGlass::ReflectionRenderTarget()
{
if (m_iszReflectRenderTarget[0] != '\0')
{
if (!m_pReflectRenderTarget)
{
// We don't use a CTextureReference for this because we don't want to shut down the texture on removal/change
m_pReflectRenderTarget = materials->FindTexture( m_iszReflectRenderTarget, TEXTURE_GROUP_RENDER_TARGET );
}
if (m_pReflectRenderTarget)
return m_pReflectRenderTarget;
}
return NULL;
//return GetWaterReflectionTexture();
}
ITexture *C_FuncReflectiveGlass::RefractionRenderTarget()
{
if (m_iszRefractRenderTarget[0] != '\0')
{
if (!m_pRefractRenderTarget)
{
// We don't use a CTextureReference for this because we don't want to shut down the texture on removal/change
m_pRefractRenderTarget = materials->FindTexture( m_iszRefractRenderTarget, TEXTURE_GROUP_RENDER_TARGET );
}
if (m_pRefractRenderTarget)
return m_pRefractRenderTarget;
}
return NULL;
//return GetWaterRefractionTexture();
}
#endif

View File

@ -21,6 +21,11 @@ class CViewSetup;
//-----------------------------------------------------------------------------
bool IsReflectiveGlassInView( const CViewSetup& view, cplane_t &plane );
#ifdef MAPBASE
C_BaseEntity *NextReflectiveGlass( C_BaseEntity *pStart, const CViewSetup& view, cplane_t &plane,
const Frustum_t &frustum, ITexture **pRenderTargets = NULL );
#endif
#endif // C_FUNC_REFLECTIVE_GLASS

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client handler for instruction players how to play
//
//=============================================================================//
#ifndef _C_GAMEINSTRUCTOR_H_
#define _C_GAMEINSTRUCTOR_H_
#include "GameEventListener.h"
#include "vgui_controls/PHandle.h"
class CBaseLesson;
struct LessonGroupConVarToggle_t
{
ConVarRef var;
char szLessonGroupName[ 64 ];
LessonGroupConVarToggle_t( const char *pchConVarName ) :
var( pchConVarName )
{
}
};
class C_GameInstructor : public CAutoGameSystemPerFrame, public CGameEventListener
{
public:
C_GameInstructor() : CAutoGameSystemPerFrame( "C_GameInstructor" )
{
m_bHasLoadedSaveData = false;
m_bDirtySaveData = false;
}
// Methods of IGameSystem
virtual bool Init( void );
virtual void Shutdown( void );
virtual void Update( float frametime );
void UpdateHiddenByOtherElements( void );
bool Mod_HiddenByOtherElements( void );
virtual void FireGameEvent( IGameEvent *event );
void DefineLesson( CBaseLesson *pLesson );
const CBaseLesson * GetLesson( const char *pchLessonName );
bool IsLessonOfSameTypeOpen( const CBaseLesson *pLesson ) const;
bool ReadSaveData( void );
bool WriteSaveData( void );
void RefreshDisplaysAndSuccesses( void );
void ResetDisplaysAndSuccesses( void );
void MarkDisplayed( const char *pchLessonName );
void MarkSucceeded( const char *pchLessonName );
void PlaySound( const char *pchSoundName );
bool OpenOpportunity( CBaseLesson *pLesson );
void DumpOpenOpportunities( void );
KeyValues * GetScriptKeys( void );
C_BasePlayer * GetLocalPlayer( void );
void EvaluateLessonsForGameRules( void );
void SetLessonGroupEnabled( const char *pszGroup, bool bEnabled );
// Mapbase needs this to be public for map-specific file system
void ReadLessonsFromFile( const char *pchFileName );
private:
void FindErrors( void );
bool UpdateActiveLesson( CBaseLesson *pLesson, const CBaseLesson *pRootLesson );
void UpdateInactiveLesson( CBaseLesson *pLesson );
CBaseLesson * GetLesson_Internal( const char *pchLessonName );
void StopAllLessons( void );
void CloseAllOpenOpportunities( void );
void CloseOpportunity( CBaseLesson *pLesson );
void InitLessonPrerequisites( void );
private:
CUtlVector < CBaseLesson* > m_Lessons;
CUtlVector < CBaseLesson* > m_OpenOpportunities;
CUtlVector < LessonGroupConVarToggle_t > m_LessonGroupConVarToggles;
KeyValues *m_pScriptKeys;
bool m_bNoDraw;
bool m_bHiddenDueToOtherElements;
int m_iCurrentPriority;
EHANDLE m_hLastSpectatedPlayer;
bool m_bSpectatedPlayerChanged;
char m_szPreviousStartSound[ 128 ];
float m_fNextStartSoundTime;
bool m_bHasLoadedSaveData;
bool m_bDirtySaveData;
};
C_GameInstructor &GetGameInstructor();
void GameInstructor_Init();
void GameInstructor_Shutdown();
#endif // _C_GAMEINSTRUCTOR_H_

View File

@ -95,18 +95,23 @@ extern PMaterialHandle g_Material_Spark;
//-----------------------------------------------------------------------------
void GetColorForSurface( trace_t *trace, Vector *color )
{
Vector baseColor, diffuseColor;
Vector end = trace->startpos + ( ( Vector )trace->endpos - ( Vector )trace->startpos ) * 1.1f;
Vector baseColor = vec3_invalid, diffuseColor;
const char *kind;
if ( trace->DidHitWorld() )
{
if ( trace->hitbox == 0 )
{
kind = "World";
Vector end = trace->startpos + ( trace->endpos - trace->startpos ) * 1.1f;
// If we hit the world, then ask the world for the fleck color
engine->TraceLineMaterialAndLighting( trace->startpos, end, diffuseColor, baseColor );
if ( !engine->TraceLineMaterialAndLighting( trace->startpos, end, diffuseColor, baseColor ) ) {
baseColor = vec3_invalid; // Make sure this wasn't modified
}
}
else
{
kind = "Static Prop";
// In this case we hit a static prop.
staticpropmgr->GetStaticPropMaterialColorAndLighting( trace, trace->hitbox - 1, diffuseColor, baseColor );
}
@ -117,20 +122,24 @@ void GetColorForSurface( trace_t *trace, Vector *color )
C_BaseEntity *pEnt = trace->m_pEnt;
if ( !pEnt )
{
Msg("Couldn't find surface in GetColorForSurface()\n");
color->x = 255;
color->y = 255;
color->z = 255;
return;
kind = "Null-Entity";
} else {
kind = "Entity";
ICollideable *pCollide = pEnt->GetCollideable();
int modelIndex = pCollide->GetCollisionModelIndex();
model_t* pModel = const_cast<model_t*>(modelinfo->GetModel( modelIndex ));
// Ask the model info about what we need to know
modelinfo->GetModelMaterialColorAndLighting( pModel, pCollide->GetCollisionOrigin(),
pCollide->GetCollisionAngles(), trace, diffuseColor, baseColor );
}
}
ICollideable *pCollide = pEnt->GetCollideable();
int modelIndex = pCollide->GetCollisionModelIndex();
model_t* pModel = const_cast<model_t*>(modelinfo->GetModel( modelIndex ));
// Ask the model info about what we need to know
modelinfo->GetModelMaterialColorAndLighting( pModel, pCollide->GetCollisionOrigin(),
pCollide->GetCollisionAngles(), trace, diffuseColor, baseColor );
if ( baseColor == vec3_invalid )
{
Warning( "Couldn't find surface color of %s\n", kind );
baseColor = Vector( .5f, .5f, .5f );
diffuseColor = engine->GetLightForPoint( trace->endpos, true );
}
//Get final light value

View File

@ -102,6 +102,10 @@ public:
C_LightGlowOverlay m_Glow;
float m_flGlowProxySize;
#ifdef MAPBASE
bool m_bDisabled;
#endif
};
static void RecvProxy_HDRColorScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
@ -123,6 +127,9 @@ IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_LightGlow, DT_LightGlow, CLightGlow )
RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
RecvPropFloat(RECVINFO(m_flGlowProxySize)),
#ifdef MAPBASE
RecvPropBool( RECVINFO( m_bDisabled ) ),
#endif
RecvPropFloat("HDRColorScale", 0, SIZEOF_IGNORE, 0, RecvProxy_HDRColorScale),
END_RECV_TABLE()
@ -202,7 +209,11 @@ void C_LightGlow::OnDataChanged( DataUpdateType_t updateType )
void C_LightGlow::ClientThink( void )
{
Vector mins = GetAbsOrigin();
#ifdef MAPBASE
if ( engine->IsBoxVisible( mins, mins ) && !m_bDisabled )
#else
if ( engine->IsBoxVisible( mins, mins ) )
#endif
{
m_Glow.Activate();
}

View File

@ -0,0 +1,27 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//
//=====================================================================================//
#include "cbase.h"
#include "c_movie_display.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_MovieDisplay, DT_MovieDisplay, CMovieDisplay )
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropBool( RECVINFO( m_bLooping ) ),
RecvPropBool( RECVINFO( m_bMuted ) ),
RecvPropString( RECVINFO( m_szMovieFilename ) ),
RecvPropString( RECVINFO( m_szGroupName ) ),
END_RECV_TABLE()
C_MovieDisplay::C_MovieDisplay()
{
}
C_MovieDisplay::~C_MovieDisplay()
{
}

View File

@ -0,0 +1,36 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef C_MOVIE_DISPLAY_H
#define C_MOVIE_DISPLAY_H
#include "cbase.h"
class C_MovieDisplay : public C_BaseEntity
{
public:
DECLARE_CLASS( C_MovieDisplay, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_MovieDisplay();
~C_MovieDisplay();
bool IsEnabled( void ) const { return m_bEnabled; }
bool IsLooping( void ) const { return m_bLooping; }
bool IsMuted(void) const { return m_bMuted; }
const char *GetMovieFilename( void ) const { return m_szMovieFilename; }
const char *GetGroupName( void ) const { return m_szGroupName; }
private:
bool m_bEnabled;
bool m_bLooping;
bool m_bMuted;
char m_szMovieFilename[128];
char m_szGroupName[128];
};
#endif //C_MOVIE_DISPLAY_H

View File

@ -32,6 +32,9 @@ public:
protected:
int m_iEffectIndex;
bool m_bActive;
#ifdef MAPBASE
bool m_bDestroyImmediately;
#endif
bool m_bOldActive;
float m_flStartTime; // Time at which the effect started
@ -39,6 +42,7 @@ protected:
EHANDLE m_hControlPointEnts[kMAXCONTROLPOINTS];
Vector m_vControlPointVecs[kMAXCONTROLPOINTS];
// SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ),
unsigned char m_iControlPointParents[kMAXCONTROLPOINTS];
@ -56,9 +60,13 @@ BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem )
RecvPropInt( RECVINFO( m_iEffectIndex ) ),
RecvPropBool( RECVINFO( m_bActive ) ),
#ifdef MAPBASE
RecvPropBool( RECVINFO( m_bDestroyImmediately ) ),
#endif
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY(m_vControlPointVecs), RecvPropVector( RECVINFO( m_vControlPointVecs[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt( RECVINFO(m_iControlPointParents[0]))),
RecvPropBool( RECVINFO( m_bWeatherEffect ) ),
END_RECV_TABLE();
@ -108,9 +116,18 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType )
SetNextClientThink( gpGlobals->curtime );
}
else
#ifdef MAPBASE
{
if (!m_bDestroyImmediately)
ParticleProp()->StopEmission();
else
ParticleProp()->StopEmissionAndDestroyImmediately();
}
#else
{
ParticleProp()->StopEmission();
}
#endif
}
}
}
@ -135,21 +152,41 @@ void C_ParticleSystem::ClientThink( void )
AssertMsg1( pEffect, "Particle system couldn't make %s", pszName );
if (pEffect)
{
for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
if (m_vControlPointVecs[0] != GetAbsOrigin() && m_hControlPointEnts[0] == NULL)
{
CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
if ( pOnEntity )
// we are using info_particle_system_coordinate
for (int i = 0; i < kMAXCONTROLPOINTS; ++i)
{
ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
ParticleProp()->AddControlPoint(pEffect, i + 1, this, PATTACH_WORLDORIGIN, 0, m_vControlPointVecs[i] - GetAbsOrigin());
AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS,
"Particle system specified bogus control point parent (%d) for point %d.",
m_iControlPointParents[i], i);
if (m_iControlPointParents[i] != 0)
{
pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]);
}
}
AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
"Particle system specified bogus control point parent (%d) for point %d.",
m_iControlPointParents[i], i );
if (m_iControlPointParents[i] != 0)
}
else
{
for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
{
pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
if ( pOnEntity )
{
ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
}
AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
"Particle system specified bogus control point parent (%d) for point %d.",
m_iControlPointParents[i], i );
if (m_iControlPointParents[i] != 0)
{
pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
}
}
}

View File

@ -429,8 +429,10 @@ void CPixelVisibilityQuery::IssueQuery( IMatRenderContext *pRenderContext, float
return;
}
}
#ifndef MAPBASE // Mapbase can also query visibility several times via multiple point_cameras, etc.
#ifndef PORTAL // FIXME: In portal we query visibility multiple times per frame because of portal renders!
Assert ( ( m_frameIssued != gpGlobals->framecount ) || UseVR() );
#endif
#endif
m_frameIssued = gpGlobals->framecount;

View File

@ -83,6 +83,10 @@ public:
bool m_bSlowMovement;
CNetworkString( m_szScriptOverlayMaterial, MAX_PATH );
//Tony; added so tonemap controller can work in multiplayer with inputs.
tonemap_params_t m_TonemapParams;
};
#endif // C_PLAYERLOCALDATA_H

View File

@ -26,6 +26,10 @@ IMPLEMENT_CLIENTCLASS_DT( C_PointCamera, DT_PointCamera, CPointCamera )
RecvPropInt( RECVINFO( m_bFogRadial ) ),
RecvPropInt( RECVINFO( m_bActive ) ),
RecvPropInt( RECVINFO( m_bUseScreenAspectRatio ) ),
#ifdef MAPBASE
RecvPropInt( RECVINFO( m_iSkyMode ) ),
RecvPropString( RECVINFO( m_iszRenderTarget ) ),
#endif
END_RECV_TABLE()
C_EntityClassList<C_PointCamera> g_PointCameraList;
@ -42,6 +46,10 @@ C_PointCamera::C_PointCamera()
m_bFogEnable = false;
m_bFogRadial = false;
#ifdef MAPBASE
m_iszRenderTarget[0] = '\0';
#endif
g_PointCameraList.Insert( this );
}
@ -55,6 +63,16 @@ bool C_PointCamera::ShouldDraw()
return false;
}
void C_PointCamera::OnDataChanged( DataUpdateType_t type )
{
#ifdef MAPBASE
// Reset render texture
m_pRenderTarget = NULL;
#endif
return BaseClass::OnDataChanged( type );
}
float C_PointCamera::GetFOV()
{
return m_FOV;
@ -119,4 +137,31 @@ void C_PointCamera::GetToolRecordingState( KeyValues *msg )
msg->SetPtr( "monitor", &state );
}
#ifdef MAPBASE
extern ITexture *GetCameraTexture( void );
extern void AddReleaseFunc( void );
ITexture *C_PointCamera::RenderTarget()
{
if (m_iszRenderTarget[0] != '\0')
{
if (!m_pRenderTarget)
{
// We don't use a CTextureReference for this because we don't want to shut down the texture on removal/change
m_pRenderTarget = materials->FindTexture( m_iszRenderTarget, TEXTURE_GROUP_RENDER_TARGET );
}
if (m_pRenderTarget)
return m_pRenderTarget;
}
return GetCameraTexture();
}
IMPLEMENT_CLIENTCLASS_DT( C_PointCameraOrtho, DT_PointCameraOrtho, CPointCameraOrtho )
RecvPropInt( RECVINFO( m_bOrtho ) ),
RecvPropArray( RecvPropFloat( RECVINFO( m_OrthoDimensions[0] ) ), m_OrthoDimensions ),
END_RECV_TABLE()
#endif

View File

@ -29,6 +29,9 @@ public:
// C_BaseEntity.
virtual bool ShouldDraw();
// Mapbase uses this for m_iszRenderTarget
virtual void OnDataChanged( DataUpdateType_t type );
float GetFOV();
float GetResolution();
bool IsFogEnabled();
@ -38,6 +41,14 @@ public:
float GetFogEnd();
bool GetFogRadial();
bool UseScreenAspectRatio() const { return m_bUseScreenAspectRatio; }
#ifdef MAPBASE
virtual bool IsOrtho() const { return false; }
virtual void GetOrthoDimensions(float &up, float &dn, float &lf, float &rt) const {}
SkyboxVisibility_t SkyMode() { return m_iSkyMode; }
ITexture *RenderTarget();
#endif
virtual void GetToolRecordingState( KeyValues *msg );
@ -52,11 +63,37 @@ private:
bool m_bFogRadial;
bool m_bActive;
bool m_bUseScreenAspectRatio;
#ifdef MAPBASE
SkyboxVisibility_t m_iSkyMode;
ITexture *m_pRenderTarget;
char m_iszRenderTarget[64];
#endif
public:
C_PointCamera *m_pNext;
};
#ifdef MAPBASE
class C_PointCameraOrtho : public C_PointCamera
{
public:
DECLARE_CLASS( C_PointCameraOrtho, C_PointCamera );
DECLARE_CLIENTCLASS();
public:
bool IsOrtho() const { return m_bOrtho; }
void GetOrthoDimensions( float &up, float &dn, float &lf, float &rt ) const
{
up = m_OrthoDimensions[0], dn = m_OrthoDimensions[1];
lf = m_OrthoDimensions[2], rt = m_OrthoDimensions[3];
}
private:
bool m_bOrtho;
float m_OrthoDimensions[4];
};
#endif
C_PointCamera *GetPointCameraList();
#endif // C_POINTCAMERA_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: stores map postprocess params
//
//=============================================================================
#include "cbase.h"
#include "c_postprocesscontroller.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_PostProcessController, DT_PostProcessController, CPostProcessController )
RecvPropArray3( RECVINFO_NAME( m_PostProcessParameters.m_flParameters[0], m_flPostProcessParameters ), POST_PROCESS_PARAMETER_COUNT, RecvPropFloat( RECVINFO_NAME( m_PostProcessParameters.m_flParameters[0], m_flPostProcessParameters[0] ) ) ),
RecvPropBool( RECVINFO(m_bMaster) )
END_RECV_TABLE()
C_PostProcessController* C_PostProcessController::ms_pMasterController = nullptr;
//-----------------------------------------------------------------------------
C_PostProcessController::C_PostProcessController()
: m_bMaster( false )
{
if ( ms_pMasterController == nullptr)
{
ms_pMasterController = this;
}
}
//-----------------------------------------------------------------------------
C_PostProcessController::~C_PostProcessController()
{
if ( ms_pMasterController == this )
{
ms_pMasterController = nullptr;
}
}
void C_PostProcessController::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
if ( m_bMaster )
{
ms_pMasterController = this;
}
}
#ifdef MAPBASE
// Prevents parameters from fading after a save/restore
bool g_bPostProcessNeedsRestore = false;
void C_PostProcessController::OnRestore()
{
BaseClass::OnRestore();
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer && pPlayer->GetActivePostProcessController() == this )
{
// Tell clientmode this is part of a save/restore
g_bPostProcessNeedsRestore = true;
}
}
#endif

View File

@ -0,0 +1,33 @@
#pragma once
#include "postprocess_shared.h"
//=============================================================================
//
// Class Postprocess Controller:
//
class C_PostProcessController : public C_BaseEntity
{
DECLARE_CLASS( C_PostProcessController, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_PostProcessController();
virtual ~C_PostProcessController();
virtual void PostDataUpdate( DataUpdateType_t updateType );
static C_PostProcessController* GetMasterController() { return ms_pMasterController; }
PostProcessParameters_t m_PostProcessParameters;
#ifdef MAPBASE
// Prevents fade time from being used in save/restore
virtual void OnRestore();
#endif
private:
bool m_bMaster;
static C_PostProcessController* ms_pMasterController;
};

View File

@ -24,6 +24,11 @@ BEGIN_NETWORK_TABLE( CDynamicProp, DT_DynamicProp )
RecvPropBool(RECVINFO(m_bUseHitboxesForRenderBox)),
END_NETWORK_TABLE()
#ifdef MAPBASE_VSCRIPT
// Allows client-side VScript to create dynamic props via CreateProp()
LINK_ENTITY_TO_CLASS( prop_dynamic, C_DynamicProp );
#endif
C_DynamicProp::C_DynamicProp( void )
{
m_iCachedFrameCount = -1;

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,9 @@ public:
DECLARE_CLASS( C_RopeKeyframe, C_BaseEntity );
DECLARE_CLIENTCLASS();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
private:
@ -107,7 +110,9 @@ public:
// Get the rope material data.
IMaterial *GetSolidMaterial( void );
#ifndef MAPBASE
IMaterial *GetBackMaterial( void );
#endif
struct BuildRopeQueuedData_t
{
@ -119,7 +124,11 @@ public:
float m_Slack;
};
#ifdef MAPBASE
void BuildRope( RopeSegData_t *pRopeSegment, const Vector &vCurrentViewForward, const Vector &vCurrentViewOrigin, BuildRopeQueuedData_t *pQueuedData );
#else
void BuildRope( RopeSegData_t *pRopeSegment, const Vector &vCurrentViewForward, const Vector &vCurrentViewOrigin, BuildRopeQueuedData_t *pQueuedData, bool bQueued );
#endif
// C_BaseEntity overrides.
public:
@ -136,6 +145,11 @@ public:
virtual bool GetAttachment( int number, Vector &origin );
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );
#ifdef MAPBASE
const Vector &GetNodePosition( int index );
int GetNumNodes();
#endif
private:
void FinishInit( const char *pMaterialName );
@ -160,6 +174,11 @@ private:
void ReceiveMessage( int classID, bf_read &msg );
bool CalculateEndPointAttachment( C_BaseEntity *pEnt, int iAttachment, Vector &vPos, QAngle *pAngles );
#ifdef MAPBASE_VSCRIPT
HSCRIPT ScriptGetStartEntity() { return ToHScript( GetStartEntity() ); }
HSCRIPT ScriptGetEndEntity() { return ToHScript( GetEndEntity() ); }
#endif
private:
// Track which links touched something last frame. Used to prevent wind from gusting on them.
@ -196,19 +215,29 @@ private:
float m_TextureScale; // pixels per inch
int m_fLockedPoints; // Which points are locked down.
#ifdef MAPBASE
int m_nChangeCount;
#endif
float m_Width;
CPhysicsDelegate m_PhysicsDelegate;
IMaterial *m_pMaterial;
#ifndef MAPBASE
IMaterial *m_pBackMaterial; // Optional translucent background material for the rope to help reduce aliasing.
#endif
int m_TextureHeight; // Texture height, for texture scale calculations.
// Instantaneous force
#ifdef MAPBASE
Vector m_vecImpulse;
Vector m_vecPreviousImpulse;
#else
Vector m_flImpulse;
Vector m_flPreviousImpulse;
#endif
// Simulated wind gusts.
float m_flCurrentGustTimer;
@ -253,7 +282,9 @@ public:
virtual void ResetRenderCache( void ) = 0;
virtual void AddToRenderCache( C_RopeKeyframe *pRope ) = 0;
virtual void DrawRenderCache( bool bShadowDepth ) = 0;
#ifndef MAPBASE
virtual void OnRenderStart( void ) = 0;
#endif
virtual void SetHolidayLightMode( bool bHoliday ) = 0;
virtual bool IsHolidayLightMode( void ) = 0;
virtual int GetHolidayLightStyle( void ) = 0;

View File

@ -622,7 +622,7 @@ void C_SceneEntity::DispatchStartSpeak( CChoreoScene *scene, C_BaseFlex *actor,
es.m_pSoundName = event->GetParameters();
EmitSound( filter, actor->entindex(), es );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
// Close captioning only on master token no matter what...
if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER )
@ -752,20 +752,72 @@ CChoreoStringPool g_ChoreoStringPool;
CChoreoScene *C_SceneEntity::LoadScene( const char *filename )
{
#ifdef MAPBASE
char loadfile[MAX_PATH];
#else
char loadfile[ 512 ];
#endif
Q_strncpy( loadfile, filename, sizeof( loadfile ) );
Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) );
Q_FixSlashes( loadfile );
#ifdef MAPBASE
//
// Raw scene file support
//
void *pBuffer = 0;
size_t bufsize = scenefilecache->GetSceneBufferSize( loadfile );
CChoreoScene *pScene = NULL;
if ( bufsize > 0 )
{
// Definitely in scenes.image
pBuffer = malloc( bufsize );
if ( !scenefilecache->GetSceneData( filename, (byte *)pBuffer, bufsize ) )
{
free( pBuffer );
return NULL;
}
if ( IsBufferBinaryVCD( (char*)pBuffer, bufsize ) )
{
pScene = new CChoreoScene( this );
CUtlBuffer buf( pBuffer, bufsize, CUtlBuffer::READ_ONLY );
if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) )
{
Warning( "Unable to restore scene '%s'\n", loadfile );
delete pScene;
pScene = NULL;
}
}
}
else if (filesystem->ReadFileEx( loadfile, "MOD", &pBuffer, true ))
{
// Not in scenes.image, but it's a raw file
g_TokenProcessor.SetBuffer((char*)pBuffer);
pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf );
}
else
{
// Abandon ship
return NULL;
}
if(pScene)
{
pScene->SetPrintFunc( Scene_Printf );
pScene->SetEventCallbackInterface( this );
}
#else
char *pBuffer = NULL;
size_t bufsize = scenefilecache->GetSceneBufferSize( loadfile );
if ( bufsize <= 0 )
return NULL;
pBuffer = new char[ bufsize ];
pBuffer = malloc( bufsize );
if ( !scenefilecache->GetSceneData( filename, (byte *)pBuffer, bufsize ) )
{
delete[] pBuffer;
free( pBuffer );
return NULL;
}
@ -791,8 +843,9 @@ CChoreoScene *C_SceneEntity::LoadScene( const char *filename )
g_TokenProcessor.SetBuffer( pBuffer );
pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf );
}
#endif
delete[] pBuffer;
free( pBuffer );
return pScene;
}
@ -859,7 +912,7 @@ void C_SceneEntity::UnloadScene( void )
//-----------------------------------------------------------------------------
void C_SceneEntity::DispatchStartFlexAnimation( CChoreoScene *scene, C_BaseFlex *actor, CChoreoEvent *event )
{
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
}
//-----------------------------------------------------------------------------
@ -879,7 +932,7 @@ void C_SceneEntity::DispatchEndFlexAnimation( CChoreoScene *scene, C_BaseFlex *a
//-----------------------------------------------------------------------------
void C_SceneEntity::DispatchStartExpression( CChoreoScene *scene, C_BaseFlex *actor, CChoreoEvent *event )
{
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
}
//-----------------------------------------------------------------------------
@ -903,7 +956,7 @@ void C_SceneEntity::DispatchStartGesture( CChoreoScene *scene, C_BaseFlex *actor
if ( !Q_stricmp( event->GetName(), "NULL" ) )
return;
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
}
//-----------------------------------------------------------------------------
@ -918,7 +971,7 @@ void C_SceneEntity::DispatchProcessGesture( CChoreoScene *scene, C_BaseFlex *act
return;
actor->RemoveSceneEvent( scene, event, false );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
}
//-----------------------------------------------------------------------------
@ -941,7 +994,7 @@ void C_SceneEntity::DispatchEndGesture( CChoreoScene *scene, C_BaseFlex *actor,
//-----------------------------------------------------------------------------
void C_SceneEntity::DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
{
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
}
//-----------------------------------------------------------------------------
@ -951,7 +1004,7 @@ void C_SceneEntity::DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor
void C_SceneEntity::DispatchProcessSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
{
actor->RemoveSceneEvent( scene, event, false );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
}
//-----------------------------------------------------------------------------
@ -1156,4 +1209,4 @@ void C_SceneEntity::PrefetchAnimBlocks( CChoreoScene *pScene )
return;
Msg( "%d of %d animations resident\n", nResident, nChecked );
}
}

View File

@ -32,13 +32,24 @@ private:
color32 m_shadowColor;
float m_flShadowMaxDist;
bool m_bDisableShadows;
#ifdef MAPBASE
bool m_bEnableLocalLightShadows;
#endif
};
IMPLEMENT_CLIENTCLASS_DT(C_ShadowControl, DT_ShadowControl, CShadowControl)
RecvPropVector(RECVINFO(m_shadowDirection)),
#ifdef MAPBASE
/*RecvPropInt(RECVINFO(m_shadowColor), 0, RecvProxy_Int32ToColor32),*/
RecvPropInt(RECVINFO(m_shadowColor), 0, RecvProxy_IntToColor32),
#else
RecvPropInt(RECVINFO(m_shadowColor)),
#endif
RecvPropFloat(RECVINFO(m_flShadowMaxDist)),
RecvPropBool(RECVINFO(m_bDisableShadows)),
#ifdef MAPBASE
RecvPropBool(RECVINFO(m_bEnableLocalLightShadows)),
#endif
END_RECV_TABLE()
@ -54,6 +65,9 @@ void C_ShadowControl::OnDataChanged(DataUpdateType_t updateType)
g_pClientShadowMgr->SetShadowColor( m_shadowColor.r, m_shadowColor.g, m_shadowColor.b );
g_pClientShadowMgr->SetShadowDistance( m_flShadowMaxDist );
g_pClientShadowMgr->SetShadowsDisabled( m_bDisableShadows );
#ifdef DYNAMIC_RTT_SHADOWS
g_pClientShadowMgr->SetShadowFromWorldLightsEnabled( m_bEnableLocalLightShadows );
#endif
}
//------------------------------------------------------------------------------

View File

@ -207,6 +207,9 @@ public:
// "dsp_volume"
void ProcessDSPVolume( KeyValues *pKey, subsoundscapeparams_t &params );
#ifdef MAPBASE // Moved to public space
void AddSoundScapeFile( const char *filename );
#endif
private:
@ -215,7 +218,9 @@ private:
return gpGlobals->framecount == m_nRestoreFrame ? true : false;
}
#ifndef MAPBASE // Moved to public space
void AddSoundScapeFile( const char *filename );
#endif
void TouchPlayLooping( KeyValues *pAmbient );
void TouchPlayRandom( KeyValues *pPlayRandom );
@ -265,6 +270,13 @@ void Soundscape_Update( audioparams_t &audio )
g_SoundscapeSystem.UpdateAudioParams( audio );
}
#ifdef MAPBASE
void Soundscape_AddFile( const char *szFile )
{
g_SoundscapeSystem.AddSoundScapeFile(szFile);
}
#endif
#define SOUNDSCAPE_MANIFEST_FILE "scripts/soundscapes_manifest.txt"
void C_SoundscapeSystem::AddSoundScapeFile( const char *filename )
@ -310,6 +322,16 @@ bool C_SoundscapeSystem::Init()
mapSoundscapeFilename = VarArgs( "scripts/soundscapes_%s.txt", mapname );
}
#ifdef MAPBASE
if (filesystem->FileExists(VarArgs("maps/%s_soundscapes.txt", mapname)))
{
// A Mapbase-specific file exists. Load that instead.
// Any additional soundscape files, like the original scripts/soundscapes version,
// could be loaded through #include and/or #base.
mapSoundscapeFilename = VarArgs("maps/%s_soundscapes.txt", mapname);
}
#endif
KeyValues *manifest = new KeyValues( SOUNDSCAPE_MANIFEST_FILE );
if ( filesystem->LoadKeyValues( *manifest, IFileSystem::TYPE_SOUNDSCAPE, SOUNDSCAPE_MANIFEST_FILE, "GAME" ) )
{

View File

@ -24,4 +24,8 @@ extern void Soundscape_Update( audioparams_t &audio );
// sounds are still playing when they're not.
void Soundscape_OnStopAllSounds();
#ifdef MAPBASE
void Soundscape_AddFile( const char *szFile );
#endif
#endif // C_SOUNDSCAPE_H

View File

@ -64,7 +64,12 @@ void C_TELargeFunnel::CreateFunnel( void )
float ratio = 0.25;
float invratio = 1 / ratio;
#ifdef MAPBASE
// Uh...figure out how to fix this
PMaterialHandle hMaterial = pSimple->GetPMaterial( "sprites/flare6" );
#else
PMaterialHandle hMaterial = pSimple->GetPMaterial( "sprites/flare6" );
#endif
for ( i = -256 ; i <= 256 ; i += 24 ) //24 from 32.. little more dense
{

View File

@ -597,8 +597,12 @@ bool C_LocalTempEntity::Frame( float frametime, int framenumber )
if ( flags & FTENT_WINDBLOWN )
{
#ifdef MAPBASE
Vector vecWind = GetWindspeedAtLocation( GetAbsOrigin() );
#else
Vector vecWind;
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
#endif
for ( int i = 0 ; i < 2 ; i++ )
{
@ -1860,6 +1864,9 @@ void CTempEnts::MuzzleFlash( const Vector& pos1, const QAngle& angles, int type,
// UNDONE: These need their own effects/sprites. For now use the pistol
// SMG1
#if defined ( HL2MP ) // HACK for hl2mp, make the default muzzleflash the smg muzzleflash for weapons like the RPG that are using 'type 0'
default:
#endif // HL2MP
case MUZZLEFLASH_SMG1:
if ( firstPerson )
{
@ -1897,10 +1904,12 @@ void CTempEnts::MuzzleFlash( const Vector& pos1, const QAngle& angles, int type,
}
break;
#if !defined ( HL2MP ) // HACK for hl2mp, make the default muzzleflash the smg muzzleflash for weapons like the RPG that are using 'type 0'
default:
// There's no supported muzzle flash for the type specified!
Assert(0);
break;
#endif // HL2MP
}
#endif

View File

@ -54,7 +54,12 @@ public:
flFOV = m_flFOV;
}
virtual void DrawHudElements();
#ifdef MAPBASE
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return m_bAllowStandardWeapons; }
bool m_bAllowStandardWeapons;
#else
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
#endif
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
virtual C_BaseCombatCharacter *GetPassenger( int nRole );
virtual int GetPassengerRole( C_BaseCombatCharacter *pPassenger );
@ -107,6 +112,9 @@ IMPLEMENT_CLIENTCLASS_DT(C_PropVehicleChoreoGeneric, DT_PropVehicleChoreoGeneric
RecvPropFloat( RECVINFO( m_vehicleView.flYawMax ) ),
RecvPropFloat( RECVINFO( m_vehicleView.flPitchMin ) ),
RecvPropFloat( RECVINFO( m_vehicleView.flPitchMax ) ),
#ifdef MAPBASE
RecvPropBool( RECVINFO( m_bAllowStandardWeapons ) ),
#endif
END_RECV_TABLE()

View File

@ -38,10 +38,14 @@ extern vgui::IInputInternal *g_InputInternal;
#define VGUI_SCREEN_MODE_RADIUS 80
//Precache the materials
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectVGuiScreen )
CLIENTEFFECT_MATERIAL( "engine/writez" )
CLIENTEFFECT_REGISTER_BEGIN(PrecacheEffectVGuiScreen)
CLIENTEFFECT_MATERIAL("engine/writez")
CLIENTEFFECT_REGISTER_END()
#ifdef MAPBASE
C_EntityClassList<C_VGuiScreen> g_VGUIScreenList;
template <> C_VGuiScreen* C_EntityClassList<C_VGuiScreen>::m_pClassList = NULL;
#endif // MAPBASE
IMPLEMENT_CLIENTCLASS_DT(C_VGuiScreen, DT_VGuiScreen, CVGuiScreen)
RecvPropFloat( RECVINFO(m_flWidth) ),
RecvPropFloat( RECVINFO(m_flHeight) ),
@ -67,11 +71,19 @@ C_VGuiScreen::C_VGuiScreen()
m_WriteZMaterial.Init( "engine/writez", TEXTURE_GROUP_VGUI );
m_OverlayMaterial.Init( m_WriteZMaterial );
#ifdef MAPBASE
g_VGUIScreenList.Insert(this);
#endif // MAPBASE
}
C_VGuiScreen::~C_VGuiScreen()
{
DestroyVguiScreen();
#ifdef MAPBASE
g_VGUIScreenList.Remove(this);
#endif // MAPBASE
}
//-----------------------------------------------------------------------------
@ -381,34 +393,69 @@ void C_VGuiScreen::ClientThink( void )
int px = (int)(u * m_nPixelWidth + 0.5f);
int py = (int)(v * m_nPixelHeight + 0.5f);
#ifndef MAPBASE
// Generate mouse input commands
if ((px != m_nOldPx) || (py != m_nOldPy))
{
g_InputInternal->InternalCursorMoved( px, py );
g_InputInternal->InternalCursorMoved(px, py);
m_nOldPx = px;
m_nOldPy = py;
}
if (m_nButtonPressed & IN_ATTACK)
{
g_InputInternal->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_PRESSED );
g_InputInternal->SetMouseCodeState(MOUSE_LEFT, vgui::BUTTON_PRESSED);
g_InputInternal->InternalMousePressed(MOUSE_LEFT);
}
if (m_nButtonPressed & IN_ATTACK2)
{
g_InputInternal->SetMouseCodeState( MOUSE_RIGHT, vgui::BUTTON_PRESSED );
g_InputInternal->InternalMousePressed( MOUSE_RIGHT );
g_InputInternal->SetMouseCodeState(MOUSE_RIGHT, vgui::BUTTON_PRESSED);
g_InputInternal->InternalMousePressed(MOUSE_RIGHT);
}
if ( (m_nButtonReleased & IN_ATTACK) || m_bLoseThinkNextFrame) // for a button release on loosing focus
if ((m_nButtonReleased & IN_ATTACK) || m_bLoseThinkNextFrame) // for a button release on loosing focus
{
g_InputInternal->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_RELEASED );
g_InputInternal->InternalMouseReleased( MOUSE_LEFT );
g_InputInternal->SetMouseCodeState(MOUSE_LEFT, vgui::BUTTON_RELEASED);
g_InputInternal->InternalMouseReleased(MOUSE_LEFT);
}
if (m_nButtonReleased & IN_ATTACK2)
{
g_InputInternal->SetMouseCodeState( MOUSE_RIGHT, vgui::BUTTON_RELEASED );
g_InputInternal->InternalMouseReleased( MOUSE_RIGHT );
g_InputInternal->SetMouseCodeState(MOUSE_RIGHT, vgui::BUTTON_RELEASED);
g_InputInternal->InternalMouseReleased(MOUSE_RIGHT);
}
#else
vgui::VPANEL focus = g_InputInternal->GetMouseOver();
// Generate mouse input commands
if ((px != m_nOldPx) || (py != m_nOldPy))
{
g_InputInternal->UpdateCursorPosInternal(px, py);
m_nOldPx = px;
m_nOldPy = py;
focus = pPanel->IsWithinTraverse(px, py, true);
g_InputInternal->SetMouseFocus(focus);
vgui::ivgui()->PostMessage(focus, new KeyValues("CursorMoved", "xpos", px, "ypos", py), NULL);
}
for (int i = 0; i < 2; i++)
{
const int nBit = i ? IN_ATTACK2 : (IN_ATTACK | IN_USE);
const vgui::MouseCode nButton = i ? MOUSE_RIGHT : MOUSE_LEFT;
if ((m_nButtonReleased & nBit) || ((m_nButtonState & nBit) && m_bLoseThinkNextFrame)) // for a button release on loosing focus
{
g_InputInternal->SetMouseCodeState(nButton, vgui::BUTTON_RELEASED);
vgui::ivgui()->PostMessage(focus, new KeyValues("MouseReleased", "code", nButton), NULL);
}
else if (m_nButtonPressed & nBit)
{
g_InputInternal->SetMouseCodeState(nButton, vgui::BUTTON_PRESSED);
vgui::ivgui()->PostMessage(focus, new KeyValues("MousePressed", "code", nButton), NULL);
}
}
#endif // !MAPBASE
if ( m_bLoseThinkNextFrame == true )
{
@ -592,6 +639,7 @@ bool C_VGuiScreen::IsInputOnlyToOwner( void )
return (m_fScreenFlags & VGUI_SCREEN_ONLY_USABLE_BY_OWNER) != 0;
}
#ifndef MAPBASE
//-----------------------------------------------------------------------------
//
// Enumator class for finding vgui screens close to the local player
@ -599,29 +647,29 @@ bool C_VGuiScreen::IsInputOnlyToOwner( void )
//-----------------------------------------------------------------------------
class CVGuiScreenEnumerator : public IPartitionEnumerator
{
DECLARE_CLASS_GAMEROOT( CVGuiScreenEnumerator, IPartitionEnumerator );
DECLARE_CLASS_GAMEROOT(CVGuiScreenEnumerator, IPartitionEnumerator);
public:
virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
virtual IterationRetval_t EnumElement(IHandleEntity* pHandleEntity);
int GetScreenCount();
C_VGuiScreen *GetVGuiScreen( int index );
C_VGuiScreen* GetVGuiScreen(int index);
private:
CUtlVector< CHandle< C_VGuiScreen > > m_VguiScreens;
};
IterationRetval_t CVGuiScreenEnumerator::EnumElement( IHandleEntity *pHandleEntity )
IterationRetval_t CVGuiScreenEnumerator::EnumElement(IHandleEntity* pHandleEntity)
{
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
if ( pEnt == NULL )
C_BaseEntity* pEnt = ClientEntityList().GetBaseEntityFromHandle(pHandleEntity->GetRefEHandle());
if (pEnt == NULL)
return ITERATION_CONTINUE;
// FIXME.. pretty expensive...
C_VGuiScreen *pScreen = dynamic_cast<C_VGuiScreen*>(pEnt);
if ( pScreen )
C_VGuiScreen* pScreen = dynamic_cast<C_VGuiScreen*>(pEnt);
if (pScreen)
{
int i = m_VguiScreens.AddToTail( );
m_VguiScreens[i].Set( pScreen );
int i = m_VguiScreens.AddToTail();
m_VguiScreens[i].Set(pScreen);
}
return ITERATION_CONTINUE;
@ -632,10 +680,12 @@ int CVGuiScreenEnumerator::GetScreenCount()
return m_VguiScreens.Count();
}
C_VGuiScreen *CVGuiScreenEnumerator::GetVGuiScreen( int index )
C_VGuiScreen* CVGuiScreenEnumerator::GetVGuiScreen(int index)
{
return m_VguiScreens[index].Get();
}
}
#endif // !MAPBASE
//-----------------------------------------------------------------------------
@ -669,18 +719,29 @@ C_BaseEntity *FindNearbyVguiScreen( const Vector &viewPosition, const QAngle &vi
Ray_t lookRay;
lookRay.Init( viewPosition, lookEnd );
#ifndef MAPBASE
// Look for vgui screens that are close to the player
CVGuiScreenEnumerator localScreens;
::partition->EnumerateElementsInSphere( PARTITION_CLIENT_NON_STATIC_EDICTS, viewPosition, VGUI_SCREEN_MODE_RADIUS, false, &localScreens );
#endif // !MAPBASE
Vector vecOut, vecViewDelta;
float flBestDist = 2.0f;
C_VGuiScreen *pBestScreen = NULL;
#ifndef MAPBASE
for (int i = localScreens.GetScreenCount(); --i >= 0; )
#else
for (C_VGuiScreen* pScreen = g_VGUIScreenList.m_pClassList; pScreen != NULL; pScreen = pScreen->m_pNext)
#endif // !MAPBASE
{
C_VGuiScreen *pScreen = localScreens.GetVGuiScreen(i);
#ifndef MAPBASE
C_VGuiScreen* pScreen = localScreens.GetVGuiScreen(i);
#else
// Skip if out of PVS
if (pScreen->IsDormant())
continue;
#endif
if ( pScreen->IsAttachedToViewModel() )
continue;
@ -829,11 +890,21 @@ vgui::Panel *CVGuiScreenPanel::CreateControlByName(const char *controlName)
//-----------------------------------------------------------------------------
// Purpose: Called when the user presses a button
//-----------------------------------------------------------------------------
void CVGuiScreenPanel::OnCommand( const char *command)
void CVGuiScreenPanel::OnCommand(const char* command)
{
if ( Q_stricmp( command, "vguicancel" ) )
if (Q_stricmp(command, "vguicancel"))
{
engine->ClientCmd( const_cast<char *>( command ) );
#ifdef MAPBASE
if (m_hEntity && m_hEntity->IsServerEntity())
{
KeyValues* pCommand = new KeyValues("EntityCommand");
pCommand->SetInt("entindex", m_hEntity->index);
pCommand->SetString("command_data", command);
engine->ServerCmdKeyValues(pCommand);
}
else
#endif
engine->ClientCmd(const_cast<char*>(command));
}
BaseClass::OnCommand(command);

View File

@ -66,6 +66,10 @@ class C_VGuiScreen : public C_BaseEntity
public:
DECLARE_CLIENTCLASS();
#ifdef MAPBASE
C_VGuiScreen* m_pNext;
#endif // MAPBASE
C_VGuiScreen();
~C_VGuiScreen();
@ -112,6 +116,15 @@ public:
C_BasePlayer *GetPlayerOwner( void );
bool IsInputOnlyToOwner( void );
#ifdef MAPBASE
void GetSize( float &width, float &height ) const { width = m_flWidth; height = m_flHeight; }
void GetPixelSize( int &width, int &height ) const { width = m_nPixelWidth; height = m_nPixelHeight; }
void SetWidth( float flWidth ) { m_flWidth = flWidth; }
void SetHeight( float flHeight ) { m_flHeight = flHeight; }
void SetPixelWidth( int nWidth ) { m_nPixelWidth = nWidth; }
void SetPixelHeight( int nHeight ) { m_nPixelHeight = nHeight; }
#endif
private:
// Vgui screen management
void CreateVguiScreen( const char *pTypeName );

View File

@ -13,6 +13,9 @@
#include "ivieweffects.h"
#include "shake.h"
#include "eventlist.h"
#ifdef MAPBASE
#include "mapentities_shared.h"
#endif
// NVNT haptic include for notification of world precache
#include "haptics/haptic_utils.h"
// memdbgon must be the last include file in a .cpp file!!!
@ -59,8 +62,15 @@ BEGIN_RECV_TABLE( C_World, DT_World )
RecvPropFloat(RECVINFO(m_flMinPropScreenSpaceWidth)),
RecvPropString(RECVINFO(m_iszDetailSpriteMaterial)),
RecvPropInt(RECVINFO(m_bColdWorld)),
#ifdef MAPBASE
RecvPropString(RECVINFO(m_iszChapterTitle)),
#endif
END_RECV_TABLE()
#ifdef MAPBASE_VSCRIPT
extern bool VScriptClientInit();
#endif
C_World::C_World( void )
{
@ -76,6 +86,11 @@ bool C_World::Init( int entnum, int iSerialNum )
ActivityList_Init();
EventList_Init();
#ifdef MAPBASE_VSCRIPT
m_iScriptLanguageServer = SL_NONE;
m_iScriptLanguageClient = SL_NONE;
#endif
return BaseClass::Init( entnum, iSerialNum );
}
@ -184,6 +199,72 @@ void C_World::Spawn( void )
Precache();
}
//-----------------------------------------------------------------------------
// Parse data from a map file
//-----------------------------------------------------------------------------
bool C_World::KeyValue( const char *szKeyName, const char *szValue )
{
#ifdef MAPBASE_VSCRIPT
if ( FStrEq( szKeyName, "vscriptlanguage" ) )
{
m_iScriptLanguageServer = atoi( szValue );
}
else if ( FStrEq( szKeyName, "vscriptlanguage_client" ) )
{
m_iScriptLanguageClient = atoi( szValue );
}
else
#endif
return BaseClass::KeyValue( szKeyName, szValue );
return true;
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Parses worldspawn data from BSP on the client
//-----------------------------------------------------------------------------
void C_World::ParseWorldMapData( const char *pMapData )
{
char szTokenBuffer[MAPKEY_MAXLENGTH];
for ( ; true; pMapData = MapEntity_SkipToNextEntity(pMapData, szTokenBuffer) )
{
//
// Parse the opening brace.
//
char token[MAPKEY_MAXLENGTH];
pMapData = MapEntity_ParseToken( pMapData, token );
//
// Check to see if we've finished or not.
//
if (!pMapData)
break;
if (token[0] != '{')
{
Error( "MapEntity_ParseAllEntities: found %s when expecting {", token);
continue;
}
CEntityMapData entData( (char*)pMapData );
char className[MAPKEY_MAXLENGTH];
if (!entData.ExtractValue( "classname", className ))
{
Error( "classname missing from entity!\n" );
}
if ( !Q_strcmp( className, "worldspawn" ) )
{
// Set up keyvalues.
ParseMapData( &entData );
return;
}
}
}
#endif
C_World *GetClientWorldEntity()

View File

@ -31,6 +31,7 @@ public:
virtual void Precache();
virtual void Spawn();
virtual bool KeyValue( const char *szKeyName, const char *szValue );
// Don't worry about adding the world to the collision list; it's already there
virtual CollideType_t GetCollideType( void ) { return ENTITY_SHOULD_NOT_COLLIDE; }
@ -41,6 +42,19 @@ public:
float GetWaveHeight() const;
const char *GetDetailSpriteMaterial() const;
#ifdef MAPBASE
// A special function which parses map data for the client world entity before LevelInitPreEntity().
// This can be used to access keyvalues early and without transmitting from the server.
void ParseWorldMapData( const char *pMapData );
#endif
#ifdef MAPBASE_VSCRIPT
void ClientThink() { ScriptContextThink(); }
// -2 = Use server language
ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)(m_iScriptLanguageClient != -2 ? m_iScriptLanguageClient : m_iScriptLanguageServer); }
#endif
public:
enum
{
@ -56,6 +70,13 @@ public:
float m_flMinPropScreenSpaceWidth;
float m_flMaxPropScreenSpaceWidth;
bool m_bColdWorld;
#ifdef MAPBASE
char m_iszChapterTitle[64];
#endif
#ifdef MAPBASE_VSCRIPT
int m_iScriptLanguageServer;
int m_iScriptLanguageClient;
#endif
private:
void RegisterSharedActivities( void );

View File

@ -37,6 +37,10 @@ struct studiohdr_t;
#include <icvar.h>
#include <baseentity_shared.h>
#ifdef MAPBASE
#include "tier1/mapbase_con_groups.h"
#endif
// This is a precompiled header. Include a bunch of common stuff.
// This is kind of ugly in that it adds a bunch of dependency where it isn't needed.

View File

@ -151,6 +151,10 @@
#endif
#ifdef MAPBASE_VSCRIPT
#include "vscript_client.h"
#endif
extern vgui::IInputInternal *g_InputInternal;
//=============================================================================
@ -218,6 +222,11 @@ IEngineReplay *g_pEngineReplay = NULL;
IEngineClientReplay *g_pEngineClientReplay = NULL;
IReplaySystem *g_pReplay = NULL;
#endif
#ifdef MAPBASE
IVEngineServer *serverengine = NULL;
#endif
IScriptManager *scriptmanager = NULL;
IHaptics* haptics = NULL;// NVNT haptics system interface singleton
@ -269,6 +278,8 @@ void ProcessCacheUsedMaterials()
}
}
void VGui_ClearVideoPanels();
// String tables
INetworkStringTable *g_pStringTableParticleEffectNames = NULL;
INetworkStringTable *g_StringTableEffectDispatch = NULL;
@ -341,6 +352,14 @@ static ConVar s_cl_load_hl1_content("cl_load_hl1_content", "0", FCVAR_ARCHIVE, "
ConVar r_lightmap_bicubic_set( "r_lightmap_bicubic_set", "0", FCVAR_ARCHIVE | FCVAR_HIDDEN, "Hack to get this convar to be re-set on first launch." );
#ifdef MAPBASE_RPC
// Mapbase stuff
extern void MapbaseRPC_Init();
extern void MapbaseRPC_Shutdown();
extern void MapbaseRPC_Update( int iType, const char *pMapName );
#endif
// Physics system
bool g_bLevelInitialized;
bool g_bTextMode = false;
@ -860,6 +879,7 @@ CHLClient::CHLClient()
}
extern IGameSystem *ViewportClientSystem();
@ -960,9 +980,30 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
return false;
#endif
#ifdef MAPBASE
// Implements the server engine interface on the client.
// I'm extremely confused as to how this is even possible, but Saul Rennison's worldlight did it.
// If it's really this possible, why wasn't it available before?
// Hopefully there's no SP-only magic going on here, because I want to use this for RPC.
if ( (serverengine = (IVEngineServer*)appSystemFactory(INTERFACEVERSION_VENGINESERVER, NULL )) == NULL )
return false;
#endif
if (!g_pMatSystemSurface)
return false;
if ( !CommandLine()->CheckParm( "-noscripting") )
{
#ifndef MAPBASE_VSCRIPT // Mapbase VScript uses .lib
scriptmanager = (IScriptManager *)appSystemFactory( VSCRIPT_INTERFACE_VERSION, NULL );
#endif
if (scriptmanager == nullptr)
{
scriptmanager = (IScriptManager*)Sys_GetFactoryThis()(VSCRIPT_INTERFACE_VERSION, NULL);
}
}
// it's ok if this is NULL. That just means the sourcevr.dll wasn't found
if ( CommandLine()->CheckParm( "-vr" ) )
@ -1091,6 +1132,9 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() );
#ifdef MAPBASE_VSCRIPT
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetVScriptSaveRestoreBlockHandler() );
#endif
ClientWorldFactoryInit();
@ -1104,6 +1148,14 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
HookHapticMessages(); // Always hook the messages
#endif
#ifdef MAPBASE_RPC
MapbaseRPC_Init();
#endif
#ifdef MAPBASE
CommandLine()->AppendParm( "+r_hunkalloclightmaps", "0" );
#endif
FnUnsafeCmdLineProcessor *pfnUnsafeCmdLineProcessor =
#ifndef TF_CLIENT_DLL
&UnsafeCmdLineProcessor;
@ -1211,12 +1263,17 @@ void CHLClient::Shutdown( void )
g_pSixenseInput = NULL;
#endif
VGui_ClearVideoPanels();
C_BaseAnimating::ShutdownBoneSetupThreadPool();
ClientWorldFactoryShutdown();
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() );
#ifdef MAPBASE_VSCRIPT
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetVScriptSaveRestoreBlockHandler() );
#endif
ClientVoiceMgr_Shutdown();
@ -1245,6 +1302,10 @@ void CHLClient::Shutdown( void )
ClientSteamContext().Shutdown();
#endif
#ifdef MAPBASE_RPC
MapbaseRPC_Shutdown();
#endif
// This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it
// DisconnectTier3Libraries( );
@ -1630,6 +1691,10 @@ void CHLClient::LevelInitPreEntity( char const* pMapName )
tempents->LevelInit();
ResetToneMapping(1.0);
#ifdef MAPBASE
GetClientWorldEntity()->ParseWorldMapData( engine->GetMapEntitiesString() );
#endif
IGameSystem::LevelInitPreEntityAllSystems(pMapName);
#ifdef USES_ECON_ITEMS
@ -1661,6 +1726,13 @@ void CHLClient::LevelInitPreEntity( char const* pMapName )
}
#endif
#ifdef MAPBASE_RPC
if (!g_bTextMode)
{
MapbaseRPC_Update(RPCSTATE_LEVEL_INIT, pMapName);
}
#endif
// Check low violence settings for this map
g_RagdollLVManager.SetLowViolence( pMapName );
@ -1752,6 +1824,13 @@ void CHLClient::LevelShutdown( void )
gHUD.LevelShutdown();
#ifdef MAPBASE_RPC
if (!g_bTextMode)
{
MapbaseRPC_Update(RPCSTATE_LEVEL_SHUTDOWN, NULL);
}
#endif
internalCenterPrint->Clear();
messagechars->Clear();
@ -2183,7 +2262,9 @@ void OnRenderStart()
// are at the correct location
view->OnRenderStart();
#ifndef MAPBASE
RopeManager()->OnRenderStart();
#endif
// This will place all entities in the correct position in world space and in the KD-tree
C_BaseAnimating::UpdateClientSideAnimations();

View File

@ -110,6 +110,9 @@ extern IReplayManager *g_pReplayManager;
extern IReplayScreenshotManager *g_pReplayScreenshotManager;
extern IEngineReplay *g_pEngineReplay;
extern IEngineClientReplay *g_pEngineClientReplay;
#ifdef MAPBASE
extern IVEngineServer *serverengine;
#endif
//=============================================================================
// HPE_BEGIN
@ -171,4 +174,16 @@ extern CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex );
#endif
#ifdef MAPBASE
// Mapbase RPC stuff
enum
{
RPCSTATE_INIT,
RPCSTATE_LEVEL_INIT,
RPCSTATE_LEVEL_SHUTDOWN,
RPCSTATE_UPDATE,
};
#endif
#endif // CDLL_CLIENT_INT_H

View File

@ -714,6 +714,24 @@ int UTIL_EntitiesAlongRay( C_BaseEntity **pList, int listMax, const Ray_t &ray,
return rayEnum.GetCount();
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Pass in an array of pointers and an array size, it fills the array and returns the number inserted
// Input : **pList -
// listMax -
// &point -
// flagMask -
// Output : int
//-----------------------------------------------------------------------------
int UTIL_EntitiesAtPoint( C_BaseEntity **pList, int listMax, const Vector &point, int flagMask, int partitionMask )
{
CFlaggedEntitiesEnum rayEnum( pList, listMax, flagMask );
partition->EnumerateElementsAtPoint( partitionMask, point, false, &rayEnum );
return rayEnum.GetCount();
}
#endif
CEntitySphereQuery::CEntitySphereQuery( const Vector &center, float radius, int flagMask, int partitionMask )
{
m_listIndex = 0;

View File

@ -119,6 +119,9 @@ void ClientPrint( C_BasePlayer *player, int msg_dest, const char *msg_name, cons
int UTIL_EntitiesInBox( C_BaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
int UTIL_EntitiesInSphere( C_BaseEntity **pList, int listMax, const Vector &center, float radius, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
int UTIL_EntitiesAlongRay( C_BaseEntity **pList, int listMax, const Ray_t &ray, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
#ifdef MAPBASE
int UTIL_EntitiesAtPoint( C_BaseEntity **pList, int listMax, const Vector &point, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
#endif
// make this a fixed size so it just sits on the stack
#define MAX_SPHERE_QUERY 256
@ -161,7 +164,12 @@ T *_CreateEntity( T *newClass, const char *className )
// Misc useful
inline bool FStrEq(const char *sz1, const char *sz2)
{
return (sz1 == sz2 || V_stricmp(sz1, sz2) == 0);
#ifdef MAPBASE
// V_stricmp() already checks if the pointers are equal, so having a comparison here is pointless.
return ( V_stricmp(sz1, sz2) == 0 );
#else
return ( sz1 == sz2 || V_stricmp(sz1, sz2) == 0 );
#endif
}
// Given a vector, clamps the scalar axes to MAX_COORD_FLOAT ranges from worldsize.h

View File

@ -18,6 +18,9 @@ $include "$SRCDIR\vpc_scripts\protobuf_builder.vpc"
$Include "$SRCDIR\vpc_scripts\source_replay.vpc" [$TF]
$Include "$SRCDIR\game\protobuf_include.vpc"
// Mapbase stuff
$Include "$SRCDIR\game\client\client_mapbase.vpc" [$MAPBASE]
$Configuration "Debug"
{
$General
@ -499,6 +502,11 @@ $Project
$File "viewrender.cpp"
$File "$SRCDIR\game\shared\voice_banmgr.cpp"
$File "$SRCDIR\game\shared\voice_status.cpp"
$File "vscript_client.cpp"
$File "vscript_client.h"
$File "vscript_client.nut"
$File "$SRCDIR\game\shared\vscript_shared.cpp"
$File "$SRCDIR\game\shared\vscript_shared.h"
$File "warp_overlay.cpp"
$File "WaterLODMaterialProxy.cpp"
$File "$SRCDIR\game\shared\weapon_parse.cpp"
@ -540,7 +548,6 @@ $Project
"$SRCDIR\public\dt_utlvector_recv.cpp" \
"$SRCDIR\public\filesystem_helpers.cpp" \
"$SRCDIR\public\interpolatortypes.cpp" \
"$SRCDIR\game\shared\interval.cpp" \
"$SRCDIR\common\language.cpp" \
"$SRCDIR\public\networkvar.cpp" \
"$SRCDIR\common\randoverride.cpp" \
@ -1114,6 +1121,7 @@ $Project
$File "$SRCDIR\public\vgui_controls\WizardSubPanel.h"
$File "$SRCDIR\public\worldsize.h"
$File "$SRCDIR\public\zip_uncompressed.h"
$File "$SRCDIR\public\tier1\interval.h"
//Haptics
$File "$SRCDIR\public\haptics\ihaptics.h" [$WIN32]
$File "$SRCDIR\public\haptics\haptic_utils.h" [$WIN32]
@ -1170,7 +1178,6 @@ $Project
$File "$SRCDIR\game\shared\igamesystem.h"
$File "$SRCDIR\game\shared\imovehelper.h"
$File "$SRCDIR\game\shared\in_buttons.h"
$File "$SRCDIR\game\shared\interval.h"
$File "$SRCDIR\game\shared\iplayeranimstate.h"
$File "$SRCDIR\game\shared\ipredictionsystem.h"
$File "$SRCDIR\game\shared\itempents.h"
@ -1266,6 +1273,9 @@ $Project
$Lib tier3
$Lib vgui_controls
$Lib vtf
// Discord integration
$Lib "$LIBPUBLIC\discord-rpc" [$MAPBASE_RPC&&!$LINUXALL]
$ImpLibexternal steam_api [!$WIN64]
$ImpLibexternal steam_api64 [$WIN64]

View File

@ -79,7 +79,7 @@ $Project "Client (Episodic)"
$File "hl2\c_weapon_crossbow.cpp"
$File "episodic\c_weapon_hopwire.cpp"
$File "hl2\c_weapon_physcannon.cpp"
$File "hl2\c_weapon_stunstick.cpp"
$File "hl2\c_weapon_stunstick.cpp" [!$MAPBASE] // See client_mapbase.vpc
$File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h"
$File "hl2\clientmode_hlnormal.cpp"
$File "hl2\clientmode_hlnormal.h"

View File

@ -74,7 +74,7 @@ $Project "Client (HL2)"
$File "hl2\c_weapon__stubs_hl2.cpp"
$File "hl2\c_weapon_crossbow.cpp"
$File "hl2\c_weapon_physcannon.cpp"
$File "hl2\c_weapon_stunstick.cpp"
$File "hl2\c_weapon_stunstick.cpp" [!$MAPBASE] // See client_mapbase.vpc
$File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h"
$File "hl2\clientmode_hlnormal.cpp"
$File "hl2\clientmode_hlnormal.h"

View File

@ -0,0 +1,98 @@
//-----------------------------------------------------------------------------
// CLIENT_MAPBASE.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Configuration
{
$Compiler
{
$PreprocessorDefinitions "$BASE;ASW_PROJECTED_TEXTURES;DYNAMIC_RTT_SHADOWS;GLOWS_ENABLE"
$PreprocessorDefinitions "$BASE;MAPBASE_RPC;DISCORD_RPC;STEAM_RPC" [$MAPBASE_RPC&&!$LINUXALL]
$PreprocessorDefinitions "$BASE;MAPBASE_VSCRIPT" [$MAPBASE_VSCRIPT]
$PreprocessorDefinitions "$BASE;NEW_RESPONSE_SYSTEM" [$NEW_RESPONSE_SYSTEM]
}
}
$Project
{
$Folder "Source Files"
{
$File "c_env_global_light.cpp"
$File "worldlight.cpp"
$File "worldlight.h"
$File "c_baselesson.cpp"
$File "c_baselesson.h"
$File "c_gameinstructor.cpp"
$File "c_gameinstructor.h"
$File "hud_locator_target.cpp"
$File "hud_locator_target.h"
$File "c_postprocesscontroller.cpp"
$File "c_postprocesscontroller.h"
$File "c_env_dof_controller.cpp"
$File "c_movie_display.cpp"
$File "c_movie_display.h"
$File "vgui_movie_display.cpp"
$File "convarproxy.cpp"
$Folder "Mapbase"
{
$File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_usermessages.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
$File "$SRCDIR\game\shared\mapbase\matchers.h"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.cpp"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.h"
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_hl2.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_consts_shared.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_consts_weapons.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\logic_script_client.cpp" [$MAPBASE_VSCRIPT]
$File "mapbase\vscript_vgui.cpp" [$MAPBASE_VSCRIPT]
$File "mapbase\vscript_vgui.h" [$MAPBASE_VSCRIPT]
$File "mapbase\vscript_vgui.nut" [$MAPBASE_VSCRIPT]
$File "mapbase\c_func_clientclip.cpp"
$File "mapbase\c_func_fake_worldportal.cpp"
$File "mapbase\c_func_fake_worldportal.h"
$File "mapbase\c_point_glow.cpp"
$File "mapbase\c_vgui_text_display.cpp"
$File "mapbase\c_weapon_custom_hl2.cpp"
$File "mapbase\mapbase_autocubemap.cpp"
}
$Folder "HL2 DLL"
{
// Original stunstick files are conditional'd out in the HL2 VPCs
$File "$SRCDIR\game\shared\hl2mp\weapon_stunstick.cpp"
$File "$SRCDIR\game\shared\hl2mp\weapon_stunstick.h"
}
$Folder "HL2MP"
{
$Folder "Weapons"
{
$File "$SRCDIR\game\shared\hl2mp\weapon_slam.cpp"
$File "$SRCDIR\game\shared\hl2mp\weapon_slam.h"
}
}
}
$Folder "Link Libraries"
{
$Lib "vscript" [$MAPBASE_VSCRIPT]
$Lib "raytrace"
}
}

View File

@ -1501,10 +1501,12 @@ inline void AddRenderableToRenderList( CClientRenderablesList &renderList, IClie
pEntry->m_RenderHandle = renderHandle;
curCount++;
}
#ifndef MAPBASE // According to ficool2, this message can cause significant lag
else
{
engine->Con_NPrintf( 10, "Warning: overflowed CClientRenderablesList group %d", group );
}
#endif
}

View File

@ -52,7 +52,11 @@ class CClientRenderablesList : public CRefCounted<>
public:
enum
{
#ifdef MAPBASE
MAX_GROUP_ENTITIES = 16834 // According to ficool2, this limit is bogus/not enforced by the engine and can be "safely" raised.
#else
MAX_GROUP_ENTITIES = 4096
#endif
};
struct CEntry

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