Merge branch 'master' into aghl

This commit is contained in:
Andrey Akhmichin 2024-02-27 04:17:10 +05:00
commit 5fbc804c1f
136 changed files with 4132 additions and 2387 deletions

View File

@ -52,13 +52,13 @@ jobs:
- name: Build on Linux - name: Build on Linux
if: startsWith(matrix.os, 'ubuntu') if: startsWith(matrix.os, 'ubuntu')
run: | run: |
schroot --chroot steamrt_scout_i386 -- cmake -B build -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DCMAKE_INSTALL_PREFIX="$PWD/dist" schroot --chroot steamrt_scout_i386 -- cmake -DCMAKE_BUILD_TYPE=Release -DPOLLY=ON -B build -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DCMAKE_INSTALL_PREFIX="$PWD/dist"
schroot --chroot steamrt_scout_i386 -- cmake --build build --target all schroot --chroot steamrt_scout_i386 -- cmake --build build --target all
schroot --chroot steamrt_scout_i386 -- cmake --build build --target install schroot --chroot steamrt_scout_i386 -- cmake --build build --target install
- name: Build on Linux with vgui - name: Build on Linux with vgui
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.cc, 'gcc') if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.cc, 'gcc')
run: | run: |
schroot --chroot steamrt_scout_i386 -- cmake -B build-vgui -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VGUI=ON -DCMAKE_INSTALL_PREFIX="$PWD/dist-vgui" schroot --chroot steamrt_scout_i386 -- cmake -DCMAKE_BUILD_TYPE=Release -DPOLLY=ON -B build-vgui -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VGUI=ON -DCMAKE_INSTALL_PREFIX="$PWD/dist-vgui"
cp vgui_support/vgui-dev/lib/vgui.so build-vgui/cl_dll cp vgui_support/vgui-dev/lib/vgui.so build-vgui/cl_dll
schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target all schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target all
schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target install schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target install

10
.gitignore vendored
View File

@ -29,3 +29,13 @@ CMakeSettings.json
CMakeFiles CMakeFiles
CMakeCache.txt CMakeCache.txt
Makefile Makefile
# Android Studio/Gradle
.gradle/
.externalNativeBuild
.cxx/
.idea/
local.properties
.project
.classpath
.settings

View File

@ -20,7 +20,8 @@
# SOFTWARE. # SOFTWARE.
# #
cmake_minimum_required(VERSION 2.8.12) # 3.9 added captures in if(MATCHES)
cmake_minimum_required(VERSION 3.9)
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.15.0") if(NOT ${CMAKE_VERSION} VERSION_LESS "3.15.0")
cmake_policy(SET CMP0091 NEW) cmake_policy(SET CMP0091 NEW)
@ -32,6 +33,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(CheckIncludeFile) include(CheckIncludeFile)
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
include(VSForceXPToolchain) # Force XP toolchain for Visual Studio include(VSForceXPToolchain) # Force XP toolchain for Visual Studio
include(CheckIPOSupported)
project (HLSDK-PORTABLE) project (HLSDK-PORTABLE)
@ -43,54 +45,72 @@ option(USE_VGUI2 "Enable VGUI2. UNDONE" OFF)
option(USE_NOVGUI_MOTD "Prefer non-VGUI MOTD when USE_VGUI is enabled" OFF) option(USE_NOVGUI_MOTD "Prefer non-VGUI MOTD when USE_VGUI is enabled" OFF)
option(USE_NOVGUI_SCOREBOARD "Prefer non-VGUI Scoreboard when USE_VGUI is enabled" OFF) option(USE_NOVGUI_SCOREBOARD "Prefer non-VGUI Scoreboard when USE_VGUI is enabled" OFF)
option(USE_VOICEMGR "Enable VOICE MANAGER." OFF) option(USE_VOICEMGR "Enable VOICE MANAGER." OFF)
option(BUILD_SERVER "Build server dll" ON)
option(LTO "Enable interprocedural optimization" OFF)
option(POLLY "Enable pollyhedral optimization" OFF)
if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR if(CMAKE_SIZEOF_VOID_P EQUAL 4 OR
((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") ((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "x64" AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "x64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64"))) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X86_64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "EM64T")))
option(64BIT "Disable auto -m32 appending to compiler flags" OFF) option(64BIT "Disable auto -m32 appending to compiler flags" OFF)
option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" ON)
else() else()
option(64BIT "Disable auto -m32 appending to compiler flags" ON) option(64BIT "Disable auto -m32 appending to compiler flags" ON)
option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" OFF)
endif() endif()
option(BARNACLE_FIX_VISIBILITY "Enable barnacle tongue length fix" OFF) # It seems CMAKE_SYSTEM_PROCESSOR parameter completely useless for APPLE platform,
option(CLIENT_WEAPONS "Enable client local weapons prediction" ON) # so may need to set options here manually.
option(CROWBAR_IDLE_ANIM "Enable crowbar idle animation" OFF) if((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
option(CROWBAR_DELAY_FIX "Enable crowbar attack delay fix" OFF) AND (((CMAKE_SYSTEM_PROCESSOR STREQUAL "x64"
option(CROWBAR_FIX_RAPID_CROWBAR "Enable rapid crowbar fix" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X64"
option(GAUSS_OVERCHARGE_FIX "Enable gauss overcharge fix" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
option(TRIPMINE_BEAM_DUPLICATION_FIX "Enable fix of tripmine beam duplication on level transition" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X86_64"
option(HANDGRENADE_DEPLOY_FIX "Enable handgrenade deploy animation fix after finishing a throw" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64"
option(WEAPONS_ANIMATION_TIMES_FIX "Enable animation times fix for some weapons" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64"
option(OEM_BUILD "Enable OEM Build" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "EM64T") AND NOT 64BIT)
option(HLDEMO_BUILD "Enable Demo Build" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86"
option(MINIAG "Compile server-side mod version for HLDM" OFF) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X86"
option(BUILD_SERVER "Build server dll" ON) OR CMAKE_SYSTEM_PROCESSOR STREQUAL "i386"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "i486"
set(SERVER_INSTALL_DIR "dlls" CACHE STRING "Where put server dll") OR CMAKE_SYSTEM_PROCESSOR STREQUAL "i586"
set(CLIENT_INSTALL_DIR "cl_dlls" CACHE STRING "Where put client dll") OR CMAKE_SYSTEM_PROCESSOR STREQUAL "i686"))
option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" ON)
if (MINIAG)
option(BUILD_CLIENT "Build client dll" OFF)
set(GAMEDIR "valve" CACHE STRING "Gamedir path")
set(SERVER_LIBRARY_NAME "hl" CACHE STRING "Library name for PC platforms")
add_definitions(-DAG_NO_CLIENT_DLL)
message(STATUS "Adrenaline Gamer Mini")
else() else()
option(BUILD_CLIENT "Build client dll" ON) option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" OFF)
set(GAMEDIR "ag" CACHE STRING "Gamedir path")
set(SERVER_LIBRARY_NAME "ag" CACHE STRING "Library name for PC platforms")
add_definitions(-DAG_USE_CHEATPROTECTION)
message(STATUS "Adrenaline Gamer")
endif() endif()
#----------------- #-----------------
# MAIN BUILD CODE \ # MAIN BUILD CODE \
###################\ ###################\
file(STRINGS "mod_options.txt" MOD_OPTIONS_STRINGS REGEX "^([A-Za-z0-9_-]+)=([A-Za-z0-9_-]+)\ \#\ (.*)$")
foreach(LINE IN LISTS MOD_OPTIONS_STRINGS)
# file() itself doesn't populate CMAKE_MATCH_<n>, so
# reparse the string
if(${LINE} MATCHES "^([A-Za-z0-9_-]+)=([A-Za-z0-9_-]+)\ \#\ (.*)$")
# detect boolean options
if(${CMAKE_MATCH_2} STREQUAL "ON" OR ${CMAKE_MATCH_2} STREQUAL "OFF")
option(${CMAKE_MATCH_1} "${CMAKE_MATCH_3}" ${CMAKE_MATCH_2})
# let's check it here as well
if(${CMAKE_MATCH_1})
message(STATUS ${CMAKE_MATCH_3} " is enabled")
add_definitions(-D${CMAKE_MATCH_1})
else()
message(STATUS ${CMAKE_MATCH_3} " is disabled")
endif()
else()
set(${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE STRING "${CMAKE_MATCH_3}")
endif()
endif()
endforeach()
if(HLDEMO_BUILD AND OEM_BUILD) if(HLDEMO_BUILD AND OEM_BUILD)
message(FATAL_ERROR "Don't mix Demo and OEM builds!") message(FATAL_ERROR "Don't mix Demo and OEM builds!")
endif() endif()
@ -120,76 +140,11 @@ else()
message(STATUS "Building for 32 Bit") message(STATUS "Building for 32 Bit")
endif() endif()
if(CLIENT_WEAPONS)
message(STATUS "Client weapons enabled.")
add_definitions(-DCLIENT_WEAPONS)
endif()
if(BARNACLE_FIX_VISIBILITY)
message(STATUS "Barnacle tongue fix enabled")
add_definitions(-DBARNACLE_FIX_VISIBILITY)
endif()
if(CROWBAR_IDLE_ANIM)
message(STATUS "Crowbar idle animation enabled")
add_definitions(-DCROWBAR_IDLE_ANIM)
endif()
if(CROWBAR_DELAY_FIX)
message(STATUS "Crowbar attack delay fix enabled")
add_definitions(-DCROWBAR_DELAY_FIX)
endif()
if(CROWBAR_FIX_RAPID_CROWBAR)
message(STATUS "Rapid crowbar fix enabled")
add_definitions(-DCROWBAR_FIX_RAPID_CROWBAR)
endif()
if(GAUSS_OVERCHARGE_FIX)
message(STATUS "Gauss overcharge fix enabled")
add_definitions(-DGAUSS_OVERCHARGE_FIX)
endif()
if(TRIPMINE_BEAM_DUPLICATION_FIX)
message(STATUS "Tripmine beam duplication fix enabled")
add_definitions(-DTRIPMINE_BEAM_DUPLICATION_FIX)
endif()
if(HANDGRENADE_DEPLOY_FIX)
message(STATUS "Handgrenade deploy animation fix enabled")
add_definitions(-DHANDGRENADE_DEPLOY_FIX)
endif()
if(WEAPONS_ANIMATION_TIMES_FIX)
message(STATUS "Weapons animation times fix enabled")
add_definitions(-DWEAPONS_ANIMATION_TIMES_FIX)
endif()
if(OEM_BUILD)
message(STATUS "OEM build enabled")
add_definitions(-DOEM_BUILD)
endif()
if(HLDEMO_BUILD)
message(STATUS "Demo build enabled")
add_definitions(-DHLDEMO_BUILD)
endif()
if (MINGW) if (MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--add-stdcall-alias") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--add-stdcall-alias")
endif() endif()
# add_compile_options for older cmake versions
if(${CMAKE_VERSION} VERSION_LESS "3.0.2")
macro(add_compile_options)
set(list_var "${ARGV}")
foreach(arg IN LISTS list_var)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${arg}")
endforeach()
endmacro()
endif()
if(NOT MSVC) if(NOT MSVC)
#add_compile_options(-Wempty-body) # GCC/Clang flag #add_compile_options(-Wempty-body) # GCC/Clang flag
add_compile_options(-Wreturn-type) # GCC/Clang flag add_compile_options(-Wreturn-type) # GCC/Clang flag
@ -201,6 +156,15 @@ if(VITA)
add_compile_options(-fno-use-cxa-atexit) add_compile_options(-fno-use-cxa-atexit)
endif() endif()
if(LTO)
check_ipo_supported(RESULT HAVE_LTO OUTPUT LTO_ERROR)
if(HAVE_LTO)
message(STATUS "IPO / LTO enabled")
else()
message(STATUS "IPO / LTO not supported: ${LTO_ERROR}")
endif()
endif()
check_include_file("tgmath.h" HAVE_TGMATH_H) check_include_file("tgmath.h" HAVE_TGMATH_H)
if(HAVE_TGMATH_H) if(HAVE_TGMATH_H)
if(NOT MSVC) if(NOT MSVC)
@ -216,7 +180,12 @@ endif()
if(BUILD_CLIENT) if(BUILD_CLIENT)
message(STATUS "Building client enabled") message(STATUS "Building client enabled")
add_definitions(-DAG_USE_CHEATPROTECTION)
add_subdirectory(cl_dll) add_subdirectory(cl_dll)
else()
add_definitions(-DAG_NO_CLIENT_DLL)
set(GAMEDIR "valve" CACHE STRING "Gamedir path")
set(SERVER_LIBRARY_NAME "hl" CACHE STRING "Library name for PC platforms")
endif() endif()
if(BUILD_SERVER) if(BUILD_SERVER)
@ -227,3 +196,11 @@ endif()
if(NOT BUILD_SERVER AND NOT BUILD_CLIENT) if(NOT BUILD_SERVER AND NOT BUILD_CLIENT)
message(FATAL_ERROR "Nothing to build") message(FATAL_ERROR "Nothing to build")
endif() endif()
if(POLLY)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(-mllvm -polly)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-fgraphite-identity -floop-interchange -floop-block)
endif()
endif()

View File

@ -80,7 +80,7 @@ git clone --recursive https://github.com/FWGS/hlsdk-portable
### Prerequisites ### Prerequisites
Install and run [Visual Studio Installer](https://visualstudio.microsoft.com/downloads/). The installer allows you to choose specific components. Select `Desktop development with C++`. You can untick everything you don't need in Installation details, but you must keep `MSVC` ticked. You may also keep `C++ CMake tools for Windows` ticked as you'll need **cmake**. Alternatively you can install **cmake** from the [cmake.org](https://cmake.org/download/) and during installation tick *Add to the PATH...*. Install and run [Visual Studio Installer](https://visualstudio.microsoft.com/downloads/). The installer allows you to choose specific components. Select `Desktop development with C++`. You can untick everything you don't need in Installation details, but you must keep `MSVC` and corresponding Windows SDK (e.g. Windows 10 SDK or Windows 11 SDK) ticked. You may also keep `C++ CMake tools for Windows` ticked as you'll need **cmake**. Alternatively you can install **cmake** from the [cmake.org](https://cmake.org/download/) and during installation tick *Add to the PATH...*.
### Opening command prompt ### Opening command prompt
@ -164,7 +164,7 @@ sudo ./setup_chroot.sh --i386 --tarball ./com.valvesoftware.SteamRuntime.Sdk-i38
Now you can use cmake and make prepending the commands with `schroot --chroot steamrt_scout_i386 --`: Now you can use cmake and make prepending the commands with `schroot --chroot steamrt_scout_i386 --`:
``` ```
schroot --chroot steamrt_scout_i386 -- cmake -B build-in-steamrt -S . schroot --chroot steamrt_scout_i386 -- cmake -DCMAKE_BUILD_TYPE=Release -B build-in-steamrt -S .
schroot --chroot steamrt_scout_i386 -- cmake --build build-in-steamrt schroot --chroot steamrt_scout_i386 -- cmake --build build-in-steamrt
``` ```
@ -180,13 +180,20 @@ sudo apt install cmake build-essential gcc-multilib g++-multilib libsdl2-dev:i38
### Building ### Building
``` ```
cmake -B build -S . cmake -DCMAKE_BUILD_TYPE=Release -B build -S .
cmake --build build cmake --build build
``` ```
Note that the libraries built this way might be not compatible with Steam Half-Life. If you have such issue you can configure it to build statically with c++ and gcc libraries: Note that the libraries built this way might be not compatible with Steam Half-Life. If you have such issue you can configure it to build statically with c++ and gcc libraries:
``` ```
cmake .. -DCMAKE_C_FLAGS="-static-libstdc++ -static-libgcc" cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc" -B build -S .
cmake --build build
```
Alternatively, you can avoid libstdc++/libgcc_s linking using small libsupc++ library and optimization build flags instead(Really just set Release build type and set C compiler as C++ compiler):
```
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=cc -B build -S .
cmake --build build
``` ```
To ensure portability it's still better to build using Steam Runtime or another chroot of some older distro. To ensure portability it's still better to build using Steam Runtime or another chroot of some older distro.
@ -229,13 +236,36 @@ Insert your actual user name in place of `yourusername`.
Prepend any make or cmake call with `schroot -c jessie --`: Prepend any make or cmake call with `schroot -c jessie --`:
``` ```
schroot --chroot jessie -- cmake -B build-in-chroot -S . schroot --chroot jessie -- cmake -DCMAKE_BUILD_TYPE=Release -B build-in-chroot -S .
schroot --chroot jessie -- cmake --build build-in-chroot schroot --chroot jessie -- cmake --build build-in-chroot
``` ```
## Android ## Android
1. Set up [Android Studio/Android SDK](https://developer.android.com/studio).
TODO ### Android Studio
Open the project located in the `android` folder and build.
### Command-line
```
cd android
./gradlew assembleRelease
```
### Customizing the build
settings.gradle:
* **rootProject.name** - project name displayed in Android Studio (optional).
app/build.gradle:
* **android->namespace** and **android->defaultConfig->applicationId** - set both to desired package name.
* **getBuildNum** function - set **releaseDate** variable as desired.
app/java/su/xash/hlsdk/MainActivity.java:
* **.putExtra("gamedir", ...)** - set desired gamedir.
src/main/AndroidManifest.xml:
* **application->android:label** - set desired application name.
* **su.xash.engine.gamedir** value - set to same as above.
## Nintendo Switch ## Nintendo Switch
@ -307,7 +337,13 @@ Install C and C++ compilers (like gcc or clang), cmake and make.
### Building ### Building
``` ```
cmake -B build -S . cmake -DCMAKE_BUILD_TYPE=Release -B build -S .
cmake --build build
```
Force 64-bit build:
```
cmake -DCMAKE_BUILD_TYPE=Release -D64BIT=1 -B build -S .
cmake --build build cmake --build build
``` ```
@ -316,15 +352,22 @@ cmake --build build
To use waf, you need to install python (2.7 minimum) To use waf, you need to install python (2.7 minimum)
``` ```
(./waf configure -T release) ./waf configure -T release
(./waf) ./waf
```
Force 64-bit build:
```
./waf configure -T release -8
./waf
``` ```
## Build options ## Build options
Some useful build options that can be set during the cmake step. Some useful build options that can be set during the cmake step.
* **GOLDSOURCE_SUPPORT** - allows to turn off/on the support for GoldSource input. Set to **ON** by default on Windows and Linux, **OFF** on other platforms. * **GOLDSOURCE_SUPPORT** - allows to turn off/on the support for GoldSource input. Set to **ON** by default on x86 Windows and x86 Linux, **OFF** on other platforms.
* **64BIT** - allows to turn off/on 64-bit build. Set to **OFF** by default on x86_64 Windows, x86_64 Linux and 32-bit platforms, **ON** on other 64-bit platforms.
* **USE_VGUI** - whether to use VGUI library. **OFF** by default. You need to init `vgui_support` submodule in order to build with VGUI. * **USE_VGUI** - whether to use VGUI library. **OFF** by default. You need to init `vgui_support` submodule in order to build with VGUI.
This list is incomplete. Look at `CMakeLists.txt` to see all available options. This list is incomplete. Look at `CMakeLists.txt` to see all available options.

73
android/app/build.gradle Normal file
View File

@ -0,0 +1,73 @@
import java.time.LocalDateTime
import java.time.Month
import java.time.temporal.ChronoUnit
apply plugin: 'com.android.application'
android {
ndkVersion '26.1.10909125'
namespace 'com.example.hlsdk'
defaultConfig {
applicationId 'com.example.hlsdk'
versionName '1.0'
versionCode getBuildNum()
minSdkVersion 3
targetSdk 34
compileSdk 34
externalNativeBuild {
cmake {
arguments '-DPOLLY=ON'
}
}
}
externalNativeBuild {
cmake {
version '3.22.1'
path file('../../CMakeLists.txt')
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
debug {
minifyEnabled false
shrinkResources false
debuggable true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
lint {
abortOnError false
}
androidResources {
noCompress += ''
}
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
}
static def getBuildNum() {
LocalDateTime now = LocalDateTime.now()
LocalDateTime releaseDate = LocalDateTime.of(2023, Month.DECEMBER, 28, 0, 0, 0)
int qBuildNum = releaseDate.until(now, ChronoUnit.DAYS)
int minuteOfDay = now.getHour() * 60 + now.getMinute()
return qBuildNum * 10000 + minuteOfDay
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:forceQueryable="true"
android:icon="@android:mipmap/sym_def_app_icon"
android:label="hlsdk-portable"
tools:targetApi="r">
<meta-data
android:name="su.xash.engine.gamedir"
android:value="valve" />
<activity
android:name="su.xash.hlsdk.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="su.xash.engine.MOD" />
</intent-filter>
</activity>
</application>
<queries>
<package android:name="su.xash.engine" />
<package android:name="su.xash.engine.test" />
</queries>
</manifest>

View File

@ -0,0 +1,37 @@
package su.xash.hlsdk;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String pkg = "su.xash.engine.test";
try {
getPackageManager().getPackageInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
try {
pkg = "su.xash.engine";
getPackageManager().getPackageInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException ex) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=su.xash.engine")).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
finish();
return;
}
}
startActivity(new Intent().setComponent(new ComponentName(pkg, "su.xash.engine.XashActivity"))
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra("gamedir", "valve")
.putExtra("gamelibdir", getApplicationInfo().nativeLibraryDir)
.putExtra("package", getPackageName()));
finish();
}
}

17
android/build.gradle Normal file
View File

@ -0,0 +1,17 @@
buildscript {
repositories {
mavenCentral()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.0'
}
}
allprojects {
repositories {
mavenCentral()
google()
}
}

21
android/gradle.properties Normal file
View File

@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=384m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# android.useDeprecatedNdk=true
android.enableJetifier=true
android.useAndroidX=true

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Thu Dec 28 14:36:02 EET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

160
android/gradlew vendored Executable file
View File

@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

3
android/settings.gradle Normal file
View File

@ -0,0 +1,3 @@
include ':app'
rootProject.name = 'hlsdk-portable'

View File

@ -70,6 +70,7 @@ SRCS+=./in_camera.cpp
SRCS+=./input.cpp SRCS+=./input.cpp
SRCS+=./input_goldsource.cpp SRCS+=./input_goldsource.cpp
SRCS+=./input_mouse.cpp SRCS+=./input_mouse.cpp
SRCS+=./interpolation.cpp
#SRCS+=./inputw32.cpp #SRCS+=./inputw32.cpp
SRCS+=./menu.cpp SRCS+=./menu.cpp
SRCS+=./message.cpp SRCS+=./message.cpp

View File

@ -20,7 +20,7 @@
# SOFTWARE. # SOFTWARE.
# #
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 3.9)
project (CLDLL) project (CLDLL)
set (CLDLL_LIBRARY client) set (CLDLL_LIBRARY client)
@ -29,13 +29,21 @@ add_definitions(-DCLIENT_DLL)
if(NOT MSVC) if(NOT MSVC)
add_compile_options(-fno-exceptions) # GCC/Clang flag add_compile_options(-fno-exceptions) # GCC/Clang flag
add_compile_options(-Wno-write-strings) # GCC/Clang flag add_compile_options(-fno-rtti) # GCC/Clang flag
add_compile_options(-fvisibility=hidden) # GCC/Clang flag add_compile_options(-fvisibility=hidden) # GCC/Clang flag
add_definitions(-D_LINUX -DLINUX) # It seems enough for all non-Win32 systems add_definitions(-D_LINUX -DLINUX) # It seems enough for all non-Win32 systems
add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp) add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp)
if(NOT MINGW) if(NOT MINGW)
add_definitions(-D_snprintf=snprintf -D_vsnprintf=vsnprintf) add_definitions(-D_snprintf=snprintf -D_vsnprintf=vsnprintf)
endif() endif()
if(CMAKE_BUILD_TYPE MATCHES "Release"
OR (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo"
AND CMAKE_SYSTEM_NAME STREQUAL "Android"))
add_compile_options(-fno-unwind-tables -fno-asynchronous-unwind-tables) # GCC/Clang flag
add_compile_options(-fomit-frame-pointer) # GCC/Clang flag
add_compile_options(-ftree-vectorize) # GCC/Clang flag
add_compile_options(-funsafe-math-optimizations) # GCC/Clang flag
endif()
else() else()
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
endif() endif()
@ -99,6 +107,7 @@ set (CLDLL_SOURCES
input_goldsource.cpp input_goldsource.cpp
input_mouse.cpp input_mouse.cpp
input_xash3d.cpp input_xash3d.cpp
interpolation.cpp
menu.cpp menu.cpp
message.cpp message.cpp
parsemsg.cpp parsemsg.cpp
@ -248,8 +257,16 @@ if(MSVC)
set_property(TARGET ${CLDLL_LIBRARY} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set_property(TARGET ${CLDLL_LIBRARY} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif() endif()
if(HAVE_LTO)
set_property(TARGET ${CLDLL_LIBRARY} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
install( TARGETS ${CLDLL_LIBRARY} install( TARGETS ${CLDLL_LIBRARY}
DESTINATION "${GAMEDIR}/${CLIENT_INSTALL_DIR}/" DESTINATION "${GAMEDIR}/${CLIENT_INSTALL_DIR}/"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE ) WORLD_READ WORLD_EXECUTE )
add_custom_command(TARGET ${CLDLL_LIBRARY}
POST_BUILD DEPENDS ${CLDLL_LIBRARY}
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}> -s $<TARGET_FILE:${CLDLL_LIBRARY}>)

View File

@ -73,7 +73,7 @@ int CHudMOTD::Draw( float fTime )
//bool bScroll; //bool bScroll;
// find the top of where the MOTD should be drawn, so the whole thing is centered in the screen // find the top of where the MOTD should be drawn, so the whole thing is centered in the screen
int ypos = ( ScreenHeight - LINE_HEIGHT * m_iLines ) / 2; // shift it up slightly int ypos = ( ScreenHeight - LINE_HEIGHT * m_iLines ) / 2; // shift it up slightly
char *ch = m_szMOTD; unsigned char *ch = (unsigned char*)m_szMOTD;
int xpos = ( ScreenWidth - gHUD.m_scrinfo.charWidths['M'] * m_iMaxLength ) / 2; int xpos = ( ScreenWidth - gHUD.m_scrinfo.charWidths['M'] * m_iMaxLength ) / 2;
if( xpos < 30 ) if( xpos < 30 )
xpos = 30; xpos = 30;
@ -95,11 +95,13 @@ int CHudMOTD::Draw( float fTime )
gHUD.DrawDarkRectangle( xpos - 5, ypos_r - 5, xmax - xpos + 10, height + 10 ); gHUD.DrawDarkRectangle( xpos - 5, ypos_r - 5, xmax - xpos + 10, height + 10 );
while( *ch ) while( *ch )
{ {
char *next_line; unsigned char *next_line;
int line_length = 0; // count the length of the current line
for( next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ ) for( next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ )
line_length += gHUD.m_scrinfo.charWidths[*next_line]; ;
char *top = next_line; // int line_length = 0; // count the length of the current line
// for( next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ )
// line_length += gHUD.m_scrinfo.charWidths[*next_line];
unsigned char *top = next_line;
if( *top == '\n' ) if( *top == '\n' )
*top = 0; *top = 0;
else else
@ -107,7 +109,7 @@ int CHudMOTD::Draw( float fTime )
// find where to start drawing the line // find where to start drawing the line
if( ( ypos > ROW_RANGE_MIN ) && ( ypos + LINE_HEIGHT <= ypos_r + height ) ) if( ( ypos > ROW_RANGE_MIN ) && ( ypos + LINE_HEIGHT <= ypos_r + height ) )
DrawUtfString( xpos, ypos, xmax, ch, 255, 180, 0 ); DrawUtfString( xpos, ypos, xmax, (const char*)ch, 255, 180, 0 );
ypos += LINE_HEIGHT; ypos += LINE_HEIGHT;

View File

@ -34,7 +34,7 @@
#include "vgui_TeamFortressViewport.h" #include "vgui_TeamFortressViewport.h"
#endif #endif
#if GOLDSOURCE_SUPPORT && (_WIN32 || __linux__ || __APPLE__) && (__i386 || _M_IX86) #if GOLDSOURCE_SUPPORT && (XASH_WIN32 || XASH_LINUX || XASH_APPLE) && XASH_X86
#define USE_FAKE_VGUI !USE_VGUI #define USE_FAKE_VGUI !USE_VGUI
#if USE_FAKE_VGUI #if USE_FAKE_VGUI
#include "VGUI_Panel.h" #include "VGUI_Panel.h"

View File

@ -28,6 +28,7 @@
#pragma once #pragma once
#if !defined(CL_DLL_H) #if !defined(CL_DLL_H)
#define CL_DLL_H #define CL_DLL_H
#include "build.h"
typedef unsigned char byte; typedef unsigned char byte;
typedef unsigned short word; typedef unsigned short word;
typedef float vec_t; typedef float vec_t;
@ -39,7 +40,7 @@ typedef float vec_t;
#include "../engine/cdll_int.h" #include "../engine/cdll_int.h"
#include "../dlls/cdll_dll.h" #include "../dlls/cdll_dll.h"
#if !_WIN32 #if !XASH_WIN32
#define _cdecl #define _cdecl
#endif #endif
#include "exportdef.h" #include "exportdef.h"
@ -49,9 +50,6 @@ typedef float vec_t;
#else #else
#include <math.h> #include <math.h>
#endif #endif
#if __LP64__ || __LLP64__ || _WIN64 || (__x86_64__ && !__ILP32__) || _M_X64 || __ia64 || _M_IA64 || __aarch64__ || __powerpc64__
#define XASH_64BIT 1
#endif
extern cl_enginefunc_t gEngfuncs; extern cl_enginefunc_t gEngfuncs;
#include "../engine/mobility_int.h" #include "../engine/mobility_int.h"

View File

@ -203,7 +203,8 @@ void VectorScale( const float *in, float scale, float *out );
float VectorNormalize( float *v ); float VectorNormalize( float *v );
void VectorInverse( float *v ); void VectorInverse( float *v );
extern vec3_t vec3_origin; // extern vec3_t vec3_origin;
extern float vec3_origin[3];
// disable 'possible loss of data converting float to int' warning message // disable 'possible loss of data converting float to int' warning message
#pragma warning( disable: 4244 ) #pragma warning( disable: 4244 )

View File

@ -52,6 +52,7 @@ set SOURCES=../dlls/crossbow.cpp ^
input_goldsource.cpp ^ input_goldsource.cpp ^
input_mouse.cpp ^ input_mouse.cpp ^
input_xash3d.cpp ^ input_xash3d.cpp ^
interpolation.cpp ^
menu.cpp ^ menu.cpp ^
message.cpp ^ message.cpp ^
parsemsg.cpp ^ parsemsg.cpp ^

View File

@ -70,6 +70,7 @@ void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args ); void EV_SnarkFire( struct event_args_s *args );
void EV_TrainPitchAdjust( struct event_args_s *args ); void EV_TrainPitchAdjust( struct event_args_s *args );
void EV_VehiclePitchAdjust( event_args_t *args );
} }
#define VECTOR_CONE_1DEGREES Vector( 0.00873f, 0.00873f, 0.00873f ) #define VECTOR_CONE_1DEGREES Vector( 0.00873f, 0.00873f, 0.00873f )
@ -98,6 +99,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
int cnt; int cnt;
float fattn = ATTN_NORM; float fattn = ATTN_NORM;
int entity; int entity;
cl_entity_t *ent;
char *pTextureName; char *pTextureName;
char texname[64]; char texname[64];
char szbuffer[64]; char szbuffer[64];
@ -109,7 +111,8 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v
chTextureType = 0; chTextureType = 0;
// Player // Player
if( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) if( ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() )
|| ( ( ent = gEngfuncs.GetEntityByIndex( entity )) && ( ent->curstate.eflags & EFLAG_MONSTER )))
{ {
// hit body // hit body
chTextureType = CHAR_TEX_FLESH; chTextureType = CHAR_TEX_FLESH;
@ -420,7 +423,7 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int
gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr );
tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
@ -883,7 +886,7 @@ void EV_FireGauss( event_args_t *args )
gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_NORMAL, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates(); gEngfuncs.pEventAPI->EV_PopPMStates();
@ -1004,14 +1007,14 @@ void EV_FireGauss( event_args_t *args )
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_NORMAL, -1, &beam_tr );
if( !beam_tr.allsolid ) if( !beam_tr.allsolid )
{ {
vec3_t delta; vec3_t delta;
// trace backwards to find exit point // trace backwards to find exit point
gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_NORMAL, -1, &beam_tr );
VectorSubtract( beam_tr.endpos, tr.endpos, delta ); VectorSubtract( beam_tr.endpos, tr.endpos, delta );
@ -1214,7 +1217,7 @@ void EV_FireCrossbow2( event_args_t *args )
// Now add in all of the players. // Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr );
//We hit something //We hit something
if( tr.fraction < 1.0f ) if( tr.fraction < 1.0f )
@ -1452,7 +1455,7 @@ void EV_EgonFire( event_args_t *args )
gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 ); gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates(); gEngfuncs.pEventAPI->EV_PopPMStates();
@ -1754,6 +1757,65 @@ void EV_TrainPitchAdjust( event_args_t *args )
} }
} }
void EV_VehiclePitchAdjust( event_args_t *args )
{
int idx;
vec3_t origin;
unsigned short us_params;
int noise;
float m_flVolume;
int pitch;
int stop;
const char *pszSound;
idx = args->entindex;
VectorCopy( args->origin, origin );
us_params = (unsigned short)args->iparam1;
stop = args->bparam1;
m_flVolume = (float)( us_params & 0x003f ) / 40.0f;
noise = (int)( ( ( us_params ) >> 12 ) & 0x0007 );
pitch = (int)( 10.0f * (float)( ( us_params >> 6 ) & 0x003f ) );
switch( noise )
{
case 1:
pszSound = "plats/vehicle1.wav";
break;
case 2:
pszSound = "plats/vehicle2.wav";
break;
case 3:
pszSound = "plats/vehicle3.wav";
break;
case 4:
pszSound = "plats/vehicle4.wav";
break;
case 5:
pszSound = "plats/vehicle6.wav";
break;
case 6:
pszSound = "plats/vehicle7.wav";
break;
default:
// no sound
return;
}
if( stop )
{
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, pszSound );
}
else
{
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, pszSound, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch );
}
}
int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 ) int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 )
{ {
return 0; return 0;

View File

@ -207,9 +207,9 @@ BOOL CBaseMonster::FindLateralCover( const Vector &vecThreat, const Vector &vecV
Vector CBaseMonster::ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; } Vector CBaseMonster::ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; }
BOOL CBaseMonster::FacingIdeal( void ) { return FALSE; } BOOL CBaseMonster::FacingIdeal( void ) { return FALSE; }
BOOL CBaseMonster::FCanActiveIdle( void ) { return FALSE; } BOOL CBaseMonster::FCanActiveIdle( void ) { return FALSE; }
void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { } void CBaseToggle::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { }
void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { } void CBaseToggle::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { }
void CBaseMonster::SentenceStop( void ) { } void CBaseToggle::SentenceStop( void ) { }
void CBaseMonster::CorpseFallThink( void ) { } void CBaseMonster::CorpseFallThink( void ) { }
void CBaseMonster::MonsterInitDead( void ) { } void CBaseMonster::MonsterInitDead( void ) { }
BOOL CBaseMonster::BBoxFlat( void ) { return TRUE; } BOOL CBaseMonster::BBoxFlat( void ) { return TRUE; }

View File

@ -40,6 +40,7 @@ void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args ); void EV_SnarkFire( struct event_args_s *args );
void EV_TrainPitchAdjust( struct event_args_s *args ); void EV_TrainPitchAdjust( struct event_args_s *args );
void EV_VehiclePitchAdjust( event_args_t *args );
} }
/* /*
@ -76,4 +77,5 @@ void Game_HookEvents( void )
gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire ); gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire ); gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire ); gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
gEngfuncs.pfnHookEvent( "events/vehicle.sc", EV_VehiclePitchAdjust );
} }

View File

@ -393,7 +393,7 @@ void CHud::Init( void )
m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE );
m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE );
cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
cl_viewbob = CVAR_CREATE( "cl_viewbob", "0", FCVAR_ARCHIVE ); cl_viewbob = CVAR_CREATE( "cl_viewbob", "1", FCVAR_ARCHIVE );
m_pSpriteList = NULL; m_pSpriteList = NULL;
@ -458,6 +458,8 @@ void CHud::Init( void )
m_Menu.Init(); m_Menu.Init();
MsgFunc_ResetHUD( 0, 0, NULL ); MsgFunc_ResetHUD( 0, 0, NULL );
ClientCmd( "richpresence_gamemode\n" );
ClientCmd( "richpresence_update\n" );
} }
// CHud destructor // CHud destructor

View File

@ -87,6 +87,11 @@ int CHud::MsgFunc_GameMode( const char *pszName, int iSize, void *pbuf )
BEGIN_READ( pbuf, iSize ); BEGIN_READ( pbuf, iSize );
m_Teamplay = READ_BYTE(); m_Teamplay = READ_BYTE();
if( m_Teamplay )
ClientCmd( "richpresence_gamemode Teamplay\n" );
else
ClientCmd( "richpresence_gamemode\n" );
ClientCmd( "richpresence_update\n" );
return 1; return 1;
} }

View File

@ -92,6 +92,11 @@ void CHud::Think( void )
// only let players adjust up in fov, and only if they are not overriden by something else // only let players adjust up in fov, and only if they are not overriden by something else
m_iFOV = Q_max( default_fov->value, 90 ); m_iFOV = Q_max( default_fov->value, 90 );
} }
if( gEngfuncs.IsSpectateOnly() )
{
m_iFOV = gHUD.m_Spectator.GetFOV(); // default_fov->value;
}
} }
// Redraw // Redraw

View File

@ -37,8 +37,6 @@ extern "C" float vJumpAngles[3];
extern void V_GetInEyePos( int entity, float * origin, float * angles ); extern void V_GetInEyePos( int entity, float * origin, float * angles );
extern void V_ResetChaseCam(); extern void V_ResetChaseCam();
extern void V_GetChasePos( int target, float * cl_angles, float * origin, float * angles ); extern void V_GetChasePos( int target, float * cl_angles, float * origin, float * angles );
extern void VectorAngles( const float *forward, float *angles );
extern "C" void NormalizeAngles( float *angles );
extern float * GetClientColor( int clientIndex ); extern float * GetClientColor( int clientIndex );
extern vec3_t v_origin; // last view origin extern vec3_t v_origin; // last view origin
@ -46,6 +44,37 @@ extern vec3_t v_angles; // last view angle
extern vec3_t v_cl_angles; // last client/mouse angle extern vec3_t v_cl_angles; // last client/mouse angle
extern vec3_t v_sim_org; // last sim origin extern vec3_t v_sim_org; // last sim origin
#if 0
const char *GetSpectatorLabel( int iMode )
{
switch( iMode )
{
case OBS_CHASE_LOCKED:
return "#OBS_CHASE_LOCKED";
case OBS_CHASE_FREE:
return "#OBS_CHASE_FREE";
case OBS_ROAMING:
return "#OBS_ROAMING";
case OBS_IN_EYE:
return "#OBS_IN_EYE";
case OBS_MAP_FREE:
return "#OBS_MAP_FREE";
case OBS_MAP_CHASE:
return "#OBS_MAP_CHASE";
case OBS_NONE:
default:
return "#OBS_NONE";
}
}
#endif
void SpectatorMode( void ) void SpectatorMode( void )
{ {
if( gEngfuncs.Cmd_Argc() <= 1 ) if( gEngfuncs.Cmd_Argc() <= 1 )
@ -152,6 +181,7 @@ int CHudSpectator::Init()
m_flNextObserverInput = 0.0f; m_flNextObserverInput = 0.0f;
m_zoomDelta = 0.0f; m_zoomDelta = 0.0f;
m_moveDelta = 0.0f; m_moveDelta = 0.0f;
m_FOV = 90.0f;
m_chatEnabled = ( gHUD.m_SayText.m_HUD_saytext->value != 0 ); m_chatEnabled = ( gHUD.m_SayText.m_HUD_saytext->value != 0 );
iJumpSpectator = 0; iJumpSpectator = 0;
@ -373,6 +403,178 @@ void CHudSpectator::SetSpectatorStartPosition()
iJumpSpectator = 1; // jump anyway iJumpSpectator = 1; // jump anyway
} }
void CHudSpectator::SetCameraView( vec3_t pos, vec3_t angle, float fov )
{
m_FOV = fov;
VectorCopy( pos, vJumpOrigin );
VectorCopy( angle, vJumpAngles );
gEngfuncs.SetViewAngles( vJumpAngles );
iJumpSpectator = 1; // jump anyway
}
void CHudSpectator::AddWaypoint( float time, vec3_t pos, vec3_t angle, float fov, int flags )
{
if( flags == 0 && time == 0.0f )
{
// switch instantly to this camera view
SetCameraView( pos, angle, fov );
return;
}
if( m_NumWayPoints >= MAX_CAM_WAYPOINTS )
{
gEngfuncs.Con_Printf( "Too many camera waypoints!\n" );
return;
}
VectorCopy( angle, m_CamPath[m_NumWayPoints].angle );
VectorCopy( pos, m_CamPath[m_NumWayPoints].position );
m_CamPath[m_NumWayPoints].flags = flags;
m_CamPath[m_NumWayPoints].fov = fov;
m_CamPath[m_NumWayPoints].time = time;
gEngfuncs.Con_DPrintf( "Added waypoint %i\n", m_NumWayPoints );
m_NumWayPoints++;
}
void CHudSpectator::SetWayInterpolation( cameraWayPoint_t *prev, cameraWayPoint_t *start, cameraWayPoint_t *end, cameraWayPoint_t *next )
{
m_WayInterpolation.SetViewAngles( start->angle, end->angle );
m_WayInterpolation.SetFOVs( start->fov, end->fov );
m_WayInterpolation.SetSmoothing( ( start->flags & DRC_FLAG_SLOWSTART ) != 0,
( start->flags & DRC_FLAG_SLOWEND ) != 0 );
if( prev && next )
{
m_WayInterpolation.SetWaypoints( &prev->position, start->position, end->position, &next->position );
}
else if( prev )
{
m_WayInterpolation.SetWaypoints( &prev->position, start->position, end->position, NULL );
}
else if( next )
{
m_WayInterpolation.SetWaypoints( NULL, start->position, end->position, &next->position );
}
else
{
m_WayInterpolation.SetWaypoints( NULL, start->position, end->position, NULL );
}
}
bool CHudSpectator::GetDirectorCamera( vec3_t &position, vec3_t &angle )
{
float now = gHUD.m_flTime;
float fov = 90.0f;
if( m_ChaseEntity )
{
cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_ChaseEntity );
if( ent )
{
vec3_t vt = ent->curstate.origin;
if( m_ChaseEntity <= gEngfuncs.GetMaxClients())
{
if( ent->curstate.solid == SOLID_NOT )
{
vt[2]+= -8 ; // PM_DEAD_VIEWHEIGHT
}
else if( ent->curstate.usehull == 1 )
{
vt[2]+= 12; // VEC_DUCK_VIEW;
}
else
{
vt[2]+= 28; // DEFAULT_VIEWHEIGHT
}
}
vt = vt - position;
VectorAngles( vt, angle );
angle[0] = -angle[0];
return true;
}
else
{
return false;
}
}
if( !m_IsInterpolating )
return false;
if( m_WayPoint < 0 || m_WayPoint >= ( m_NumWayPoints - 1 ))
return false;
cameraWayPoint_t *wp1 = &m_CamPath[m_WayPoint];
cameraWayPoint_t *wp2 = &m_CamPath[m_WayPoint+1];
if( now < wp1->time )
return false;
while( now > wp2->time )
{
// go to next waypoint, if possible
m_WayPoint++;
if( m_WayPoint >= ( m_NumWayPoints - 1 ))
{
m_IsInterpolating = false;
return false; // there is no following waypoint
}
wp1 = wp2;
wp2 = &m_CamPath[m_WayPoint + 1];
if( m_WayPoint > 0 )
{
// we have a predecessor
if( m_WayPoint < ( m_NumWayPoints - 1 ))
{
// we have also a successor
SetWayInterpolation( &m_CamPath[m_WayPoint - 1], wp1, wp2, &m_CamPath[m_WayPoint + 2] );
}
else
{
SetWayInterpolation( &m_CamPath[m_WayPoint - 1], wp1, wp2, NULL );
}
}
else if( m_WayPoint < ( m_NumWayPoints - 1 ))
{
// we only have a successor
SetWayInterpolation( NULL, wp1, wp2, &m_CamPath[m_WayPoint + 2] );
}
else
{
// we have only two waypoints
SetWayInterpolation( NULL, wp1, wp2, NULL );
}
}
if( wp2->time <= wp1->time )
return false;
float fraction = ( now - wp1->time ) / ( wp2->time - wp1->time );
if( fraction < 0.0f )
fraction = 0.0f;
else if( fraction > 1.0f )
fraction = 1.0f;
m_WayInterpolation.Interpolate( fraction, position, angle, &fov );
// gEngfuncs.Con_Printf( "Interpolate time: %.2f, fraction %.2f, point : %.2f,%.2f,%.2f\n", now, fraction, position[0], position[1], position[2] );
SetCameraView( position, angle, fov );
return true;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Loads new icons // Purpose: Loads new icons
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -387,9 +589,21 @@ int CHudSpectator::VidInit()
m_hsprCamera = SPR_Load( "sprites/camera.spr" ); m_hsprCamera = SPR_Load( "sprites/camera.spr" );
m_hCrosshair = SPR_Load( "sprites/crosshairs.spr" ); m_hCrosshair = SPR_Load( "sprites/crosshairs.spr" );
m_lastPrimaryObject = m_lastSecondaryObject = 0;
m_flNextObserverInput = 0.0f;
m_lastHudMessage = 0;
m_iSpectatorNumber = 0;
iJumpSpectator = 0;
g_iUser1 = g_iUser2 = 0;
return 1; return 1;
} }
float CHudSpectator::GetFOV( void )
{
return m_FOV;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
// Input : flTime - // Input : flTime -
@ -437,8 +651,11 @@ int CHudSpectator::Draw( float flTime )
return 1; return 1;
// make sure we have player info // make sure we have player info
#if USE_VGUI
gViewPort->GetAllPlayersInfo();
#else
gHUD.GetAllPlayersInfo(); gHUD.GetAllPlayersInfo();
#endif
// loop through all the players and draw additional infos to their sprites on the map // loop through all the players and draw additional infos to their sprites on the map
for( int i = 0; i < MAX_PLAYERS; i++ ) for( int i = 0; i < MAX_PLAYERS; i++ )
{ {
@ -473,8 +690,10 @@ int CHudSpectator::Draw( float flTime )
void CHudSpectator::DirectorMessage( int iSize, void *pbuf ) void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
{ {
float value; float f1, f2;
char *string; char *string;
vec3_t v1, v2;
int i1, i2, i3;
BEGIN_READ( pbuf, iSize ); BEGIN_READ( pbuf, iSize );
@ -491,7 +710,7 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
gHUD.MsgFunc_InitHUD( NULL, 0, NULL ); gHUD.MsgFunc_InitHUD( NULL, 0, NULL );
gHUD.MsgFunc_ResetHUD( NULL, 0, NULL ); gHUD.MsgFunc_ResetHUD( NULL, 0, NULL );
break; break;
case DRC_CMD_EVENT: case DRC_CMD_EVENT: // old director style message
m_lastPrimaryObject = READ_WORD(); m_lastPrimaryObject = READ_WORD();
m_lastSecondaryObject = READ_WORD(); m_lastSecondaryObject = READ_WORD();
m_iObserverFlags = READ_LONG(); m_iObserverFlags = READ_LONG();
@ -514,19 +733,22 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
} }
break; break;
case DRC_CMD_CAMERA: case DRC_CMD_CAMERA:
v1[0] = READ_COORD(); // position
v1[1] = READ_COORD();
v1[2] = READ_COORD(); // vJumpOrigin
v1[0] = READ_COORD(); // view angle
v1[1] = READ_COORD(); // vJumpAngles
v1[2] = READ_COORD();
f1 = READ_BYTE(); // fov
i1 = READ_WORD(); // target
if( m_autoDirector->value ) if( m_autoDirector->value )
{ {
vJumpOrigin[0] = READ_COORD(); // position SetModes( OBS_ROAMING, -1 );
vJumpOrigin[1] = READ_COORD(); SetCameraView( v1, v2, f1 );
vJumpOrigin[2] = READ_COORD(); m_ChaseEntity = i1;
vJumpAngles[0] = READ_COORD(); // view angle
vJumpAngles[1] = READ_COORD();
vJumpAngles[2] = READ_COORD();
gEngfuncs.SetViewAngles( vJumpAngles );
iJumpSpectator = 1;
} }
break; break;
case DRC_CMD_MESSAGE: case DRC_CMD_MESSAGE:
@ -563,13 +785,13 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
break; break;
case DRC_CMD_SOUND: case DRC_CMD_SOUND:
string = READ_STRING(); string = READ_STRING();
value = READ_FLOAT(); f1 = READ_FLOAT();
// gEngfuncs.Con_Printf("DRC_CMD_FX_SOUND: %s %.2f\n", string, value ); // gEngfuncs.Con_Printf("DRC_CMD_FX_SOUND: %s %.2f\n", string, f1 );
gEngfuncs.pEventAPI->EV_PlaySound( 0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM ); gEngfuncs.pEventAPI->EV_PlaySound( 0, v_origin, CHAN_BODY, string, f1, ATTN_NORM, 0, PITCH_NORM );
break; break;
case DRC_CMD_TIMESCALE: case DRC_CMD_TIMESCALE:
value = READ_FLOAT(); f1 = READ_FLOAT();
break; break;
case DRC_CMD_STATUS: case DRC_CMD_STATUS:
READ_LONG(); // total number of spectator slots READ_LONG(); // total number of spectator slots
@ -586,13 +808,71 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
gViewPort->UpdateSpectatorPanel(); gViewPort->UpdateSpectatorPanel();
#endif #endif
break; break;
case DRC_CMD_FADE:
break;
case DRC_CMD_STUFFTEXT: case DRC_CMD_STUFFTEXT:
gEngfuncs.pfnFilteredClientCmd( READ_STRING() ); gEngfuncs.pfnFilteredClientCmd( READ_STRING() );
break; break;
case DRC_CMD_CAMPATH:
v1[0] = READ_COORD(); // position
v1[1] = READ_COORD();
v1[2] = READ_COORD(); // vJumpOrigin
v2[0] = READ_COORD(); // view angle
v2[1] = READ_COORD(); // vJumpAngles
v2[2] = READ_COORD();
f1 = READ_BYTE(); // FOV
i1 = READ_BYTE(); // flags
if( m_autoDirector->value )
{
SetModes( OBS_ROAMING, -1 );
SetCameraView( v1, v2, f1 );
}
break;
case DRC_CMD_WAYPOINTS:
i1 = READ_BYTE();
m_NumWayPoints = 0;
m_WayPoint = 0;
for( i2 = 0; i2 < i1; i2++ )
{
f1 = gHUD.m_flTime + (float)( READ_SHORT()) / 100.0f;
v1[0] = READ_COORD(); // position
v1[1] = READ_COORD();
v1[2] = READ_COORD(); // vJumpOrigin
v2[0] = READ_COORD(); // view angle
v2[1] = READ_COORD(); // vJumpAngles
v2[2] = READ_COORD();
f2 = READ_BYTE(); // fov
i3 = READ_BYTE(); // flags
AddWaypoint( f1, v1, v2, f2, i3 );
}
// gEngfuncs.Con_Printf( "CHudSpectator::DirectorMessage: waypoints %i.\n", m_NumWayPoints );
if( !m_autoDirector->value )
{
// ignore waypoints
m_NumWayPoints = 0;
break;
}
SetModes( OBS_ROAMING, -1 );
m_IsInterpolating = true;
if( m_NumWayPoints > 2 )
{
SetWayInterpolation( NULL, &m_CamPath[0], &m_CamPath[1], &m_CamPath[2] );
}
else
{
SetWayInterpolation( NULL, &m_CamPath[0], &m_CamPath[1], NULL );
}
break;
default: default:
gEngfuncs.Con_DPrintf( "CHudSpectator::DirectorMessage: unknown command %i.\n", cmd ); gEngfuncs.Con_DPrintf( "CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );
break;
} }
} }
@ -607,9 +887,10 @@ void CHudSpectator::FindNextPlayer( bool bReverse )
// if we are NOT in HLTV mode, spectator targets are set on server // if we are NOT in HLTV mode, spectator targets are set on server
if( !gEngfuncs.IsSpectateOnly() ) if( !gEngfuncs.IsSpectateOnly() )
{ {
char cmdstring[32]; char cmdstring[256];
// forward command to server // forward command to server
sprintf( cmdstring, "follownext %i", bReverse ? 1 : 0 ); _snprintf( cmdstring, sizeof( cmdstring ) - 1,"follownext %i", bReverse ? 1 : 0 );
cmdstring[sizeof( cmdstring ) - 1] = '\0';
gEngfuncs.pfnServerCmd( cmdstring ); gEngfuncs.pfnServerCmd( cmdstring );
return; return;
} }
@ -626,8 +907,11 @@ void CHudSpectator::FindNextPlayer( bool bReverse )
int iDir = bReverse ? -1 : 1; int iDir = bReverse ? -1 : 1;
// make sure we have player info // make sure we have player info
#if USE_VGUI
gViewPort->GetAllPlayersInfo();
#else
gHUD.GetAllPlayersInfo(); gHUD.GetAllPlayersInfo();
#endif
do do
{ {
iCurrent += iDir; iCurrent += iDir;
@ -668,7 +952,7 @@ void CHudSpectator::FindNextPlayer( bool bReverse )
#endif #endif
} }
void CHudSpectator::FindPlayer(const char *name) void CHudSpectator::FindPlayer( const char *name )
{ {
// MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching
// only a subset of the players. e.g. Make it check the target's team. // only a subset of the players. e.g. Make it check the target's team.
@ -676,18 +960,22 @@ void CHudSpectator::FindPlayer(const char *name)
// if we are NOT in HLTV mode, spectator targets are set on server // if we are NOT in HLTV mode, spectator targets are set on server
if ( !gEngfuncs.IsSpectateOnly() ) if ( !gEngfuncs.IsSpectateOnly() )
{ {
char cmdstring[32]; char cmdstring[256];
// forward command to server // forward command to server
sprintf(cmdstring,"follow %s",name); _snprintf( cmdstring, sizeof( cmdstring ) - 1, "follow %s", name );
gEngfuncs.pfnServerCmd(cmdstring); cmdstring[sizeof( cmdstring ) - 1] = '\0';
gEngfuncs.pfnServerCmd( cmdstring );
return; return;
} }
g_iUser2 = 0; g_iUser2 = 0;
// make sure we have player info // make sure we have player info
#if USE_VGUI
gViewPort->GetAllPlayersInfo();
#else
gHUD.GetAllPlayersInfo(); gHUD.GetAllPlayersInfo();
#endif
cl_entity_t * pEnt = NULL; cl_entity_t * pEnt = NULL;
for (int i = 1; i < MAX_PLAYERS; i++ ) for (int i = 1; i < MAX_PLAYERS; i++ )
@ -859,16 +1147,19 @@ void CHudSpectator::SetModes( int iNewMainMode, int iNewInsetMode )
return; return;
} }
// main modes ettings will override inset window settings m_IsInterpolating = false;
m_ChaseEntity = 0;
// main modes settings will override inset window settings
if( iNewMainMode != g_iUser1 ) if( iNewMainMode != g_iUser1 )
{ {
// if we are NOT in HLTV mode, main spectator mode is set on server // if we are NOT in HLTV mode, main spectator mode is set on server
if( !gEngfuncs.IsSpectateOnly() ) if( !gEngfuncs.IsSpectateOnly() )
{ {
char cmdstring[32]; char cmdstring[256];
// forward command to server // forward command to server
sprintf( cmdstring, "spec_mode %i", iNewMainMode ); _snprintf( cmdstring, sizeof( cmdstring ) - 1,"spec_mode %i", iNewMainMode );
cmdstring[sizeof( cmdstring ) - 1] = '\0';
gEngfuncs.pfnServerCmd( cmdstring ); gEngfuncs.pfnServerCmd( cmdstring );
return; return;
} }
@ -1565,8 +1856,9 @@ void CHudSpectator::CheckSettings()
if( gEngfuncs.IsSpectateOnly() ) if( gEngfuncs.IsSpectateOnly() )
{ {
// tell proxy our new chat mode // tell proxy our new chat mode
char chatcmd[32]; char chatcmd[256];
sprintf( chatcmd, "ignoremsg %i", m_chatEnabled ? 0 : 1 ); _snprintf( chatcmd, sizeof( chatcmd ) - 1, "ignoremsg %i", m_chatEnabled ? 0 : 1 );
chatcmd[sizeof( chatcmd ) - 1] = '\0';
gEngfuncs.pfnServerCmd( chatcmd ); gEngfuncs.pfnServerCmd( chatcmd );
} }
} }
@ -1645,6 +1937,12 @@ void CHudSpectator::Reset()
memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities) ); memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities) );
m_FOV = 90.0f;
m_IsInterpolating = false;
m_ChaseEntity = 0;
SetSpectatorStartPosition(); SetSpectatorStartPosition();
} }
@ -1667,7 +1965,7 @@ void CHudSpectator::InitHUDData()
Reset(); Reset();
SetModes( OBS_CHASE_FREE, INSET_OFF ); SetModes( OBS_CHASE_LOCKED, INSET_OFF );
g_iUser2 = 0; // fake not target until first camera command g_iUser2 = 0; // fake not target until first camera command

View File

@ -10,6 +10,7 @@
#define HUD_SPECTATOR_H #define HUD_SPECTATOR_H
#include "cl_entity.h" #include "cl_entity.h"
#include "interpolation.h"
#define INSET_OFF 0 #define INSET_OFF 0
#define INSET_CHASE_FREE 1 #define INSET_CHASE_FREE 1
@ -22,6 +23,9 @@
#define OVERVIEW_TILE_SIZE 128 // don't change this #define OVERVIEW_TILE_SIZE 128 // don't change this
#define OVERVIEW_MAX_LAYERS 1 #define OVERVIEW_MAX_LAYERS 1
extern void VectorAngles( const float *forward, float *angles );
extern "C" void NormalizeAngles( float *angles );
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it ) // Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -49,7 +53,17 @@ typedef struct overviewEntity_s
double killTime; double killTime;
} overviewEntity_t; } overviewEntity_t;
typedef struct cameraWayPoint_s
{
float time;
vec3_t position;
vec3_t angle;
float fov;
int flags;
} cameraWayPoint_t;
#define MAX_OVERVIEW_ENTITIES 128 #define MAX_OVERVIEW_ENTITIES 128
#define MAX_CAM_WAYPOINTS 32
class CHudSpectator : public CHudBase class CHudSpectator : public CHudBase
{ {
@ -73,7 +87,7 @@ public:
void HandleButtonsDown( int ButtonPressed ); void HandleButtonsDown( int ButtonPressed );
void HandleButtonsUp( int ButtonPressed ); void HandleButtonsUp( int ButtonPressed );
void FindNextPlayer( bool bReverse ); void FindNextPlayer( bool bReverse );
void FindPlayer(const char *name); void FindPlayer( const char *name );
void DirectorMessage( int iSize, void *pbuf ); void DirectorMessage( int iSize, void *pbuf );
void SetSpectatorStartPosition(); void SetSpectatorStartPosition();
int Init(); int Init();
@ -81,6 +95,13 @@ public:
int Draw( float flTime ); int Draw( float flTime );
void AddWaypoint( float time, vec3_t pos, vec3_t angle, float fov, int flags );
void SetCameraView( vec3_t pos, vec3_t angle, float fov );
float GetFOV();
bool GetDirectorCamera( vec3_t &position, vec3_t &angle );
void SetWayInterpolation( cameraWayPoint_t *prev, cameraWayPoint_t *start, cameraWayPoint_t *end, cameraWayPoint_t *next );
int m_iDrawCycle; int m_iDrawCycle;
client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES]; client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES];
char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128]; char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128];
@ -100,8 +121,13 @@ public:
qboolean m_chatEnabled; qboolean m_chatEnabled;
qboolean m_IsInterpolating;
int m_ChaseEntity; // if != 0, follow this entity with viewangles
int m_WayPoint; // current waypoint 1
int m_NumWayPoints; // current number of waypoints
vec3_t m_cameraOrigin; // a help camera vec3_t m_cameraOrigin; // a help camera
vec3_t m_cameraAngles; // and it's angles vec3_t m_cameraAngles; // and it's angles
CInterpolation m_WayInterpolation;
private: private:
vec3_t m_vPlayerPos[MAX_PLAYERS]; vec3_t m_vPlayerPos[MAX_PLAYERS];
@ -119,9 +145,11 @@ private:
struct model_s *m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame struct model_s *m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame
float m_flNextObserverInput; float m_flNextObserverInput;
float m_FOV;
float m_zoomDelta; float m_zoomDelta;
float m_moveDelta; float m_moveDelta;
int m_lastPrimaryObject; int m_lastPrimaryObject;
int m_lastSecondaryObject; int m_lastSecondaryObject;
cameraWayPoint_t m_CamPath[MAX_CAM_WAYPOINTS];
}; };
#endif // SPECTATOR_H #endif // SPECTATOR_H

View File

@ -15,7 +15,7 @@
#include "camera.h" #include "camera.h"
#include "in_defs.h" #include "in_defs.h"
#if _WIN32 #if XASH_WIN32
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define WIN32_EXTRA_LEAN #define WIN32_EXTRA_LEAN
#define HSPRITE WINDOWS_HSPRITE #define HSPRITE WINDOWS_HSPRITE

View File

@ -23,7 +23,7 @@
#include "keydefs.h" #include "keydefs.h"
#include "view.h" #include "view.h"
#if !_WIN32 #if !XASH_WIN32
#define USE_SDL2 1 #define USE_SDL2 1
#endif #endif
@ -114,7 +114,7 @@ static SDLFunction sdlFunctions[] = {
}; };
#endif #endif
#if _WIN32 #if XASH_WIN32
#include <process.h> #include <process.h>
#else #else
typedef unsigned int DWORD; typedef unsigned int DWORD;
@ -149,7 +149,7 @@ extern cvar_t *cl_forwardspeed;
extern cvar_t *cl_pitchspeed; extern cvar_t *cl_pitchspeed;
extern cvar_t *cl_movespeedkey; extern cvar_t *cl_movespeedkey;
#if _WIN32 #if XASH_WIN32
static cvar_t* m_rawinput = NULL; static cvar_t* m_rawinput = NULL;
static double s_flRawInputUpdateTime = 0.0f; static double s_flRawInputUpdateTime = 0.0f;
static bool m_bRawInput = false; static bool m_bRawInput = false;
@ -157,7 +157,7 @@ static bool m_bMouseThread = false;
bool isMouseRelative = false; bool isMouseRelative = false;
#endif #endif
#if _WIN32 #if XASH_WIN32
#include "progdefs.h" #include "progdefs.h"
#endif #endif
@ -184,7 +184,7 @@ static cvar_t *m_customaccel_max;
//Mouse move is raised to this power before being scaled by scale factor //Mouse move is raised to this power before being scaled by scale factor
static cvar_t *m_customaccel_exponent; static cvar_t *m_customaccel_exponent;
#if _WIN32 #if XASH_WIN32
// if threaded mouse is enabled then the time to sleep between polls // if threaded mouse is enabled then the time to sleep between polls
static cvar_t *m_mousethread_sleep; static cvar_t *m_mousethread_sleep;
#endif #endif
@ -218,7 +218,7 @@ enum _ControlList
AxisTurn AxisTurn
}; };
#if !USE_SDL2 && _WIN32 #if !USE_SDL2 && XASH_WIN32
DWORD dwAxisFlags[JOY_MAX_AXES] = DWORD dwAxisFlags[JOY_MAX_AXES] =
{ {
JOY_RETURNX, JOY_RETURNX,
@ -234,7 +234,7 @@ DWORD dwAxisMap[ JOY_MAX_AXES ];
DWORD dwControlMap[ JOY_MAX_AXES ]; DWORD dwControlMap[ JOY_MAX_AXES ];
#if USE_SDL2 #if USE_SDL2
int pdwRawValue[ JOY_MAX_AXES ]; int pdwRawValue[ JOY_MAX_AXES ];
#elif _WIN32 #elif XASH_WIN32
PDWORD pdwRawValue[ JOY_MAX_AXES ]; PDWORD pdwRawValue[ JOY_MAX_AXES ];
#endif #endif
DWORD joy_oldbuttonstate, joy_oldpovstate; DWORD joy_oldbuttonstate, joy_oldpovstate;
@ -244,7 +244,7 @@ DWORD joy_numbuttons;
#if USE_SDL2 #if USE_SDL2
SDL_GameController *s_pJoystick = NULL; SDL_GameController *s_pJoystick = NULL;
#elif _WIN32 #elif XASH_WIN32
DWORD joy_flags; DWORD joy_flags;
static JOYINFOEX ji; static JOYINFOEX ji;
#endif #endif
@ -276,7 +276,7 @@ cvar_t *joy_wwhack2;
int joy_avail, joy_advancedinit, joy_haspov; int joy_avail, joy_advancedinit, joy_haspov;
#if _WIN32 #if XASH_WIN32
unsigned int s_hMouseThreadId = 0; unsigned int s_hMouseThreadId = 0;
HANDLE s_hMouseThread = 0; HANDLE s_hMouseThread = 0;
HANDLE s_hMouseQuitEvent = 0; HANDLE s_hMouseQuitEvent = 0;
@ -300,7 +300,7 @@ void Force_CenterView_f (void)
} }
} }
#if _WIN32 #if XASH_WIN32
LONG mouseThreadActive = 0; LONG mouseThreadActive = 0;
LONG mouseThreadCenterX = 0; LONG mouseThreadCenterX = 0;
@ -382,7 +382,7 @@ void IN_SetMouseMode(bool enable)
if(enable) if(enable)
{ {
#if _WIN32 #if XASH_WIN32
if (mouseparmsvalid) if (mouseparmsvalid)
restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
@ -402,7 +402,7 @@ void IN_SetMouseMode(bool enable)
} }
else else
{ {
#if _WIN32 #if XASH_WIN32
if(isMouseRelative) if(isMouseRelative)
{ {
#if USE_SDL2 #if USE_SDL2
@ -423,7 +423,7 @@ void IN_SetMouseMode(bool enable)
void IN_SetVisibleMouse(bool visible) void IN_SetVisibleMouse(bool visible)
{ {
#if _WIN32 #if XASH_WIN32
bool lockEntered = MouseThread_ActiveLock_Enter(); bool lockEntered = MouseThread_ActiveLock_Enter();
#endif #endif
@ -431,7 +431,7 @@ void IN_SetVisibleMouse(bool visible)
IN_SetMouseMode(!visible); IN_SetMouseMode(!visible);
#if _WIN32 #if XASH_WIN32
UpdateMouseThreadActive(); UpdateMouseThreadActive();
if(lockEntered) MouseThread_ActiveLock_Exit(); if(lockEntered) MouseThread_ActiveLock_Exit();
#endif #endif
@ -448,7 +448,7 @@ void GoldSourceInput::IN_ActivateMouse (void)
{ {
if (mouseinitialized) if (mouseinitialized)
{ {
#if _WIN32 #if XASH_WIN32
bool lockEntered = MouseThread_ActiveLock_Enter(); bool lockEntered = MouseThread_ActiveLock_Enter();
#endif #endif
@ -456,7 +456,7 @@ void GoldSourceInput::IN_ActivateMouse (void)
mouseactive = 1; mouseactive = 1;
#if _WIN32 #if XASH_WIN32
UpdateMouseThreadActive(); UpdateMouseThreadActive();
if(lockEntered) MouseThread_ActiveLock_Exit(); if(lockEntered) MouseThread_ActiveLock_Exit();
#endif #endif
@ -476,7 +476,7 @@ void GoldSourceInput::IN_DeactivateMouse (void)
{ {
if (mouseinitialized) if (mouseinitialized)
{ {
#if _WIN32 #if XASH_WIN32
bool lockEntered = MouseThread_ActiveLock_Enter(); bool lockEntered = MouseThread_ActiveLock_Enter();
#endif #endif
@ -484,7 +484,7 @@ void GoldSourceInput::IN_DeactivateMouse (void)
mouseactive = 0; mouseactive = 0;
#if _WIN32 #if XASH_WIN32
UpdateMouseThreadActive(); UpdateMouseThreadActive();
if(lockEntered) MouseThread_ActiveLock_Exit(); if(lockEntered) MouseThread_ActiveLock_Exit();
#endif #endif
@ -502,7 +502,7 @@ void GoldSourceInput::IN_StartupMouse (void)
return; return;
mouseinitialized = 1; mouseinitialized = 1;
#if _WIN32 #if XASH_WIN32
mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0);
if (mouseparmsvalid) if (mouseparmsvalid)
@ -537,7 +537,7 @@ void GoldSourceInput::IN_Shutdown (void)
{ {
IN_DeactivateMouse (); IN_DeactivateMouse ();
#if _WIN32 #if XASH_WIN32
if ( s_hMouseQuitEvent ) if ( s_hMouseQuitEvent )
{ {
SetEvent( s_hMouseQuitEvent ); SetEvent( s_hMouseQuitEvent );
@ -597,7 +597,7 @@ FIXME: Call through to engine?
void IN_ResetMouse( void ) void IN_ResetMouse( void )
{ {
// no work to do in SDL // no work to do in SDL
#if _WIN32 #if XASH_WIN32
// reset only if mouse is active and not in visible mode: // reset only if mouse is active and not in visible mode:
if(mouseactive && !iVisibleMouse && gEngfuncs.GetWindowCenterX && gEngfuncs.GetWindowCenterY) if(mouseactive && !iVisibleMouse && gEngfuncs.GetWindowCenterX && gEngfuncs.GetWindowCenterY)
{ {
@ -712,7 +712,7 @@ void GoldSourceInput::IN_GetMouseDelta( int *pOutX, int *pOutY)
if(active) if(active)
{ {
int deltaX, deltaY; int deltaX, deltaY;
#if _WIN32 #if XASH_WIN32
if ( !m_bRawInput ) if ( !m_bRawInput )
{ {
if ( m_bMouseThread ) if ( m_bMouseThread )
@ -746,7 +746,7 @@ void GoldSourceInput::IN_GetMouseDelta( int *pOutX, int *pOutY)
#endif #endif
} }
#if _WIN32 #if XASH_WIN32
if ( !m_bRawInput ) if ( !m_bRawInput )
{ {
if ( m_bMouseThread ) if ( m_bMouseThread )
@ -771,7 +771,7 @@ void GoldSourceInput::IN_GetMouseDelta( int *pOutX, int *pOutY)
my_accum = 0; my_accum = 0;
// reset mouse position if required, so there is room to move: // reset mouse position if required, so there is room to move:
#if _WIN32 #if XASH_WIN32
// do not reset if mousethread would do it: // do not reset if mousethread would do it:
if ( m_bRawInput || !m_bMouseThread ) if ( m_bRawInput || !m_bMouseThread )
#else #else
@ -779,7 +779,7 @@ void GoldSourceInput::IN_GetMouseDelta( int *pOutX, int *pOutY)
#endif #endif
IN_ResetMouse(); IN_ResetMouse();
#if _WIN32 #if XASH_WIN32
// update m_bRawInput occasionally: // update m_bRawInput occasionally:
const float currentTime = gEngfuncs.GetClientTime(); const float currentTime = gEngfuncs.GetClientTime();
if ( currentTime - s_flRawInputUpdateTime > 1.0f || s_flRawInputUpdateTime == 0.0f ) if ( currentTime - s_flRawInputUpdateTime > 1.0f || s_flRawInputUpdateTime == 0.0f )
@ -929,7 +929,7 @@ void GoldSourceInput::IN_Accumulate (void)
{ {
if (mouseactive) if (mouseactive)
{ {
#if _WIN32 #if XASH_WIN32
if ( !m_bRawInput ) if ( !m_bRawInput )
{ {
if ( !m_bMouseThread ) if ( !m_bMouseThread )
@ -957,7 +957,7 @@ void GoldSourceInput::IN_Accumulate (void)
} }
// force the mouse to the center, so there's room to move // force the mouse to the center, so there's room to move
#if _WIN32 #if XASH_WIN32
// do not reset if mousethread would do it: // do not reset if mousethread would do it:
if ( m_bRawInput || !m_bMouseThread ) if ( m_bRawInput || !m_bMouseThread )
#else #else
@ -1030,7 +1030,7 @@ void IN_StartupJoystick (void)
{ {
gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n"); gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n");
} }
#elif _WIN32 #elif XASH_WIN32
int numdevs; int numdevs;
JOYCAPS jc; JOYCAPS jc;
MMRESULT mmr; MMRESULT mmr;
@ -1102,7 +1102,7 @@ int RawValuePointer (int axis)
} }
} }
#elif _WIN32 #elif XASH_WIN32
PDWORD RawValuePointer (int axis) PDWORD RawValuePointer (int axis)
{ {
switch (axis) switch (axis)
@ -1185,7 +1185,7 @@ void Joy_AdvancedUpdate_f (void)
dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS; dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
} }
#if !USE_SDL2 && _WIN32 #if !USE_SDL2 && XASH_WIN32
// compute the axes to collect from DirectInput // compute the axes to collect from DirectInput
joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV; joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
for (i = 0; i < JOY_MAX_AXES; i++) for (i = 0; i < JOY_MAX_AXES; i++)
@ -1231,7 +1231,7 @@ void GoldSourceInput::IN_Commands (void)
{ {
pdwRawValue[i] = RawValuePointer(i); pdwRawValue[i] = RawValuePointer(i);
} }
#elif _WIN32 #elif XASH_WIN32
buttonstate = ji.dwButtons; buttonstate = ji.dwButtons;
#endif #endif
@ -1257,7 +1257,7 @@ void GoldSourceInput::IN_Commands (void)
// this avoids any potential problems related to moving from one // this avoids any potential problems related to moving from one
// direction to another without going through the center position // direction to another without going through the center position
povstate = 0; povstate = 0;
#if !USE_SDL2 && _WIN32 #if !USE_SDL2 && XASH_WIN32
if(ji.dwPOV != JOY_POVCENTERED) if(ji.dwPOV != JOY_POVCENTERED)
{ {
if (ji.dwPOV == JOY_POVFORWARD) if (ji.dwPOV == JOY_POVFORWARD)
@ -1298,7 +1298,7 @@ int IN_ReadJoystick (void)
#if USE_SDL2 #if USE_SDL2
safe_pfnSDL_JoystickUpdate(); safe_pfnSDL_JoystickUpdate();
return 1; return 1;
#elif _WIN32 #elif XASH_WIN32
memset (&ji, 0, sizeof(ji)); memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji); ji.dwSize = sizeof(ji);
ji.dwFlags = joy_flags; ji.dwFlags = joy_flags;
@ -1377,7 +1377,7 @@ void IN_JoyMove ( float frametime, usercmd_t *cmd )
// get the floating point zero-centered, potentially-inverted data for the current axis // get the floating point zero-centered, potentially-inverted data for the current axis
#if USE_SDL2 #if USE_SDL2
fAxisValue = (float)pdwRawValue[i]; fAxisValue = (float)pdwRawValue[i];
#elif _WIN32 #elif XASH_WIN32
fAxisValue = (float) *pdwRawValue[i]; fAxisValue = (float) *pdwRawValue[i];
fAxisValue -= 32768.0; fAxisValue -= 32768.0;
#endif #endif
@ -1571,7 +1571,7 @@ void GoldSourceInput::IN_Init (void)
m_customaccel_max = gEngfuncs.pfnRegisterVariable ( "m_customaccel_max", "0", FCVAR_ARCHIVE ); m_customaccel_max = gEngfuncs.pfnRegisterVariable ( "m_customaccel_max", "0", FCVAR_ARCHIVE );
m_customaccel_exponent = gEngfuncs.pfnRegisterVariable ( "m_customaccel_exponent", "1", FCVAR_ARCHIVE ); m_customaccel_exponent = gEngfuncs.pfnRegisterVariable ( "m_customaccel_exponent", "1", FCVAR_ARCHIVE );
#if _WIN32 #if XASH_WIN32
m_rawinput = gEngfuncs.pfnGetCvarPointer("m_rawinput"); m_rawinput = gEngfuncs.pfnGetCvarPointer("m_rawinput");
m_bRawInput = m_rawinput && m_rawinput->value != 0; m_bRawInput = m_rawinput && m_rawinput->value != 0;
m_bMouseThread = gEngfuncs.CheckParm ("-mousethread", NULL ) != NULL; m_bMouseThread = gEngfuncs.CheckParm ("-mousethread", NULL ) != NULL;
@ -1603,7 +1603,7 @@ void GoldSourceInput::IN_Init (void)
#endif #endif
#if USE_SDL2 #if USE_SDL2
#if __APPLE__ #if XASH_APPLE
#define SDL2_FULL_LIBNAME "libsdl2-2.0.0.dylib" #define SDL2_FULL_LIBNAME "libsdl2-2.0.0.dylib"
#else #else
#define SDL2_FULL_LIBNAME "libSDL2-2.0.so.0" #define SDL2_FULL_LIBNAME "libSDL2-2.0.so.0"

View File

@ -1,7 +1,4 @@
#pragma once #pragma once
#include "build.h"
#if !defined(INPUT_MOUSE_H) #if !defined(INPUT_MOUSE_H)
#define INPUT_MOUSE_H #define INPUT_MOUSE_H
#include "cl_dll.h" #include "cl_dll.h"
@ -51,7 +48,7 @@ protected:
#if GOLDSOURCE_SUPPORT && ( XASH_WIN32 || ( XASH_LINUX && !XASH_ANDROID ) || XASH_APPLE ) && XASH_X86 #if GOLDSOURCE_SUPPORT && ( XASH_WIN32 || ( XASH_LINUX && !XASH_ANDROID ) || XASH_APPLE ) && XASH_X86
#define SUPPORT_GOLDSOURCE_INPUT 1 #define SUPPORT_GOLDSOURCE_INPUT 1
#if _WIN32 #if XASH_WIN32
#define HSPRITE WINDOWS_HSPRITE #define HSPRITE WINDOWS_HSPRITE
#include <windows.h> #include <windows.h>
#undef HSPRITE #undef HSPRITE

217
cl_dll/interpolation.cpp Normal file
View File

@ -0,0 +1,217 @@
/************ (C) Copyright 2003 Valve, L.L.C. All rights reserved. ***********
**
** The copyright to the contents herein is the property of Valve, L.L.C.
** The contents may be used and/or copied only with the written permission of
** Valve, L.L.C., or in accordance with the terms and conditions stipulated in
** the agreement/contract under which the contents have been supplied.
**
*******************************************************************************
**
** Contents:
**
** interpolation.cpp: implementation of the interpolation class
**
******************************************************************************/
#include "hud.h"
#include "cl_util.h"
#include "interpolation.h"
// = determinant of matrix a,b,c
#define Determinant( a, b, c ) ( (a)[2] * ( (b)[0]*(c)[1] - (b)[1]*(c)[0] ) + \
(a)[1] * ( (b)[2]*(c)[0] - (b)[0]*(c)[2] ) + \
(a)[0] * ( (b)[1]*(c)[2] - (b)[2]*(c)[1] ) )
// solve 3 vector linear system of equations v0 = x*v1 + y*v2 + z*v3 (if possible)
bool SolveLSE( vec3_t v0, vec3_t v1, vec3_t v2, vec3_t v3, float * x, float * y, float * z )
{
float d = Determinant( v1, v2, v3 );
if( d == 0.0f )
return false;
if( x )
*x = Determinant( v0, v2, v3 ) / d;
if( y )
*y= Determinant( v1, v0, v3 ) / d;
if( z )
*z= Determinant( v1, v2, v0 ) / d;
return true;
}
// p = closest point between vector lines a1+x*m1 and a2+x*m2
bool GetPointBetweenLines( vec3_t &p, vec3_t a1, vec3_t m1, vec3_t a2, vec3_t m2 )
{
float x, z;
vec3_t t1 = CrossProduct( m1, m2 );
vec3_t t2 = a2 - a1;
if( !SolveLSE( t2, m1, t1, m2, &x , NULL, &z ) )
return false;
t1 = a1 + x * m1;
t2 = a2 + ( -z ) * m2;
p = ( t1 + t2 ) / 2.0f;
return true;
}
// Bernstein Poynom B(u) with n = 2, i = 0
#define BernsteinPolynom20(u) ( ( 1.0f - u ) * ( 1.0f - u ))
#define BernsteinPolynom21(u) ( 2.0f * u * ( 1.0f - u ) )
#define BernsteinPolynom22(u) ( u * u )
CInterpolation::CInterpolation()
{
}
CInterpolation::~CInterpolation()
{
m_SmoothStart = m_SmoothEnd = false;
}
void CInterpolation::SetViewAngles( vec3_t start, vec3_t end )
{
m_StartAngle = start;
m_EndAngle = end;
NormalizeAngles( m_StartAngle );
NormalizeAngles( m_EndAngle );
}
void CInterpolation::SetFOVs( float start, float end )
{
m_StartFov = start;
m_EndFov = end;
}
void CInterpolation::SetWaypoints( vec3_t *prev, vec3_t start, vec3_t end, vec3_t *next )
{
m_StartPoint = start;
m_EndPoint = end;
vec3_t a, b, c, d;
if( !prev && !next )
{
// no direction given, straight linear interpolation
m_Center = ( m_StartPoint + m_EndPoint ) / 2.0f;
}
else if( !prev )
{
a = start - end;
float dist = a.Length() / 2.0f;
a = a.Normalize();
b = *next - end;
b = b.Normalize();
c = a - b;
c = c.Normalize();
m_Center = end + c * dist;
}
else if( !next )
{
a = *prev - start;
a = a.Normalize();
b = end - start;
float dist = b.Length() / 2.0f;
b = b.Normalize();
c = b - a;
c = c.Normalize();
m_Center = start + c * dist;
}
else
{
// we have a previous and a next point, great!
a = *prev - start;
a = a.Normalize();
b = end - start;
b = b.Normalize();
c = b - a;
a = start - end;
a = a.Normalize();
b = *next - end;
b = b.Normalize();
d = a - b;
GetPointBetweenLines( m_Center, start, c, end, d );
}
}
void CInterpolation::Interpolate( float t, vec3_t &point, vec3_t &angle, float *fov )
{
if( m_SmoothStart && m_SmoothEnd )
{
t = ( 1.0f - t ) * ( t * t ) + t * ( 1.0f - ( ( t - 1.0f ) * ( t - 1.0f )));
}
else if( m_SmoothStart )
{
t = t * t;
}
else if( m_SmoothEnd )
{
t = t - 1.0f;
t = -( t * t ) + 1;
}
if( point )
{
BezierInterpolatePoint( t, point );
}
if( angle )
{
InterpolateAngle( t, angle );
}
if( fov )
{
*fov = m_StartFov + ( t * ( m_EndFov - m_StartFov ));
}
}
void CInterpolation::BezierInterpolatePoint( float t, vec3_t &point )
{
point = m_StartPoint * BernsteinPolynom20( t );
point = point + m_Center * BernsteinPolynom21( t );
point = point + m_EndPoint * BernsteinPolynom22( t );
}
void CInterpolation::SetSmoothing( bool start, bool end )
{
m_SmoothStart = start;
m_SmoothEnd = end;
}
void CInterpolation::InterpolateAngle( float t, vec3_t &angle )
{
int i;
float ang1, ang2;
float d;
for( i = 0; i < 3; i++ )
{
ang1 = m_StartAngle[i];
ang2 = m_EndAngle[i];
d = ang2 - ang1;
if ( d > 180 )
{
d -= 360;
}
else if ( d < -180 )
{
d += 360;
}
angle[i] = ang1 + d * t;
}
NormalizeAngles( angle );
}

52
cl_dll/interpolation.h Normal file
View File

@ -0,0 +1,52 @@
/************ (C) Copyright 2003 Valve, L.L.C. All rights reserved. ***********
**
** The copyright to the contents herein is the property of Valve, L.L.C.
** The contents may be used and/or copied only with the written permission of
** Valve, L.L.C., or in accordance with the terms and conditions stipulated in
** the agreement/contract under which the contents have been supplied.
**
*******************************************************************************
**
** Contents:
**
** interpolation.h: Bezier inpolation classes
**
******************************************************************************/
#pragma once
#if !defined(INTERPOLATION_H)
#define INTERPOLATION_H
// interpolation class
class CInterpolation
{
public:
CInterpolation();
virtual ~CInterpolation();
void SetWaypoints( vec3_t *prev, vec3_t start, vec3_t end, vec3_t *next );
void SetViewAngles( vec3_t start, vec3_t end );
void SetFOVs( float start, float end );
void SetSmoothing( bool start, bool end );
// get interpolated point 0 =< t =< 1, 0 = start, 1 = end
void Interpolate( float t, vec3_t &point, vec3_t &angle, float * fov );
protected:
void BezierInterpolatePoint( float t, vec3_t &point );
void InterpolateAngle( float t, vec3_t &angle );
vec3_t m_StartPoint;
vec3_t m_EndPoint;
vec3_t m_StartAngle;
vec3_t m_EndAngle;
vec3_t m_Center;
float m_StartFov;
float m_EndFov;
bool m_SmoothStart;
bool m_SmoothEnd;
};
#endif // INTERPOLATION_H

View File

@ -104,10 +104,11 @@ int CHudSayText::Draw( float flTime )
int y = Y_START; int y = Y_START;
#if USE_VGUI #if USE_VGUI
if( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) || !m_HUD_saytext->value ) if( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) )
return 1; return 1;
#endif #endif
if ( !m_HUD_saytext->value )
return 1;
// make sure the scrolltime is within reasonable bounds, to guard against the clock being reset // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
flScrollTime = Q_min( flScrollTime, flTime + m_HUD_saytext_time->value ); flScrollTime = Q_min( flScrollTime, flTime + m_HUD_saytext_time->value );
@ -179,8 +180,6 @@ void CHudSayText::SayTextPrint( const char *pszBuf, int iBufSize, int clientInde
ConsolePrint( pszBuf ); ConsolePrint( pszBuf );
return; return;
} }
#else
ConsolePrint( pszBuf );
#endif #endif
//++ BulliT //++ BulliT

View File

@ -33,11 +33,11 @@
#if !defined(M_PI_F) #if !defined(M_PI_F)
#define M_PI_F (float)M_PI #define M_PI_F (float)M_PI
#endif #endif
extern vec3_t vec3_origin; // extern vec3_t vec3_origin;
// if C++ mangling differs from C symbol name // if C++ mangling differs from C symbol name
#if _MSC_VER || __WATCOMC__ #if _MSC_VER || __WATCOMC__
vec3_t vec3_origin; float vec3_origin[3];
#endif #endif
float Length( const float *v ) float Length( const float *v )

View File

@ -673,7 +673,7 @@ int TeamFortressViewport::CreateCommandMenu( const char *menuFile, int direction
return newIndex; return newIndex;
} }
#ifdef _WIN32 #if XASH_WIN32
try try
{ {
#endif #endif
@ -841,7 +841,7 @@ int TeamFortressViewport::CreateCommandMenu( const char *menuFile, int direction
{ {
gEngfuncs.Con_Printf( "Too many menus in %s past '%s'\n", menuFile, szLastButtonText ); gEngfuncs.Con_Printf( "Too many menus in %s past '%s'\n", menuFile, szLastButtonText );
} }
else else if( pButton )
{ {
// Create the menu // Create the menu
m_pCommandMenus[m_iNumMenus] = CreateSubMenu( pButton, m_pCurrentCommandMenu, iButtonY ); m_pCommandMenus[m_iNumMenus] = CreateSubMenu( pButton, m_pCurrentCommandMenu, iButtonY );
@ -873,7 +873,7 @@ int TeamFortressViewport::CreateCommandMenu( const char *menuFile, int direction
pfile = gEngfuncs.COM_ParseFile( pfile, token ); pfile = gEngfuncs.COM_ParseFile( pfile, token );
} }
#ifdef _WIN32 #if XASH_WIN32
} }
catch( CException *e ) catch( CException *e )
{ {

View File

@ -295,8 +295,11 @@ void V_CalcGunAngle( struct ref_params_s *pparams )
viewent->angles[PITCH] -= v_idlescale * sin( pparams->time * v_ipitch_cycle.value ) * ( v_ipitch_level.value * 0.5f ); viewent->angles[PITCH] -= v_idlescale * sin( pparams->time * v_ipitch_cycle.value ) * ( v_ipitch_level.value * 0.5f );
viewent->angles[YAW] -= v_idlescale * sin( pparams->time * v_iyaw_cycle.value ) * v_iyaw_level.value; viewent->angles[YAW] -= v_idlescale * sin( pparams->time * v_iyaw_cycle.value ) * v_iyaw_level.value;
VectorCopy( viewent->angles, viewent->curstate.angles ); if( !( cl_viewbob && cl_viewbob->value ))
VectorCopy( viewent->angles, viewent->latched.prevangles ); {
VectorCopy( viewent->angles, viewent->curstate.angles );
VectorCopy( viewent->angles, viewent->latched.prevangles );
}
} }
/* /*
@ -575,6 +578,7 @@ void V_CalcNormalRefdef( struct ref_params_s *pparams )
{ {
VectorCopy( pparams->cl_viewangles, view->angles ); VectorCopy( pparams->cl_viewangles, view->angles );
} }
// set up gun position // set up gun position
V_CalcGunAngle( pparams ); V_CalcGunAngle( pparams );
@ -597,9 +601,6 @@ void V_CalcNormalRefdef( struct ref_params_s *pparams )
view->angles[ROLL] -= bob * 1.0f; view->angles[ROLL] -= bob * 1.0f;
view->angles[PITCH] -= bob * 0.3f; view->angles[PITCH] -= bob * 0.3f;
if( cl_viewbob && cl_viewbob->value )
VectorCopy( view->angles, view->curstate.angles );
// pushing the view origin down off of the same X/Z plane as the ent's origin will give the // pushing the view origin down off of the same X/Z plane as the ent's origin will give the
// gun a very nice 'shifting' effect when the player looks up/down. If there is a problem // gun a very nice 'shifting' effect when the player looks up/down. If there is a problem
// with view model distortion, this may be a cause. (SJB). // with view model distortion, this may be a cause. (SJB).
@ -768,6 +769,14 @@ void V_CalcNormalRefdef( struct ref_params_s *pparams )
} }
} }
if( cl_viewbob && cl_viewbob->value )
{
VectorCopy( view->origin, view->curstate.origin );
VectorCopy( view->origin, view->latched.prevorigin );
VectorCopy( view->angles, view->curstate.angles );
VectorCopy( view->angles, view->latched.prevangles );
}
lasttime = pparams->time; lasttime = pparams->time;
v_origin = pparams->vieworg; v_origin = pparams->vieworg;
@ -1462,6 +1471,8 @@ void V_CalcSpectatorRefdef( struct ref_params_s * pparams )
case OBS_ROAMING: case OBS_ROAMING:
VectorCopy( v_cl_angles, v_angles ); VectorCopy( v_cl_angles, v_angles );
VectorCopy( v_sim_org, v_origin ); VectorCopy( v_sim_org, v_origin );
// override values if director is active
gHUD.m_Spectator.GetDirectorCamera(v_origin, v_angles);
break; break;
case OBS_IN_EYE: case OBS_IN_EYE:
V_CalcNormalRefdef( pparams ); V_CalcNormalRefdef( pparams );

View File

@ -6,27 +6,70 @@ from waflib import Utils
import os import os
def options(opt): def options(opt):
# stub grp = opt.add_option_group('Client options')
return
grp.add_option('--enable-vgui', action = 'store_true', dest = 'USE_VGUI', default = False,
help = 'Enable VGUI1')
grp.add_option('--enable-vgui2', action = 'store_true', dest = 'USE_VGUI2', default = False,
help = 'Enable VGUI2. UNDONE')
grp.add_option('--enable-novgui-motd', action = 'store_true', dest = 'USE_NOVGUI_MOTD', default = False,
help = 'Prefer non-VGUI MOTD when USE_VGUI is enabled')
grp.add_option('--enable-novgui-scoreboard', action = 'store_true', dest = 'USE_NOVGUI_SCOREBOARD', default = False,
help = 'Prefer non-VGUI Scoreboard when USE_VGUI is enabled')
grp.add_option('--disable-goldsrc-support', action = 'store_false', dest = 'GOLDSOURCE_SUPPORT',
default=True, help = 'disable GoldSource compatibility')
opt.load('vgui')
def configure(conf): def configure(conf):
if conf.env.DEST_OS == 'win32': conf.env.USE_VGUI = conf.options.USE_VGUI
conf.check_cxx(lib='user32') conf.env.USE_NOVGUI_MOTD = conf.options.USE_NOVGUI_MOTD
conf.env.USE_NOVGUI_SCOREBOARD = conf.options.USE_NOVGUI_SCOREBOARD
if conf.env.GOLDSRC: conf.env.USE_VOICEMGR = conf.options.USE_VOICEMGR
if conf.env.DEST_OS == 'win32': conf.env.GOLDSOURCE_SUPPORT = conf.options.GOLDSOURCE_SUPPORT
conf.check_cxx(lib='winmm') if conf.env.USE_VGUI:
else: conf.load('vgui')
conf.check_cc(lib='dl') if not conf.check_vgui():
conf.fatal('VGUI was enabled but VGUI cannot be used')
def build(bld): def build(bld):
source = bld.path.parent.ant_glob([ libs = []
'pm_shared/*.c' defines = ['CLIENT_DLL']
]) includes = ['.',
source += bld.path.ant_glob([ '../dlls',
'hl/*.cpp' '../common',
]) '../engine',
'../pm_shared',
'../game_shared',
'../public']
excluded_files = ['GameStudioModelRenderer_Sample.cpp',
'game_shared/voice_vgui_tweakdlg.cpp',
'game_shared/voice_gamemgr.cpp',
'game_shared/voice_status.cpp']
if bld.env.USE_VGUI:
defines += ['USE_VGUI']
libs += ['VGUI']
if bld.env.USE_NOVGUI_MOTD:
defines += ['USE_NOVGUI_MOTD']
else:
excluded_files += ['MOTD.cpp']
if bld.env.USE_NOVGUI_SCOREBOARD:
defines += ['USE_NOVGUI_SCOREBOARD']
else:
excluded_files += ['scoreboard.cpp']
else:
includes += ['../utils/fake_vgui/include']
excluded_files += ['voice_status.cpp',
'vgui_*.cpp',
'game_shared/vgui_*.cpp',
'game_shared/voice_banmgr.cpp']
source = bld.path.ant_glob('**/*.cpp', excl=excluded_files)
source += bld.path.parent.ant_glob('game_shared/*.cpp', excl=excluded_files)
source += bld.path.parent.ant_glob([ source += bld.path.parent.ant_glob([
'pm_shared/*.c',
'dlls/crossbow.cpp', 'dlls/crossbow.cpp',
'dlls/crowbar.cpp', 'dlls/crowbar.cpp',
'dlls/egon.cpp', 'dlls/egon.cpp',
@ -42,78 +85,21 @@ def build(bld):
'dlls/squeakgrenade.cpp', 'dlls/squeakgrenade.cpp',
'dlls/tripmine.cpp' 'dlls/tripmine.cpp'
]) ])
source += [
'GameStudioModelRenderer.cpp',
'MOTD.cpp',
'StudioModelRenderer.cpp',
'ammo.cpp',
'ammo_secondary.cpp',
'ammohistory.cpp',
'battery.cpp',
'cdll_int.cpp',
'com_weapons.cpp',
'death.cpp',
'demo.cpp',
'entity.cpp',
'ev_hldm.cpp',
'ev_common.cpp',
'events.cpp',
'flashlight.cpp',
'geiger.cpp',
'health.cpp',
'hud.cpp',
'hud_msg.cpp',
'hud_redraw.cpp',
'hud_spectator.cpp',
'hud_update.cpp',
'in_camera.cpp',
'input.cpp',
'input_goldsource.cpp',
'input_mouse.cpp',
'input_xash3d.cpp',
'menu.cpp',
'message.cpp',
'parsemsg.cpp',
'saytext.cpp',
'scoreboard.cpp',
'status_icons.cpp',
'statusbar.cpp',
'studio_util.cpp',
'text_message.cpp',
'train.cpp',
'tri.cpp',
'util.cpp',
'view.cpp'
]
includes = [
'.',
'hl/',
'../dlls',
'../common',
'../engine',
'../pm_shared',
'../game_shared',
'../public',
'../utils/fake_vgui/include'
]
defines = ['CLIENT_DLL'] if bld.env.DEST_OS == 'win32':
if bld.env.GOLDSRC: libs += ['USER32']
if bld.env.GOLDSOURCE_SUPPORT:
defines += ['GOLDSOURCE_SUPPORT'] defines += ['GOLDSOURCE_SUPPORT']
libs = []
if bld.env.DEST_OS == 'win32':
libs += ["USER32"]
if bld.env.GOLDSRC:
if bld.env.DEST_OS == 'win32': if bld.env.DEST_OS == 'win32':
libs += ["WINMM"] libs += ["WINMM"]
else: else:
libs += ['DL'] libs += ['DL']
if bld.env.DEST_OS not in ['android', 'dos']: if bld.env.DEST_OS not in ['android', 'dos']:
install_path = os.path.join(bld.env.GAMEDIR, bld.env.CLIENT_DIR) install_path = os.path.join(bld.env.GAMEDIR, bld.env.CLIENT_INSTALL_DIR)
else: else:
install_path = bld.env.PREFIX install_path = bld.env.PREFIX
@ -127,6 +113,6 @@ def build(bld):
use = libs, use = libs,
install_path = install_path, install_path = install_path,
subsystem = bld.env.MSVC_SUBSYSTEM, subsystem = bld.env.MSVC_SUBSYSTEM,
idx = bld.get_taskgen_count() idx = bld.get_taskgen_count()
) )

View File

@ -1,49 +1,83 @@
include(CheckSymbolExists) include(CheckSymbolExists)
# generated(see comments in public/build.h) macro(check_build_target symbol)
# cat build.h | grep '^#undef XASH' | awk '{ print "check_symbol_exists(" $2 " \"build.h\" " $2 ")" }' check_symbol_exists(${symbol} "build.h" ${symbol})
endmacro()
macro(check_group_build_target symbol group)
if(NOT ${group})
check_build_target(${symbol})
if(${symbol})
set(${group} TRUE)
endif()
else()
set(${symbol} FALSE)
endif()
endmacro()
# So there is a problem:
# 1. Number of these symbols only grows, as we support more and more ports
# 2. CMake was written by morons and can't check these symbols in parallel
# 3. MSVC is very slow at everything (startup, parsing, generating error)
# Solution: group these symbols and set variable if one of them was found
# this way we can reorder to reorder them by most common configurations
# but we can't generate this list anymore! ... OR IS IT ???
# Well, after reordering positions in engine's buildenums.h, we can partially autogenerate this list!
# echo "check_build_target(XASH_64BIT)"
# grep "#define PLATFORM" buildenums.h | cut -d' ' -f 2 | cut -d_ -f 2- | awk '{ print "check_group_build_target(XASH_" $1 " XASH_PLATFORM)" }'
# grep "#define ARCHITECTURE" buildenums.h | cut -d' ' -f 2 | cut -d_ -f 2- | awk '{ print "check_group_build_target(XASH_" $1 " XASH_ARCHITECTURE)"
# grep "#define ENDIAN" buildenums.h | cut -d' ' -f 2 | cut -d_ -f 2- | awk '{ print "check_group_build_target(XASH_" $1 "_ENDIAN XASH_ENDIANNESS)"}'
# echo "if(XASH_ARM)"
# grep '^#undef XASH' build.h | grep "XASH_ARM[v_]" | awk '{ print "check_build_target(" $2 ")"}'
# echo "endif()"
# echo "if(XASH_RISCV)"
# grep '^#undef XASH' build.h | grep "XASH_RISCV_" | awk '{ print "check_build_target(" $2 ")"}'
# echo "endif()"
# NOTE: Android must have priority over Linux to work correctly!
set(CMAKE_REQUIRED_INCLUDES "${PROJECT_SOURCE_DIR}/public/") set(CMAKE_REQUIRED_INCLUDES "${PROJECT_SOURCE_DIR}/public/")
check_symbol_exists(XASH_64BIT "build.h" XASH_64BIT) check_build_target(XASH_64BIT)
check_symbol_exists(XASH_AMD64 "build.h" XASH_AMD64) check_group_build_target(XASH_WIN32 XASH_PLATFORM)
check_symbol_exists(XASH_ANDROID "build.h" XASH_ANDROID) check_group_build_target(XASH_ANDROID XASH_PLATFORM)
check_symbol_exists(XASH_APPLE "build.h" XASH_APPLE) check_group_build_target(XASH_LINUX XASH_PLATFORM)
check_symbol_exists(XASH_ARM "build.h" XASH_ARM) check_group_build_target(XASH_FREEBSD XASH_PLATFORM)
check_symbol_exists(XASH_ARM_HARDFP "build.h" XASH_ARM_HARDFP) check_group_build_target(XASH_APPLE XASH_PLATFORM)
check_symbol_exists(XASH_ARM_SOFTFP "build.h" XASH_ARM_SOFTFP) check_group_build_target(XASH_NETBSD XASH_PLATFORM)
check_symbol_exists(XASH_ARMv4 "build.h" XASH_ARMv4) check_group_build_target(XASH_OPENBSD XASH_PLATFORM)
check_symbol_exists(XASH_ARMv5 "build.h" XASH_ARMv5) check_group_build_target(XASH_EMSCRIPTEN XASH_PLATFORM)
check_symbol_exists(XASH_ARMv6 "build.h" XASH_ARMv6) check_group_build_target(XASH_DOS4GW XASH_PLATFORM)
check_symbol_exists(XASH_ARMv7 "build.h" XASH_ARMv7) check_group_build_target(XASH_HAIKU XASH_PLATFORM)
check_symbol_exists(XASH_ARMv8 "build.h" XASH_ARMv8) check_group_build_target(XASH_SERENITY XASH_PLATFORM)
check_symbol_exists(XASH_BIG_ENDIAN "build.h" XASH_BIG_ENDIAN) check_group_build_target(XASH_IRIX XASH_PLATFORM)
check_symbol_exists(XASH_BSD "build.h" XASH_BSD) check_group_build_target(XASH_NSWITCH XASH_PLATFORM)
check_symbol_exists(XASH_DOS4GW "build.h" XASH_DOS4GW) check_group_build_target(XASH_PSVITA XASH_PLATFORM)
check_symbol_exists(XASH_E2K "build.h" XASH_E2K) check_group_build_target(XASH_X86 XASH_ARCHITECTURE)
check_symbol_exists(XASH_EMSCRIPTEN "build.h" XASH_EMSCRIPTEN) check_group_build_target(XASH_AMD64 XASH_ARCHITECTURE)
check_symbol_exists(XASH_FREEBSD "build.h" XASH_FREEBSD) check_group_build_target(XASH_ARM XASH_ARCHITECTURE)
check_symbol_exists(XASH_HAIKU "build.h" XASH_HAIKU) check_group_build_target(XASH_MIPS XASH_ARCHITECTURE)
check_symbol_exists(XASH_IOS "build.h" XASH_IOS) check_group_build_target(XASH_PPC XASH_ARCHITECTURE)
check_symbol_exists(XASH_JS "build.h" XASH_JS) check_group_build_target(XASH_JS XASH_ARCHITECTURE)
check_symbol_exists(XASH_LINUX "build.h" XASH_LINUX) check_group_build_target(XASH_E2K XASH_ARCHITECTURE)
check_symbol_exists(XASH_LITTLE_ENDIAN "build.h" XASH_LITTLE_ENDIAN) check_group_build_target(XASH_RISCV XASH_ARCHITECTURE)
check_symbol_exists(XASH_MINGW "build.h" XASH_MINGW) check_group_build_target(XASH_LITTLE_ENDIAN XASH_ENDIANNESS)
check_symbol_exists(XASH_MIPS "build.h" XASH_MIPS) check_group_build_target(XASH_BIG_ENDIAN XASH_ENDIANNESS)
check_symbol_exists(XASH_PPC "build.h" XASH_PPC) if(XASH_ARM)
check_symbol_exists(XASH_MOBILE_PLATFORM "build.h" XASH_MOBILE_PLATFORM) check_build_target(XASH_ARM_HARDFP)
check_symbol_exists(XASH_MSVC "build.h" XASH_MSVC) check_build_target(XASH_ARM_SOFTFP)
check_symbol_exists(XASH_NETBSD "build.h" XASH_NETBSD) check_build_target(XASH_ARMv4)
check_symbol_exists(XASH_OPENBSD "build.h" XASH_OPENBSD) check_build_target(XASH_ARMv5)
check_symbol_exists(XASH_POSIX "build.h" XASH_POSIX) check_build_target(XASH_ARMv6)
check_symbol_exists(XASH_RISCV "build.h" XASH_RISCV) check_build_target(XASH_ARMv7)
check_symbol_exists(XASH_RISCV_DOUBLEFP "build.h" XASH_RISCV_DOUBLEFP) check_build_target(XASH_ARMv8)
check_symbol_exists(XASH_RISCV_SINGLEFP "build.h" XASH_RISCV_SINGLEFP) endif()
check_symbol_exists(XASH_RISCV_SOFTFP "build.h" XASH_RISCV_SOFTFP) if(XASH_RISCV)
check_symbol_exists(XASH_SERENITY "build.h" XASH_SERENITY) check_build_target(XASH_RISCV_DOUBLEFP)
check_symbol_exists(XASH_WIN32 "build.h" XASH_WIN32) check_build_target(XASH_RISCV_SINGLEFP)
check_symbol_exists(XASH_WIN64 "build.h" XASH_WIN64) check_build_target(XASH_RISCV_SOFTFP)
check_symbol_exists(XASH_X86 "build.h" XASH_X86) endif()
check_symbol_exists(XASH_NSWITCH "build.h" XASH_NSWITCH)
check_symbol_exists(XASH_PSVITA "build.h" XASH_PSVITA)
unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_INCLUDES)
# engine/common/build.c # engine/common/build.c
@ -69,6 +103,8 @@ elseif(XASH_NSWITCH)
set(BUILDOS "nswitch") set(BUILDOS "nswitch")
elseif(XASH_PSVITA) elseif(XASH_PSVITA)
set(BUILDOS "psvita") set(BUILDOS "psvita")
elseif(XASH_IRIX)
set(BUILDOS "irix")
else() else()
message(SEND_ERROR "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug") message(SEND_ERROR "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug")
endif() endif()
@ -113,15 +149,6 @@ elseif(XASH_MIPS)
if(XASH_LITTLE_ENDIAN) if(XASH_LITTLE_ENDIAN)
set(BUILDARCH "${BUILDARCH}el") set(BUILDARCH "${BUILDARCH}el")
endif() endif()
elseif(XASH_PPC)
set(BUILDARCH "powerpc")
if(XASH_64BIT)
set(BUILDARCH "${BUILDARCH}64")
endif()
if(XASH_LITTLE_ENDIAN)
set(BUILDARCH "${BUILDARCH}le")
endif()
elseif(XASH_RISCV) elseif(XASH_RISCV)
set(BUILDARCH "riscv") set(BUILDARCH "riscv")
if(XASH_64BIT) if(XASH_64BIT)
@ -139,6 +166,15 @@ elseif(XASH_JS)
set(BUILDARCH "javascript") set(BUILDARCH "javascript")
elseif(XASH_E2K) elseif(XASH_E2K)
set(BUILDARCH "e2k") set(BUILDARCH "e2k")
elseif(XASH_PPC)
set(BUILDARCH "ppc")
if(XASH_64BIT)
set(BUILDARCH "${BUILDARCH}64")
endif()
if(XASH_LITTLE_ENDIAN)
set(BUILDARCH "${BUILDARCH}el")
endif()
else() else()
message(SEND_ERROR "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug") message(SEND_ERROR "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug")
endif() endif()

View File

@ -1,4 +1,4 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ //========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============
// //
// Purpose: // Purpose:
// //

View File

@ -127,7 +127,8 @@
// entity flags // entity flags
#define EFLAG_SLERP 1 // do studio interpolation of this entity #define EFLAG_SLERP 1 // do studio interpolation of this entity
#define EFLAG_MONSTER 2
// //
// temp entity events // temp entity events
// //

View File

@ -37,11 +37,14 @@
#define DRC_CMD_SOUND 7 // plays a particular sound #define DRC_CMD_SOUND 7 // plays a particular sound
#define DRC_CMD_STATUS 8 // status info about broadcast #define DRC_CMD_STATUS 8 // status info about broadcast
#define DRC_CMD_BANNER 9 // banner file name for HLTV gui #define DRC_CMD_BANNER 9 // banner file name for HLTV gui
#define DRC_CMD_FADE 10 // send screen fade command #define DRC_CMD_STUFFTEXT 10 // like the normal svc_stufftext but as director command
#define DRC_CMD_SHAKE 11 // send screen shake command #define DRC_CMD_CHASE 11 // chase a certain player
#define DRC_CMD_STUFFTEXT 12 // like the normal svc_stufftext but as director command #define DRC_CMD_INEYE 12 // view player through own eyes
#define DRC_CMD_MAP 13 // show overview map
#define DRC_CMD_CAMPATH 14 // define camera waypoint
#define DRC_CMD_WAYPOINTS 15 // start moving camera, inetranl message
#define DRC_CMD_LAST 12 #define DRC_CMD_LAST 15
// HLTV_EVENT event flags // HLTV_EVENT event flags
#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important) #define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important)
@ -53,7 +56,9 @@
#define DRC_FLAG_FINAL (1<<9) // is a final scene #define DRC_FLAG_FINAL (1<<9) // is a final scene
#define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data #define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data
#define MAX_DIRECTOR_CMD_PARAMETERS 4 // DRC_CMD_WAYPOINT flags
#define MAX_DIRECTOR_CMD_STRING 128 #define DRC_FLAG_STARTPATH 1 // end with speed 0.0
#define DRC_FLAG_SLOWSTART 2 // start with speed 0.0
#define DRC_FLAG_SLOWEND 4 // end with speed 0.0
#endif//HLTV_H #endif//HLTV_H

View File

@ -219,6 +219,7 @@ files{"dlls/agrunt.cpp",
"dlls/triggers.cpp", "dlls/triggers.cpp",
"dlls/turret.cpp", "dlls/turret.cpp",
"dlls/util.cpp", "dlls/util.cpp",
"dlls/vehicle.cpp",
"dlls/weapons.cpp", "dlls/weapons.cpp",
"dlls/world.cpp", "dlls/world.cpp",
"dlls/xen.cpp", "dlls/xen.cpp",
@ -269,6 +270,7 @@ files{"cl_dll/hl/hl_baseentity.cpp",
"cl_dll/input_goldsource.cpp", "cl_dll/input_goldsource.cpp",
"cl_dll/input_mouse.cpp", "cl_dll/input_mouse.cpp",
"cl_dll/input_xash3d.cpp", "cl_dll/input_xash3d.cpp",
"cl_dll/interpolation.cpp",
"cl_dll/menu.cpp", "cl_dll/menu.cpp",
"cl_dll/message.cpp", "cl_dll/message.cpp",
"cl_dll/overview.cpp", "cl_dll/overview.cpp",

View File

@ -124,6 +124,7 @@ LOCAL_SRC_FILES := agrunt.cpp airtank.cpp \
tripmine.cpp \ tripmine.cpp \
turret.cpp \ turret.cpp \
util.cpp \ util.cpp \
vehicle.cpp \
weapons.cpp \ weapons.cpp \
world.cpp \ world.cpp \
xen.cpp \ xen.cpp \

View File

@ -20,17 +20,26 @@
# SOFTWARE. # SOFTWARE.
# #
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 3.9)
project (SVDLL) project (SVDLL)
set (SVDLL_LIBRARY server) set (SVDLL_LIBRARY server)
if(NOT MSVC) if(NOT MSVC)
add_compile_options(-fno-exceptions) # GCC/Clang flag add_compile_options(-fno-exceptions) # GCC/Clang flag
add_compile_options(-fno-rtti) # GCC/Clang flag
add_compile_options(-Wno-invalid-offsetof) # GCC/Clang flag add_compile_options(-Wno-invalid-offsetof) # GCC/Clang flag
add_compile_options(-fvisibility=hidden) # GCC/Clang flag add_compile_options(-fvisibility=hidden) # GCC/Clang flag
add_definitions(-D_LINUX) # It seems enough for all non-Win32 systems add_definitions(-D_LINUX) # It seems enough for all non-Win32 systems
add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf ) add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf )
if(CMAKE_BUILD_TYPE MATCHES "Release"
OR (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo"
AND CMAKE_SYSTEM_NAME STREQUAL "Android"))
add_compile_options(-fno-unwind-tables -fno-asynchronous-unwind-tables) # GCC/Clang flag
add_compile_options(-fomit-frame-pointer) # GCC/Clang flag
add_compile_options(-ftree-vectorize) # GCC/Clang flag
add_compile_options(-funsafe-math-optimizations) # GCC/Clang flag
endif()
else() else()
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
endif() endif()
@ -131,6 +140,7 @@ set (SVDLL_SOURCES
tripmine.cpp tripmine.cpp
turret.cpp turret.cpp
util.cpp util.cpp
vehicle.cpp
weapons.cpp weapons.cpp
world.cpp world.cpp
xen.cpp xen.cpp
@ -201,8 +211,16 @@ if(MSVC)
set_property(TARGET ${SVDLL_LIBRARY} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set_property(TARGET ${SVDLL_LIBRARY} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif() endif()
if(HAVE_LTO)
set_property(TARGET ${SVDLL_LIBRARY} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
install( TARGETS ${SVDLL_LIBRARY} install( TARGETS ${SVDLL_LIBRARY}
DESTINATION "${GAMEDIR}/${SERVER_INSTALL_DIR}/" DESTINATION "${GAMEDIR}/${SERVER_INSTALL_DIR}/"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE) WORLD_READ WORLD_EXECUTE)
add_custom_command(TARGET ${SVDLL_LIBRARY}
POST_BUILD DEPENDS ${SVDLL_LIBRARY}
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}> -s $<TARGET_FILE:${SVDLL_LIBRARY}>)

View File

@ -576,7 +576,7 @@ void AgClient::Say(CBasePlayer* pPlayer, say_type Type )
else if ('l' == *pSayText || 'L' == *pSayText) else if ('l' == *pSayText || 'L' == *pSayText)
{ {
#if AG_NO_CLIENT_DLL #if AG_NO_CLIENT_DLL
pText = pText + sprintf(pText,g_pGameRules->m_LocationCache.Location(pPlayer->pev->origin).c_str()); pText = pText + sprintf(pText, "%s", g_pGameRules->m_LocationCache.Location(pPlayer->pev->origin).c_str());
pSayText++; pSayText++;
continue; continue;
#else #else
@ -588,7 +588,7 @@ void AgClient::Say(CBasePlayer* pPlayer, say_type Type )
else if ('d' == *pSayText || 'D' == *pSayText) else if ('d' == *pSayText || 'D' == *pSayText)
{ {
#if AG_NO_CLIENT_DLL #if AG_NO_CLIENT_DLL
pText = pText + sprintf(pText,g_pGameRules->m_LocationCache.Location(pPlayer->GetKilledPosition()).c_str()); pText = pText + sprintf(pText, "%s", g_pGameRules->m_LocationCache.Location(pPlayer->GetKilledPosition()).c_str());
pSayText++; pSayText++;
continue; continue;
#else #else

View File

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

View File

@ -128,7 +128,7 @@ DLL_GLOBAL cvar_t ag_start_health = {"sv_ag_start_health","100"};
DLL_GLOBAL cvar_t ag_dmg_crowbar = {"sv_ag_dmg_crowbar","25"}; DLL_GLOBAL cvar_t ag_dmg_crowbar = {"sv_ag_dmg_crowbar","25"};
DLL_GLOBAL cvar_t ag_dmg_glock = {"sv_ag_dmg_glock","12"}; DLL_GLOBAL cvar_t ag_dmg_glock = {"sv_ag_dmg_glock","12"};
DLL_GLOBAL cvar_t ag_dmg_357 = {"sv_ag_dmg_357","40"}; DLL_GLOBAL cvar_t ag_dmg_357 = {"sv_ag_dmg_357","50"};
DLL_GLOBAL cvar_t ag_dmg_mp5 = {"sv_ag_dmg_mp5","12"}; DLL_GLOBAL cvar_t ag_dmg_mp5 = {"sv_ag_dmg_mp5","12"};
DLL_GLOBAL cvar_t ag_dmg_shotgun = {"sv_ag_dmg_shotgun", "20"}; DLL_GLOBAL cvar_t ag_dmg_shotgun = {"sv_ag_dmg_shotgun", "20"};
DLL_GLOBAL cvar_t ag_dmg_crossbow = {"sv_ag_dmg_crossbow", "20"}; DLL_GLOBAL cvar_t ag_dmg_crossbow = {"sv_ag_dmg_crossbow", "20"};

View File

@ -202,7 +202,7 @@ void CBasePlayer::Spectate_Stop(bool bIntermediateSpawn)
pev->iuser2 = 0; pev->iuser2 = 0;
pev->effects &= ~EF_NODRAW; pev->effects &= ~EF_NODRAW;
pev->movetype = MOVETYPE_WALK; pev->movetype = MOVETYPE_WALK;
m_iRespawnFrames = 0; m_flRespawnTimer = 0;
m_bDoneFirstSpawn = !bIntermediateSpawn; m_bDoneFirstSpawn = !bIntermediateSpawn;
m_iHideHUD &= ~HIDEHUD_WEAPONS; m_iHideHUD &= ~HIDEHUD_WEAPONS;
m_iHideHUD &= ~HIDEHUD_FLASHLIGHT; m_iHideHUD &= ~HIDEHUD_FLASHLIGHT;

View File

@ -139,4 +139,28 @@ protected:
void SendMOTDToClient( edict_t *client ); void SendMOTDToClient( edict_t *client );
}; };
bool IsPlayerBusting( CBaseEntity *pPlayer );
BOOL BustingCanHaveItem( CBasePlayer *pPlayer, CBaseEntity *pItem );
class CMultiplayBusters : public CHalfLifeMultiplay
{
public:
CMultiplayBusters();
void Think();
void PlayerSpawn( CBasePlayer *pPlayer );
void ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer );
int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled );
void PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor );
void DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor );
BOOL CanHavePlayerItem( CBasePlayer *pPlayer, CBasePlayerItem *pItem );
void PlayerGotWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );
int WeaponShouldRespawn( CBasePlayerItem *pWeapon );
BOOL CanHaveItem( CBasePlayer *pPlayer, CItem *pItem );
void CheckForEgons();
void SetPlayerModel( CBasePlayer *pPlayer, BOOL bKnownBuster );
BOOL IsBustingGame( void ){ return TRUE; };
protected:
float m_flEgonBustingCheckTime;
};
#endif //_MULTIPLAY_H_ #endif //_MULTIPLAY_H_

View File

@ -120,6 +120,7 @@ public:
virtual int BloodColor( void ) { return m_bloodColor; } virtual int BloodColor( void ) { return m_bloodColor; }
virtual CBaseMonster *MyMonsterPointer( void ) { return this; } virtual CBaseMonster *MyMonsterPointer( void ) { return this; }
virtual BOOL IsAllowedToSpeak( void ) { return IsAlive(); }
virtual void Look( int iDistance );// basic sight function for monsters virtual void Look( int iDistance );// basic sight function for monsters
virtual void RunAI( void );// core ai function! virtual void RunAI( void );// core ai function!
void Listen( void ); void Listen( void );
@ -186,11 +187,7 @@ public:
virtual void ScheduleChange( void ) {} virtual void ScheduleChange( void ) {}
// virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); } // virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); }
virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel ); virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel );
virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); } virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAllowedToSpeak(); }
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
virtual void SentenceStop( void );
Task_t *GetTask( void ); Task_t *GetTask( void );
virtual MONSTERSTATE GetIdealState( void ); virtual MONSTERSTATE GetIdealState( void );

View File

@ -931,7 +931,7 @@ void CBigMomma::StartTask( Task_t *pTask )
TaskComplete(); TaskComplete();
break; break;
case TASK_WAIT_NODE: case TASK_WAIT_NODE:
m_flWaitFinished = gpGlobals->time + GetNodeDelay(); m_flWait = gpGlobals->time + GetNodeDelay();
if( m_hTargetEnt->pev->spawnflags & SF_INFOBM_WAIT ) if( m_hTargetEnt->pev->spawnflags & SF_INFOBM_WAIT )
ALERT( at_aiconsole, "BM: Wait at node %s forever\n", STRING( pev->netname ) ); ALERT( at_aiconsole, "BM: Wait at node %s forever\n", STRING( pev->netname ) );
else else

View File

@ -22,6 +22,8 @@
#include "gamerules.h" #include "gamerules.h"
#include "game.h" #include "game.h"
bool g_fIsXash3D = false;
void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd ); void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd );
extern "C" void PM_Move ( struct playermove_s *ppmove, int server ); extern "C" void PM_Move ( struct playermove_s *ppmove, int server );
@ -98,7 +100,7 @@ static DLL_FUNCTIONS gFunctionTable =
static void SetObjectCollisionBox( entvars_t *pev ); static void SetObjectCollisionBox( entvars_t *pev );
#if !_WIN32 #if !XASH_WIN32
extern "C" { extern "C" {
#endif #endif
int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ) int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
@ -125,7 +127,12 @@ int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
return TRUE; return TRUE;
} }
#if !_WIN32 int Server_GetPhysicsInterface( int version, server_physics_api_t *api, physics_interface_t *interface )
{
g_fIsXash3D = true;
return FALSE; // do not tell engine to init physics interface, as we're not using it
}
#if !XASH_WIN32
} }
#endif #endif

View File

@ -58,6 +58,11 @@ CBaseEntity
extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
extern "C" EXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); extern "C" EXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
// TODO: replace this by actual definitions from physint.h
typedef void *server_physics_api_t;
typedef void *physics_interface_t;
extern "C" EXPORT int Server_GetPhysicsInterface( int version, server_physics_api_t *api, physics_interface_t *interface );
extern bool g_fIsXash3D;
extern int DispatchSpawn( edict_t *pent ); extern int DispatchSpawn( edict_t *pent );
extern void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd ); extern void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd );
@ -103,9 +108,11 @@ typedef void(CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCalle
#define CLASS_PLAYER_ALLY 11 #define CLASS_PLAYER_ALLY 11
#define CLASS_PLAYER_BIOWEAPON 12 // hornets and snarks.launched by players #define CLASS_PLAYER_BIOWEAPON 12 // hornets and snarks.launched by players
#define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace #define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace
#define CLASS_VEHICLE 14
#define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures. #define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
class CBaseEntity; class CBaseEntity;
class CBaseToggle;
class CBaseMonster; class CBaseMonster;
class CBasePlayerItem; class CBasePlayerItem;
class CSquadMonster; class CSquadMonster;
@ -172,6 +179,7 @@ public:
virtual int BloodColor( void ) { return DONT_BLEED; } virtual int BloodColor( void ) { return DONT_BLEED; }
virtual void TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ); virtual void TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
virtual BOOL IsTriggered( CBaseEntity *pActivator ) {return TRUE; } virtual BOOL IsTriggered( CBaseEntity *pActivator ) {return TRUE; }
virtual CBaseToggle *MyTogglePointer( void ) { return NULL; }
virtual CBaseMonster *MyMonsterPointer( void ) { return NULL; } virtual CBaseMonster *MyMonsterPointer( void ) { return NULL; }
virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL; } virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL; }
virtual int GetToggleState( void ) { return TS_AT_TOP; } virtual int GetToggleState( void ) { return TS_AT_TOP; }
@ -256,7 +264,6 @@ public:
int Intersects( CBaseEntity *pOther ); int Intersects( CBaseEntity *pOther );
void MakeDormant( void ); void MakeDormant( void );
int IsDormant( void ); int IsDormant( void );
BOOL IsLockedByMaster( void ) { return FALSE; }
static CBaseEntity *Instance( edict_t *pent ) static CBaseEntity *Instance( edict_t *pent )
{ {
@ -532,9 +539,15 @@ public:
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
CBaseToggle *MyTogglePointer( void ) { return this; }
virtual int GetToggleState( void ) { return m_toggle_state; } virtual int GetToggleState( void ) { return m_toggle_state; }
virtual float GetDelay( void ) { return m_flWait; } virtual float GetDelay( void ) { return m_flWait; }
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
virtual void SentenceStop( void );
virtual BOOL IsAllowedToSpeak( void ) { return FALSE; }
// common member functions // common member functions
void LinearMove( Vector vecDest, float flSpeed ); void LinearMove( Vector vecDest, float flSpeed );
void EXPORT LinearMoveDone( void ); void EXPORT LinearMoveDone( void );
@ -704,6 +717,8 @@ public:
// Buttons that don't take damage can be IMPULSE used // Buttons that don't take damage can be IMPULSE used
virtual int ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); } virtual int ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); }
BOOL IsAllowedToSpeak( void ) { return TRUE; }
BOOL m_fStayPushed; // button stays pushed in until touched again? BOOL m_fStayPushed; // button stays pushed in until touched again?
BOOL m_fRotating; // a rotating button? default is a sliding button. BOOL m_fRotating; // a rotating button? default is a sliding button.

View File

@ -130,6 +130,7 @@ void ClientDisconnect( edict_t *pEntity )
pEntity->v.takedamage = DAMAGE_NO;// don't attract autoaim pEntity->v.takedamage = DAMAGE_NO;// don't attract autoaim
pEntity->v.solid = SOLID_NOT;// nonsolid pEntity->v.solid = SOLID_NOT;// nonsolid
pEntity->v.effects = 0;// clear any effects pEntity->v.effects = 0;// clear any effects
pEntity->v.flags = 0;// clear any flags
UTIL_SetOrigin( &pEntity->v, pEntity->v.origin ); UTIL_SetOrigin( &pEntity->v, pEntity->v.origin );
g_pGameRules->ClientDisconnected( pEntity ); g_pGameRules->ClientDisconnected( pEntity );
@ -926,6 +927,8 @@ void ClientPrecache( void )
PRECACHE_SOUND( "plats/train_use1.wav" ); // use a train PRECACHE_SOUND( "plats/train_use1.wav" ); // use a train
PRECACHE_SOUND( "plats/vehicle_ignition.wav" );
PRECACHE_SOUND( "buttons/spark5.wav" ); // hit computer texture PRECACHE_SOUND( "buttons/spark5.wav" ); // hit computer texture
PRECACHE_SOUND( "buttons/spark6.wav" ); PRECACHE_SOUND( "buttons/spark6.wav" );
PRECACHE_SOUND( "debris/glass1.wav" ); PRECACHE_SOUND( "debris/glass1.wav" );
@ -1160,6 +1163,7 @@ we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to.
int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet ) int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet )
{ {
int i; int i;
CBaseEntity *Entity;
// don't send if flagged for NODRAW and it's not the host getting the message // don't send if flagged for NODRAW and it's not the host getting the message
if( ( ent->v.effects & EF_NODRAW ) && ( ent != host ) ) if( ( ent->v.effects & EF_NODRAW ) && ( ent != host ) )
@ -1349,6 +1353,17 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
state->health = (int)ent->v.health; state->health = (int)ent->v.health;
} }
if( ( Entity = CBaseEntity::Instance( ent ))
&& Entity->Classify() != CLASS_NONE
&& Entity->Classify() != CLASS_MACHINE )
{
SetBits( state->eflags, EFLAG_MONSTER );
}
else
{
ClearBits( state->eflags, EFLAG_SLERP | EFLAG_MONSTER );
}
return 1; return 1;
} }

View File

@ -62,12 +62,6 @@ void CGib::SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs )
{ {
int i; int i;
if( g_Language == LANGUAGE_GERMAN )
{
// no sticky gibs in germany right now!
return;
}
for( i = 0; i < cGibs; i++ ) for( i = 0; i < cGibs; i++ )
{ {
CGib *pGib = GetClassPtr( (CGib *)NULL ); CGib *pGib = GetClassPtr( (CGib *)NULL );
@ -130,16 +124,8 @@ void CGib::SpawnHeadGib( entvars_t *pevVictim )
{ {
CGib *pGib = GetClassPtr( (CGib *)NULL ); CGib *pGib = GetClassPtr( (CGib *)NULL );
if( g_Language == LANGUAGE_GERMAN ) pGib->Spawn( "models/hgibs.mdl" );// throw one head
{ pGib->pev->body = 0;
pGib->Spawn( "models/germangibs.mdl" );// throw one head
pGib->pev->body = 0;
}
else
{
pGib->Spawn( "models/hgibs.mdl" );// throw one head
pGib->pev->body = 0;
}
if( pevVictim ) if( pevVictim )
{ {
@ -191,25 +177,17 @@ void CGib::SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int human )
{ {
CGib *pGib = GetClassPtr( (CGib *)NULL ); CGib *pGib = GetClassPtr( (CGib *)NULL );
if( g_Language == LANGUAGE_GERMAN ) if( human )
{ {
pGib->Spawn( "models/germangibs.mdl" ); // human pieces
pGib->pev->body = RANDOM_LONG( 0, GERMAN_GIB_COUNT - 1 ); pGib->Spawn( "models/hgibs.mdl" );
pGib->pev->body = RANDOM_LONG( 1, HUMAN_GIB_COUNT - 1 );// start at one to avoid throwing random amounts of skulls (0th gib)
} }
else else
{ {
if( human ) // aliens
{ pGib->Spawn( "models/agibs.mdl" );
// human pieces pGib->pev->body = RANDOM_LONG( 0, ALIEN_GIB_COUNT - 1 );
pGib->Spawn( "models/hgibs.mdl" );
pGib->pev->body = RANDOM_LONG( 1, HUMAN_GIB_COUNT - 1 );// start at one to avoid throwing random amounts of skulls (0th gib)
}
else
{
// aliens
pGib->Spawn( "models/agibs.mdl" );
pGib->pev->body = RANDOM_LONG( 0, ALIEN_GIB_COUNT - 1 );
}
} }
if( pevVictim ) if( pevVictim )
@ -723,7 +701,7 @@ void CGib::BounceGibTouch( CBaseEntity *pOther )
} }
else else
{ {
if( g_Language != LANGUAGE_GERMAN && m_cBloodDecals > 0 && m_bloodColor != DONT_BLEED ) if( m_cBloodDecals > 0 && m_bloodColor != DONT_BLEED )
{ {
vecSpot = pev->origin + Vector( 0.0f, 0.0f, 8.0f );//move up a bit, and trace down. vecSpot = pev->origin + Vector( 0.0f, 0.0f, 8.0f );//move up a bit, and trace down.
UTIL_TraceLine( vecSpot, vecSpot + Vector( 0.0f, 0.0f, -24.0f ), ignore_monsters, ENT( pev ), &tr ); UTIL_TraceLine( vecSpot, vecSpot + Vector( 0.0f, 0.0f, -24.0f ), ignore_monsters, ENT( pev ), &tr );

View File

@ -103,6 +103,7 @@ set SOURCES=agrunt.cpp ^
tripmine.cpp ^ tripmine.cpp ^
turret.cpp ^ turret.cpp ^
util.cpp ^ util.cpp ^
vehicle.cpp ^
weapons.cpp ^ weapons.cpp ^
world.cpp ^ world.cpp ^
xen.cpp ^ xen.cpp ^

View File

@ -33,8 +33,6 @@
#define BOLT_AIR_VELOCITY 2000 #define BOLT_AIR_VELOCITY 2000
#define BOLT_WATER_VELOCITY 1000 #define BOLT_WATER_VELOCITY 1000
extern BOOL g_fIsXash3D;
// UNDONE: Save/restore this? Don't forget to set classname and LINK_ENTITY_TO_CLASS() // UNDONE: Save/restore this? Don't forget to set classname and LINK_ENTITY_TO_CLASS()
// //
// OVERLOADS SOME ENTVARS: // OVERLOADS SOME ENTVARS:
@ -330,7 +328,7 @@ void CCrossbow::Holster( int skiplocal /* = 0 */ )
{ {
m_fInReload = FALSE;// cancel any reload in progress. m_fInReload = FALSE;// cancel any reload in progress.
if( m_fInZoom ) if( m_pPlayer->pev->fov != 0 )
{ {
SecondaryAttack(); SecondaryAttack();
} }

View File

@ -1330,14 +1330,7 @@ LINK_ENTITY_TO_CLASS( gibshooter, CGibShooter )
void CGibShooter::Precache( void ) void CGibShooter::Precache( void )
{ {
if( g_Language == LANGUAGE_GERMAN ) m_iGibModelIndex = PRECACHE_MODEL( "models/hgibs.mdl" );
{
m_iGibModelIndex = PRECACHE_MODEL( "models/germanygibs.mdl" );
}
else
{
m_iGibModelIndex = PRECACHE_MODEL( "models/hgibs.mdl" );
}
} }
void CGibShooter::KeyValue( KeyValueData *pkvd ) void CGibShooter::KeyValue( KeyValueData *pkvd )

View File

@ -307,7 +307,8 @@ void CEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
// multiplayer uses 1 ammo every 1/10th second // multiplayer uses 1 ammo every 1/10th second
if( gpGlobals->time >= m_flAmmoUseTime ) if( gpGlobals->time >= m_flAmmoUseTime )
{ {
UseAmmo( 1 ); if( !g_pGameRules->IsBustingGame())
UseAmmo( 1 );
m_flAmmoUseTime = gpGlobals->time + 0.1f; m_flAmmoUseTime = gpGlobals->time + 0.1f;
} }
} }
@ -352,7 +353,8 @@ void CEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
//multiplayer uses 5 ammo/second //multiplayer uses 5 ammo/second
if( gpGlobals->time >= m_flAmmoUseTime ) if( gpGlobals->time >= m_flAmmoUseTime )
{ {
UseAmmo( 1 ); if( !g_pGameRules->IsBustingGame())
UseAmmo( 1 );
m_flAmmoUseTime = gpGlobals->time + 0.2f; m_flAmmoUseTime = gpGlobals->time + 0.2f;
} }
} }
@ -513,6 +515,15 @@ void CEgon::WeaponIdle( void )
m_deployed = TRUE; m_deployed = TRUE;
} }
BOOL CEgon::CanHolster( void )
{
#if CLIENT_DLL
return TRUE;
#else
return !g_pGameRules->IsBustingGame();
#endif
}
void CEgon::EndAttack( void ) void CEgon::EndAttack( void )
{ {
bool bMakeNoise = false; bool bMakeNoise = false;

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#if !defined(EXPORTDEF_H) #if !defined(EXPORTDEF_H)
#define EXPORTDEF_H #define EXPORTDEF_H
#if _WIN32 || __CYGWIN__ #if XASH_WIN32 || __CYGWIN__
#if __GNUC__ #if __GNUC__
#define EXPORT __attribute__ ((dllexport)) #define EXPORT __attribute__ ((dllexport))
#else #else

View File

@ -15,7 +15,7 @@
#pragma once #pragma once
#if !defined(EXTDLL_H) #if !defined(EXTDLL_H)
#define EXTDLL_H #define EXTDLL_H
#include "build.h"
// //
// Global header file for extension DLLs // Global header file for extension DLLs
// //
@ -35,7 +35,7 @@
#endif #endif
// Prevent tons of unused windows definitions // Prevent tons of unused windows definitions
#if _WIN32 #if XASH_WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define NOWINRES #define NOWINRES
#define NOSERVICE #define NOSERVICE
@ -76,10 +76,6 @@ typedef int BOOL;
#define M_PI_F (float)M_PI #define M_PI_F (float)M_PI
#endif #endif
#if __LP64__ || __LLP64__ || _WIN64 || (__x86_64__ && !__ILP32__) || _M_X64 || __ia64 || _M_IA64 || __aarch64__ || __powerpc64__
#define XASH_64BIT 1
#endif
// Header file containing definition of globalvars_t and entvars_t // Header file containing definition of globalvars_t and entvars_t
typedef unsigned int func_t; typedef unsigned int func_t;
typedef int string_t; // from engine's pr_comp.h; typedef int string_t; // from engine's pr_comp.h;

View File

@ -928,22 +928,25 @@ void CPushable::Move( CBaseEntity *pOther, int push )
if( pOther->IsPlayer() ) if( pOther->IsPlayer() )
{ {
// g-cont. fix pushable acceleration bug (now implemented as cvar) if( pushablemode.value == -1 )
if (pushablemode.value == 1)
{
// Allow player push when moving right, left and back too
if ( push && !(pevToucher->button & (IN_FORWARD|IN_MOVERIGHT|IN_MOVELEFT|IN_BACK)) )
return;
// Require player walking back when applying '+use' on pushable
if ( !push && !(pevToucher->button & (IN_BACK)) )
return;
}
else
{ {
// Don't push unless the player is pushing forward and NOT use (pull) // Don't push unless the player is pushing forward and NOT use (pull)
if( push && !( pevToucher->button & ( IN_FORWARD | IN_USE ) ) ) if( push && !( pevToucher->button & ( IN_FORWARD | IN_USE )))
return; return;
} }
// g-cont. fix pushable acceleration bug (now implemented as cvar)
else if( pushablemode.value != 0 )
{
// Allow player push when moving right, left and back too
if( push && !( pevToucher->button & ( IN_FORWARD | IN_MOVERIGHT | IN_MOVELEFT | IN_BACK )))
return;
// Require player walking back when applying '+use' on pushable
if( !push && !( pevToucher->button & ( IN_BACK )))
return;
}
// Don't push when +use pressed
else if( push && ( pevToucher->button & ( IN_USE )))
return;
playerTouch = 1; playerTouch = 1;
} }
@ -964,30 +967,55 @@ void CPushable::Move( CBaseEntity *pOther, int push )
else else
factor = 0.25f; factor = 0.25f;
// Spirit fix for pushable acceleration if( pushablemode.value != 0 )
if (pushablemode.value == 2)
{ {
if (!push) pev->velocity.x += pevToucher->velocity.x * factor;
factor *= 0.5f; pev->velocity.y += pevToucher->velocity.y * factor;
} }
else
{
if( push )
{
factor = 0.25f;
pev->velocity.x += pevToucher->velocity.x * factor;
pev->velocity.y += pevToucher->velocity.y * factor;
}
else
{
// fix for pushable acceleration
if( sv_pushable_fixed_tick_fudge.value >= 0 )
factor *= ( sv_pushable_fixed_tick_fudge.value * gpGlobals->frametime );
pev->velocity.x += pevToucher->velocity.x * factor; if( fabs( pev->velocity.x ) < fabs( pevToucher->velocity.x - pevToucher->velocity.x * factor ))
pev->velocity.y += pevToucher->velocity.y * factor; pev->velocity.x += pevToucher->velocity.x * factor;
if( fabs( pev->velocity.y ) < fabs( pevToucher->velocity.y - pevToucher->velocity.y * factor ))
pev->velocity.y += pevToucher->velocity.y * factor;
}
}
float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y ); float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y );
if( push && ( length > MaxSpeed() ) ) if( ( push && pushablemode.value != 0 )
|| pushablemode.value == 0 )
{ {
pev->velocity.x = (pev->velocity.x * MaxSpeed() / length ); if( length > MaxSpeed())
pev->velocity.y = (pev->velocity.y * MaxSpeed() / length ); {
pev->velocity.x = ( pev->velocity.x * MaxSpeed() / length );
pev->velocity.y = ( pev->velocity.y * MaxSpeed() / length );
}
} }
if( playerTouch ) if( playerTouch )
{ {
pevToucher->velocity.x = pev->velocity.x; if( push || pushablemode.value != 0 )
pevToucher->velocity.y = pev->velocity.y; {
pevToucher->velocity.x = pev->velocity.x;
pevToucher->velocity.y = pev->velocity.y;
}
if( ( gpGlobals->time - m_soundTime ) > 0.7f ) if( ( gpGlobals->time - m_soundTime ) > 0.7f )
{ {
m_soundTime = gpGlobals->time; m_soundTime = gpGlobals->time;
if( length > 0 && FBitSet( pev->flags,FL_ONGROUND ) ) if( length > 0 && FBitSet( pev->flags, FL_ONGROUND ))
{ {
m_lastSound = RANDOM_LONG( 0, 2 ); m_lastSound = RANDOM_LONG( 0, 2 );
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, m_soundNames[m_lastSound], 0.5f, ATTN_NORM ); EMIT_SOUND( ENT( pev ), CHAN_WEAPON, m_soundNames[m_lastSound], 0.5f, ATTN_NORM );

View File

@ -20,7 +20,6 @@
//++ BulliT //++ BulliT
#include "agglobal.h" #include "agglobal.h"
//-- Martin Webrant //-- Martin Webrant
BOOL g_fIsXash3D;
cvar_t displaysoundlist = {"displaysoundlist","0"}; cvar_t displaysoundlist = {"displaysoundlist","0"};
@ -37,7 +36,7 @@ cvar_t falldamage = { "mp_falldamage","0", FCVAR_SERVER };
cvar_t weaponstay = { "mp_weaponstay","0", FCVAR_SERVER }; cvar_t weaponstay = { "mp_weaponstay","0", FCVAR_SERVER };
cvar_t selfgauss = { "selfgauss", "1", FCVAR_SERVER }; cvar_t selfgauss = { "selfgauss", "1", FCVAR_SERVER };
cvar_t chargerfix = { "chargerfix", "0", FCVAR_SERVER }; cvar_t chargerfix = { "chargerfix", "0", FCVAR_SERVER };
cvar_t satchelfix = { "satchelfix", "0", FCVAR_SERVER }; cvar_t satchelfix = { "satchelfix", "1", FCVAR_SERVER };
cvar_t explosionfix = { "explosionfix", "0", FCVAR_SERVER }; cvar_t explosionfix = { "explosionfix", "0", FCVAR_SERVER };
cvar_t monsteryawspeedfix = { "monsteryawspeedfix", "1", FCVAR_SERVER }; cvar_t monsteryawspeedfix = { "monsteryawspeedfix", "1", FCVAR_SERVER };
cvar_t corpsephysics = { "corpsephysics", "0", FCVAR_SERVER }; cvar_t corpsephysics = { "corpsephysics", "0", FCVAR_SERVER };
@ -459,14 +458,13 @@ cvar_t sk_player_leg3 = { "sk_player_leg3","1" };
// END Cvars for Skill Level settings // END Cvars for Skill Level settings
cvar_t sv_pushable_fixed_tick_fudge = { "sv_pushable_fixed_tick_fudge", "15" };
cvar_t sv_busters = { "sv_busters", "0" };
// Register your console variables here // Register your console variables here
// This gets called one time when the game is initialied // This gets called one time when the game is initialied
void GameDLLInit( void ) void GameDLLInit( void )
{ {
// Register cvars here:
if( CVAR_GET_POINTER( "build" ) )
g_fIsXash3D = TRUE;
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" ); g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
g_psv_aim = CVAR_GET_POINTER( "sv_aim" ); g_psv_aim = CVAR_GET_POINTER( "sv_aim" );
g_footsteps = CVAR_GET_POINTER( "mp_footsteps" ); g_footsteps = CVAR_GET_POINTER( "mp_footsteps" );
@ -506,7 +504,7 @@ void GameDLLInit( void )
CVAR_REGISTER( &multibyte_only ); CVAR_REGISTER( &multibyte_only );
CVAR_REGISTER( &mp_chattime ); CVAR_REGISTER( &mp_chattime );
CVAR_REGISTER( &sv_busters );
// REGISTER CVARS FOR SKILL LEVEL STUFF // REGISTER CVARS FOR SKILL LEVEL STUFF
@ -884,6 +882,7 @@ void GameDLLInit( void )
CVAR_REGISTER( &sk_player_leg3 ); CVAR_REGISTER( &sk_player_leg3 );
// END REGISTER CVARS FOR SKILL LEVEL STUFF // END REGISTER CVARS FOR SKILL LEVEL STUFF
CVAR_REGISTER( &sv_pushable_fixed_tick_fudge );
//++ BulliT //++ BulliT
AgInitGame(); AgInitGame();
//-- Martin Webrant //-- Martin Webrant

View File

@ -42,6 +42,9 @@ extern cvar_t teamlist;
extern cvar_t teamoverride; extern cvar_t teamoverride;
extern cvar_t defaultteam; extern cvar_t defaultteam;
extern cvar_t allowmonsters; extern cvar_t allowmonsters;
extern cvar_t bhopcap;
extern cvar_t sv_pushable_fixed_tick_fudge;
extern cvar_t sv_busters;
// Engine Cvars // Engine Cvars
extern cvar_t *g_psv_gravity; extern cvar_t *g_psv_gravity;

View File

@ -28,8 +28,6 @@
extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer ); extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer );
extern BOOL g_fIsXash3D;
//++ BulliT //++ BulliT
DLL_GLOBAL AgGameRules *g_pGameRules = NULL; DLL_GLOBAL AgGameRules *g_pGameRules = NULL;
//-- Martin Webrant //-- Martin Webrant
@ -380,6 +378,11 @@ AgGameRules *InstallGameRules( void )
g_teamplay = 1; g_teamplay = 1;
return new CHalfLifeTeamplay; return new CHalfLifeTeamplay;
} }
if( sv_busters.value > 0 )
{
g_teamplay = 0;
return new CMultiplayBusters;
}
if( (int)gpGlobals->deathmatch == 1 ) if( (int)gpGlobals->deathmatch == 1 )
{ {
// vanilla deathmatch // vanilla deathmatch

View File

@ -168,11 +168,13 @@ public:
// Immediately end a multiplayer game // Immediately end a multiplayer game
virtual void EndMultiplayerGame( void ) {} virtual void EndMultiplayerGame( void ) {}
virtual BOOL IsBustingGame( void ){ return FALSE; };
}; };
//++ BulliT //++ BulliT
//extern CGameRules *InstallGameRules( void ); //extern CGameRules *InstallGameRules( void );
//-- Martin Webrant //-- Martin Webrant
BOOL HLGetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon );
//========================================================= //=========================================================
// CHalfLifeRules - rules for the single player Half-Life // CHalfLifeRules - rules for the single player Half-Life
@ -260,7 +262,6 @@ public:
virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget );
}; };
//++ BulliT //++ BulliT
#include "aggamerules.h" #include "aggamerules.h"
extern AgGameRules *InstallGameRules( void ); extern AgGameRules *InstallGameRules( void );

View File

@ -204,6 +204,8 @@ void CGauss::PrimaryAttack()
void CGauss::SecondaryAttack() void CGauss::SecondaryAttack()
{ {
if( m_pPlayer->m_flStartCharge > gpGlobals->time )
m_pPlayer->m_flStartCharge = gpGlobals->time;
// don't fire underwater // don't fire underwater
if( m_pPlayer->pev->waterlevel == 3 ) if( m_pPlayer->pev->waterlevel == 3 )
{ {
@ -349,6 +351,8 @@ void CGauss::StartFire( void )
{ {
float flDamage; float flDamage;
if( m_pPlayer->m_flStartCharge > gpGlobals->time )
m_pPlayer->m_flStartCharge = gpGlobals->time;
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
Vector vecAiming = gpGlobals->v_forward; Vector vecAiming = gpGlobals->v_forward;
Vector vecSrc = m_pPlayer->GetGunPosition(); // + gpGlobals->v_up * -8 + gpGlobals->v_right * 8; Vector vecSrc = m_pPlayer->GetGunPosition(); // + gpGlobals->v_up * -8 + gpGlobals->v_right * 8;
@ -472,12 +476,21 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
ClearMultiDamage(); ClearMultiDamage();
//++ BulliT //++ BulliT
//pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_ENERGYBEAM ); //pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_ENERGYBEAM );
if( pEntity == m_pPlayer && 0 < ag_gauss_fix.value ) if( pEntity == m_pPlayer )
{ {
//Skip reflective gauss on the player that holds the gun. Americans that wanna fiddle around :P if( 0 < ag_gauss_fix.value )
{
//Skip reflective gauss on the player that holds the gun. Americans that wanna fiddle around :P
}
else
{
tr.iHitgroup = 0;
pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_ENERGYBEAM );
}
} }
else else
{ {
pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_ENERGYBEAM ); pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_ENERGYBEAM );
//pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET ); //pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET );
} }

View File

@ -267,6 +267,7 @@ void CGrenade::BounceTouch( CBaseEntity *pOther )
pev->velocity = pev->velocity * 0.8f; pev->velocity = pev->velocity * 0.8f;
pev->sequence = RANDOM_LONG( 1, 1 ); pev->sequence = RANDOM_LONG( 1, 1 );
ResetSequenceInfo();
} }
else else
{ {
@ -410,7 +411,9 @@ CGrenade *CGrenade::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vec
pGrenade->pev->velocity = Vector( 0, 0, 0 ); pGrenade->pev->velocity = Vector( 0, 0, 0 );
} }
SET_MODEL( ENT( pGrenade->pev ), "models/w_grenade.mdl" );
pGrenade->pev->sequence = RANDOM_LONG( 3, 6 ); pGrenade->pev->sequence = RANDOM_LONG( 3, 6 );
pGrenade->ResetSequenceInfo();
pGrenade->pev->framerate = 1.0f; pGrenade->pev->framerate = 1.0f;
// Tumble through the air // Tumble through the air
@ -419,7 +422,6 @@ CGrenade *CGrenade::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vec
pGrenade->pev->gravity = 0.5f; pGrenade->pev->gravity = 0.5f;
pGrenade->pev->friction = 0.8f; pGrenade->pev->friction = 0.8f;
SET_MODEL( ENT( pGrenade->pev ), "models/w_grenade.mdl" );
pGrenade->pev->dmg = 100; pGrenade->pev->dmg = 100;
return pGrenade; return pGrenade;

View File

@ -36,4 +36,4 @@ DLL_GLOBAL int g_iSkillLevel;
DLL_GLOBAL int gDisplayTitle; DLL_GLOBAL int gDisplayTitle;
DLL_GLOBAL BOOL g_fGameOver; DLL_GLOBAL BOOL g_fGameOver;
DLL_GLOBAL const Vector g_vecZero = Vector( 0, 0, 0 ); DLL_GLOBAL const Vector g_vecZero = Vector( 0, 0, 0 );
DLL_GLOBAL int g_Language;

View File

@ -49,6 +49,8 @@ public:
virtual int Restore( CRestore &restore ); virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
BOOL IsAllowedToSpeak( void ) { return TRUE; }
int m_animate; int m_animate;
}; };

View File

@ -29,7 +29,7 @@
enginefuncs_t g_engfuncs; enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals; globalvars_t *gpGlobals;
#if _WIN32 #if XASH_WIN32
// Required DLL entry point // Required DLL entry point
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )

View File

@ -140,9 +140,9 @@ void CHandGrenade::WeaponIdle( void )
else else
angThrow.x = -10.0f + angThrow.x * ( ( 90.0f + 10.0f ) / 90.0f ); angThrow.x = -10.0f + angThrow.x * ( ( 90.0f + 10.0f ) / 90.0f );
float flVel = ( 90.0f - angThrow.x ) * 4.0f; float flVel = ( 90.0f - angThrow.x ) * 6.5f;
if( flVel > 500.0f ) if( flVel > 1000.0f )
flVel = 500.0f; flVel = 1000.0f;
UTIL_MakeVectors( angThrow ); UTIL_MakeVectors( angThrow );

View File

@ -278,7 +278,7 @@ void CHGrunt::GibMonster( void )
Vector vecGunPos; Vector vecGunPos;
Vector vecGunAngles; Vector vecGunAngles;
if( GetBodygroup( 2 ) != 2 ) if( GetBodygroup( GUN_GROUP ) != GUN_NONE )
{ {
// throw a gun if the grunt has one // throw a gun if the grunt has one
GetAttachment( 0, vecGunPos, vecGunAngles ); GetAttachment( 0, vecGunPos, vecGunAngles );
@ -604,7 +604,7 @@ void CHGrunt::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
if( ptr->iHitgroup == 11 ) if( ptr->iHitgroup == 11 )
{ {
// make sure we're wearing one // make sure we're wearing one
if( GetBodygroup( 1 ) == HEAD_GRUNT && ( bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB ) ) ) if( GetBodygroup( HEAD_GROUP ) == HEAD_GRUNT && ( bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB ) ) )
{ {
// absorb damage // absorb damage
flDamage -= 20; flDamage -= 20;
@ -849,27 +849,30 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
{ {
case HGRUNT_AE_DROP_GUN: case HGRUNT_AE_DROP_GUN:
{ {
Vector vecGunPos; if ( GetBodygroup( GUN_GROUP ) != GUN_NONE )
Vector vecGunAngles;
GetAttachment( 0, vecGunPos, vecGunAngles );
// switch to body group with no gun.
SetBodygroup( GUN_GROUP, GUN_NONE );
// now spawn a gun.
if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) )
{ {
DropItem( "weapon_shotgun", vecGunPos, vecGunAngles ); Vector vecGunPos;
} Vector vecGunAngles;
else
{
DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles );
}
if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) GetAttachment( 0, vecGunPos, vecGunAngles );
{
DropItem( "ammo_ARgrenades", BodyTarget( pev->origin ), vecGunAngles ); // switch to body group with no gun.
SetBodygroup( GUN_GROUP, GUN_NONE );
// now spawn a gun.
if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) )
{
DropItem( "weapon_shotgun", vecGunPos, vecGunAngles );
}
else
{
DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles );
}
if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) )
{
DropItem( "ammo_ARgrenades", BodyTarget( pev->origin ), vecGunAngles );
}
} }
} }
break; break;

View File

@ -153,7 +153,12 @@ void CHgun::PrimaryAttack()
CBaseEntity *pHornet = CBaseEntity::Create( "hornet", m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16.0f + gpGlobals->v_right * 8.0f + gpGlobals->v_up * -12.0f, m_pPlayer->pev->v_angle, m_pPlayer->edict() ); CBaseEntity *pHornet = CBaseEntity::Create( "hornet", m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16.0f + gpGlobals->v_right * 8.0f + gpGlobals->v_up * -12.0f, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pHornet->pev->velocity = gpGlobals->v_forward * 300.0f; pHornet->pev->velocity = gpGlobals->v_forward * 300.0f;
m_flRechargeTime = gpGlobals->time + 0.5f; float flRechargeTimePause = 0.5f;
if( g_pGameRules->IsMultiplayer() )
flRechargeTimePause = 0.3f;
m_flRechargeTime = gpGlobals->time + flRechargeTimePause;
#endif #endif
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
@ -245,8 +250,14 @@ void CHgun::SecondaryAttack( void )
pHornet->SetThink( &CHornet::StartDart ); pHornet->SetThink( &CHornet::StartDart );
m_flRechargeTime = gpGlobals->time + 0.5f; float flRechargeTimePause = 0.5f;
if( g_pGameRules->IsMultiplayer() )
flRechargeTimePause = 0.3f;
m_flRechargeTime = gpGlobals->time + flRechargeTimePause;
#endif #endif
int flags; int flags;
#if CLIENT_WEAPONS #if CLIENT_WEAPONS
flags = FEV_NOTHOST; flags = FEV_NOTHOST;
@ -279,8 +290,16 @@ void CHgun::Reload( void )
while( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < HORNET_MAX_CARRY && m_flRechargeTime < gpGlobals->time ) while( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < HORNET_MAX_CARRY && m_flRechargeTime < gpGlobals->time )
{ {
float flRechargeTimePause = 0.5f;
#if CLIENT_DLL
if( bIsMultiplayer() )
#else
if( g_pGameRules->IsMultiplayer() )
#endif
flRechargeTimePause = 0.3f;
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++;
m_flRechargeTime += 0.5f; m_flRechargeTime += flRechargeTimePause;
} }
} }

View File

@ -732,6 +732,7 @@ void CISlave::ArmBeam( int side )
m_pBeam[m_iBeams]->SetColor( 96, 128, 16 ); m_pBeam[m_iBeams]->SetColor( 96, 128, 16 );
m_pBeam[m_iBeams]->SetBrightness( 64 ); m_pBeam[m_iBeams]->SetBrightness( 64 );
m_pBeam[m_iBeams]->SetNoise( 80 ); m_pBeam[m_iBeams]->SetNoise( 80 );
m_pBeam[m_iBeams]->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition
m_iBeams++; m_iBeams++;
} }
@ -776,6 +777,7 @@ void CISlave::WackBeam( int side, CBaseEntity *pEntity )
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 ); m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
m_pBeam[m_iBeams]->SetBrightness( 255 ); m_pBeam[m_iBeams]->SetBrightness( 255 );
m_pBeam[m_iBeams]->SetNoise( 80 ); m_pBeam[m_iBeams]->SetNoise( 80 );
m_pBeam[m_iBeams]->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition
m_iBeams++; m_iBeams++;
} }
@ -806,6 +808,7 @@ void CISlave::ZapBeam( int side )
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 ); m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
m_pBeam[m_iBeams]->SetBrightness( 255 ); m_pBeam[m_iBeams]->SetBrightness( 255 );
m_pBeam[m_iBeams]->SetNoise( 20 ); m_pBeam[m_iBeams]->SetNoise( 20 );
m_pBeam[m_iBeams]->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition
m_iBeams++; m_iBeams++;
pEntity = CBaseEntity::Instance( tr.pHit ); pEntity = CBaseEntity::Instance( tr.pHit );

View File

@ -1392,7 +1392,7 @@ float CBaseMonster::OpenDoorAndWait( entvars_t *pevDoor )
//ALERT( at_aiconsole, "A door. " ); //ALERT( at_aiconsole, "A door. " );
CBaseEntity *pcbeDoor = CBaseEntity::Instance( pevDoor ); CBaseEntity *pcbeDoor = CBaseEntity::Instance( pevDoor );
if( pcbeDoor && !pcbeDoor->IsLockedByMaster() ) if( pcbeDoor )
{ {
//ALERT( at_aiconsole, "unlocked! " ); //ALERT( at_aiconsole, "unlocked! " );
pcbeDoor->Use( this, this, USE_ON, 0.0 ); pcbeDoor->Use( this, this, USE_ON, 0.0 );
@ -3189,27 +3189,6 @@ BOOL CBaseMonster::FCanActiveIdle( void )
return FALSE; return FALSE;
} }
void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation )
{
if( pszSentence && IsAlive() )
{
if( pszSentence[0] == '!' )
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, PITCH_NORM );
else
SENTENCEG_PlayRndSz( edict(), pszSentence, volume, attenuation, 0, PITCH_NORM );
}
}
void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener )
{
PlaySentence( pszSentence, duration, volume, attenuation );
}
void CBaseMonster::SentenceStop( void )
{
EMIT_SOUND( edict(), CHAN_VOICE, "common/null.wav", 1.0, ATTN_IDLE );
}
void CBaseMonster::CorpseFallThink( void ) void CBaseMonster::CorpseFallThink( void )
{ {
if( pev->flags & FL_ONGROUND ) if( pev->flags & FL_ONGROUND )

View File

@ -69,12 +69,14 @@ void CMP5::Spawn()
m_iId = WEAPON_MP5; m_iId = WEAPON_MP5;
m_iDefaultAmmo = MP5_DEFAULT_GIVE; m_iDefaultAmmo = MP5_DEFAULT_GIVE;
//++ BulliT
#if !CLIENT_DLL #if CLIENT_DLL
if( ARENA == AgGametype() || ARCADE == AgGametype() || LMS == AgGametype() ) if( bIsMultiplayer() )
m_iDefaultAmmo = MP5_MAX_CLIP; #else
if( g_pGameRules->IsMultiplayer() )
#endif #endif
//-- Martin Webrant m_iDefaultAmmo = MP5_DEFAULT_GIVE_MP;
FallInit();// get ready to fall down. FallInit();// get ready to fall down.
} }

View File

@ -30,6 +30,7 @@
#include "voice_gamemgr.h" #include "voice_gamemgr.h"
#endif #endif
#include "hltv.h" #include "hltv.h"
#include "trains.h"
//++ BulliT //++ BulliT
#include "aggamerules.h" #include "aggamerules.h"
@ -321,6 +322,8 @@ BOOL CHalfLifeMultiplay::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerI
//-- Martin Webrant //-- Martin Webrant
} }
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay::GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) BOOL CHalfLifeMultiplay::GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon )
{ {
//++ BulliT //++ BulliT
@ -379,12 +382,13 @@ void CHalfLifeMultiplay::InitHUD( CBasePlayer *pl )
// sending just one score makes the hud scoreboard active; otherwise // sending just one score makes the hud scoreboard active; otherwise
// it is just disabled for single play // it is just disabled for single play
MESSAGE_BEGIN( MSG_ONE, gmsgScoreInfo, NULL, pl->edict() ); //fix a bug in the information about the player's score when he left the server, so that his score would not be transferred to another player(seems to work)
MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo );
WRITE_BYTE( ENTINDEX(pl->edict()) ); WRITE_BYTE( ENTINDEX(pl->edict()) );
WRITE_SHORT( (int)pl->pev->frags );
WRITE_SHORT( pl->m_iDeaths );
WRITE_SHORT( 0 ); WRITE_SHORT( 0 );
WRITE_SHORT( 0 ); WRITE_SHORT( GetTeamIndex( pl->m_szTeamName ) + 1 );
WRITE_SHORT( 0 );
WRITE_SHORT( 0 );
MESSAGE_END(); MESSAGE_END();
SendMOTDToClient( pl->edict() ); SendMOTDToClient( pl->edict() );
@ -571,6 +575,16 @@ void CHalfLifeMultiplay::PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller,
CBaseEntity *ktmp = CBaseEntity::Instance( pKiller ); CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
if( ktmp && (ktmp->Classify() == CLASS_PLAYER ) ) if( ktmp && (ktmp->Classify() == CLASS_PLAYER ) )
peKiller = (CBasePlayer*)ktmp; peKiller = (CBasePlayer*)ktmp;
else if( ktmp && ktmp->Classify() == CLASS_VEHICLE )
{
CBasePlayer *pDriver = (CBasePlayer *)( (CFuncVehicle *)ktmp )->m_pDriver;
if( pDriver != NULL )
{
pKiller = pDriver->pev;
peKiller = (CBasePlayer *)pDriver;
}
}
if( pVictim->pev == pKiller ) if( pVictim->pev == pKiller )
{ {
@ -1672,3 +1686,219 @@ void CHalfLifeMultiplay::SendMOTDToClient( edict_t *client )
FREE_FILE( (void*)aFileList ); FREE_FILE( (void*)aFileList );
} }
int CMultiplayBusters::WeaponShouldRespawn( CBasePlayerItem *pWeapon )
{
if( pWeapon->m_iId == WEAPON_EGON )
return GR_WEAPON_RESPAWN_NO;
return CHalfLifeMultiplay::WeaponShouldRespawn( pWeapon );
}
BOOL CMultiplayBusters::CanHaveItem( CBasePlayer *pPlayer, CItem *pItem )
{
return BustingCanHaveItem( pPlayer, pItem );
}
BOOL CMultiplayBusters::CanHavePlayerItem( CBasePlayer *pPlayer, CBasePlayerItem *pItem )
{
if( !BustingCanHaveItem( pPlayer, pItem ))
return FALSE;
return CHalfLifeMultiplay::CanHavePlayerItem( pPlayer, pItem );
}
int CMultiplayBusters::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled )
{
if( IsPlayerBusting( pAttacker ))
return 1;
if( IsPlayerBusting( pKilled ))
return 2;
return 0;
}
void CMultiplayBusters::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor )
{
if( IsPlayerBusting( pVictim )
|| IsPlayerBusting( CBaseEntity::Instance( pKiller )))
CHalfLifeMultiplay::DeathNotice( pVictim, pKiller, pevInflictor );
}
void CMultiplayBusters::PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
if( IsPlayerBusting( pVictim ))
{
UTIL_ClientPrintAll( HUD_PRINTCENTER, "The Buster is dead!!" );
m_flEgonBustingCheckTime = -1.0f;
CBasePlayer *peKiller = NULL;
CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
if( ktmp && ( ktmp->Classify() == CLASS_PLAYER ) )
peKiller = (CBasePlayer*)ktmp;
else if( ktmp && ktmp->Classify() == CLASS_VEHICLE )
{
CBasePlayer *pDriver = (CBasePlayer *)( (CFuncVehicle *)ktmp )->m_pDriver;
if( pDriver != NULL )
{
pKiller = pDriver->pev;
peKiller = (CBasePlayer *)pDriver;
}
}
if( peKiller && peKiller->IsPlayer() )
{
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s has killed the Buster!", STRING( peKiller->pev->netname )));
}
pVictim->pev->renderfx = 0;
pVictim->pev->rendercolor = g_vecZero;
}
CHalfLifeMultiplay::PlayerKilled( pVictim, pKiller, pInflictor );
}
void CMultiplayBusters::ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer )
{
SetPlayerModel( pPlayer, FALSE );
CHalfLifeMultiplay::ClientUserInfoChanged( pPlayer, infobuffer );
}
void CMultiplayBusters::PlayerSpawn( CBasePlayer *pPlayer )
{
CHalfLifeMultiplay::PlayerSpawn( pPlayer );
SetPlayerModel( pPlayer, FALSE );
}
bool IsPlayerBusting( CBaseEntity *pPlayer )
{
if( g_pGameRules->IsBustingGame()
&& pPlayer && pPlayer->IsPlayer()
&& ((CBasePlayer*)pPlayer)->HasPlayerItemFromID( WEAPON_EGON ))
return true;
return false;
}
BOOL BustingCanHaveItem( CBasePlayer *pPlayer, CBaseEntity *pItem )
{
if( IsPlayerBusting( pPlayer )
&& !( strncmp( STRING( pItem->pev->classname ), "weapon_", 7 )
&& strncmp( STRING( pItem->pev->classname ), "ammo_", 5 )))
return FALSE;
return TRUE;
}
CMultiplayBusters::CMultiplayBusters()
{
CHalfLifeMultiplay();
m_flEgonBustingCheckTime = -1.0;
}
void CMultiplayBusters::CheckForEgons( void )
{
CBaseEntity *pPlayer;
CWeaponBox *pWeaponBox = NULL;
CBasePlayerItem *pWeapon;
CBasePlayer *pNewBuster = NULL;
int i, bestfrags = 9999;
if( m_flEgonBustingCheckTime <= 0.0f )
{
m_flEgonBustingCheckTime = gpGlobals->time + 10.0f;
return;
}
if( gpGlobals->time < m_flEgonBustingCheckTime )
return;
m_flEgonBustingCheckTime = -1.0f;
for( i = 1; i <= gpGlobals->maxClients; i++ )
{
pPlayer = UTIL_PlayerByIndex( i );
if( IsPlayerBusting( pPlayer ))
return;
}
for( i = 1; i <= gpGlobals->maxClients; i++ )
{
pPlayer = UTIL_PlayerByIndex( i );
if( pPlayer && pPlayer->pev->frags < bestfrags )
{
pNewBuster = (CBasePlayer*)pPlayer;
bestfrags = pPlayer->pev->frags;
}
}
if( !pNewBuster )
return;
pNewBuster->GiveNamedItem( "weapon_egon" );
while( ( pWeaponBox = (CWeaponBox*)UTIL_FindEntityByClassname( pWeaponBox, "weaponbox" )))
{
// destroy weaponboxes with egons
for( i = 0; i < MAX_ITEM_TYPES; i++ )
{
pWeapon = pWeaponBox->m_rgpPlayerItems[i];
while( pWeapon )
{
if( pWeapon->m_iId != WEAPON_EGON )
{
pWeapon = pWeapon->m_pNext;
continue;
}
pWeaponBox->Kill();
pWeapon = 0;
i = MAX_ITEM_TYPES;
}
}
}
}
void CMultiplayBusters::Think( void )
{
CheckForEgons();
CHalfLifeMultiplay::Think();
}
void CMultiplayBusters::SetPlayerModel( CBasePlayer *pPlayer, BOOL bKnownBuster )
{
const char *pszModel = NULL;
if( bKnownBuster || IsPlayerBusting( pPlayer ))
{
pszModel = "ivan";
}
else
{
pszModel = "skeleton";
}
g_engfuncs.pfnSetClientKeyValue( ENTINDEX( pPlayer->edict()), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict()), "model", pszModel );
}
void CMultiplayBusters::PlayerGotWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon )
{
if( pWeapon->m_iId != WEAPON_EGON )
return;
pPlayer->RemoveAllItems( FALSE );
UTIL_ClientPrintAll( HUD_PRINTCENTER, "Long live the new Buster!" );
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s is busting!\n", STRING( pPlayer->pev->netname )));
SetPlayerModel( pPlayer, TRUE );
pPlayer->pev->health = pPlayer->pev->max_health;
pPlayer->pev->armorvalue = MAX_NORMAL_BATTERY;
pPlayer->pev->renderfx = kRenderFxGlowShell;
pPlayer->pev->renderamt = 25;
pPlayer->pev->rendercolor = Vector( 0, 75, 250 );
pPlayer->m_rgAmmo[pWeapon->PrimaryAmmoIndex()] = pPlayer->ammo_uranium = 100;
}

View File

@ -737,7 +737,7 @@ void CBasePlayer::PackDeadPlayerItems( void )
{ {
int iWeaponRules; int iWeaponRules;
int iAmmoRules; int iAmmoRules;
int i; int i, j;
CBasePlayerWeapon *rgpPackWeapons[MAX_WEAPONS] = {0,}; CBasePlayerWeapon *rgpPackWeapons[MAX_WEAPONS] = {0,};
int iPackAmmo[MAX_AMMO_SLOTS]; int iPackAmmo[MAX_AMMO_SLOTS];
int iPW = 0;// index into packweapons array int iPW = 0;// index into packweapons array
@ -772,16 +772,26 @@ void CBasePlayer::PackDeadPlayerItems( void )
if( m_pActiveItem && pPlayerItem == m_pActiveItem ) if( m_pActiveItem && pPlayerItem == m_pActiveItem )
{ {
// this is the active item. Pack it. // this is the active item. Pack it.
rgpPackWeapons[iPW++] = (CBasePlayerWeapon *)pPlayerItem; rgpPackWeapons[iPW] = (CBasePlayerWeapon *)pPlayerItem;
} }
break; break;
case GR_PLR_DROP_GUN_ALL: case GR_PLR_DROP_GUN_ALL:
rgpPackWeapons[iPW++] = (CBasePlayerWeapon *)pPlayerItem; rgpPackWeapons[iPW] = (CBasePlayerWeapon *)pPlayerItem;
break; break;
default: default:
break; break;
} }
if( rgpPackWeapons[iPW] )
{
// complete the reload.
j = Q_min( rgpPackWeapons[iPW]->iMaxClip() - rgpPackWeapons[iPW]->m_iClip, m_rgAmmo[rgpPackWeapons[iPW]->m_iPrimaryAmmoType] );
// Add them to the clip
rgpPackWeapons[iPW]->m_iClip += j;
m_rgAmmo[rgpPackWeapons[iPW]->m_iPrimaryAmmoType] -= j;
iPW++;
}
pPlayerItem = pPlayerItem->m_pNext; pPlayerItem = pPlayerItem->m_pNext;
} }
} }
@ -831,24 +841,43 @@ void CBasePlayer::PackDeadPlayerItems( void )
iPA = 0; iPA = 0;
iPW = 0; iPW = 0;
// pack the ammo if( g_pGameRules->IsBustingGame())
while( iPackAmmo[iPA] != -1 )
{ {
pWeaponBox->PackAmmo( MAKE_STRING( CBasePlayerItem::AmmoInfoArray[iPackAmmo[iPA]].pszName ), m_rgAmmo[iPackAmmo[iPA]] ); while( rgpPackWeapons[iPW] )
iPA++; {
// weapon unhooked from the player. Pack it into der box.
if( FClassnameIs( rgpPackWeapons[iPW]->pev, "weapon_egon" ))
{
pWeaponBox->PackWeapon( rgpPackWeapons[iPW] );
SET_MODEL( pWeaponBox->edict(), "models/w_egon.mdl" );
pWeaponBox->pev->velocity = g_vecZero;
pWeaponBox->pev->renderfx = kRenderFxGlowShell;
pWeaponBox->pev->renderamt = 25;
pWeaponBox->pev->rendercolor = Vector( 0, 75, 250 );
break;
}
iPW++;
}
} }
else
// now pack all of the items in the lists
while( rgpPackWeapons[iPW] )
{ {
// weapon unhooked from the player. Pack it into der box. // pack the ammo
pWeaponBox->PackWeapon( rgpPackWeapons[iPW] ); while( iPackAmmo[iPA] != -1 )
{
pWeaponBox->PackAmmo( MAKE_STRING( CBasePlayerItem::AmmoInfoArray[iPackAmmo[iPA]].pszName ), m_rgAmmo[iPackAmmo[iPA]] );
iPA++;
}
iPW++; // now pack all of the items in the lists
while( rgpPackWeapons[iPW] )
{
// weapon unhooked from the player. Pack it into der box.
pWeaponBox->PackWeapon( rgpPackWeapons[iPW] );
iPW++;
}
pWeaponBox->pev->velocity = pev->velocity * 1.2f;// weaponbox has player's velocity, then some.
} }
pWeaponBox->pev->velocity = pev->velocity * 1.2;// weaponbox has player's velocity, then some.
RemoveAllItems( TRUE );// now strip off everything that wasn't handled by the code above. RemoveAllItems( TRUE );// now strip off everything that wasn't handled by the code above.
} }
@ -947,7 +976,7 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
SetAnimation( PLAYER_DIE ); SetAnimation( PLAYER_DIE );
m_iRespawnFrames = 0; m_flRespawnTimer = 0;
pev->modelindex = g_ulModelIndexPlayer; // don't use eyes pev->modelindex = g_ulModelIndexPlayer; // don't use eyes
@ -983,6 +1012,9 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
// UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12 // UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12
// UTIL_ScreenFade( edict(), Vector( 128, 0, 0 ), 6, 15, 255, FFADE_OUT | FFADE_MODULATE ); // UTIL_ScreenFade( edict(), Vector( 128, 0, 0 ), 6, 15, 255, FFADE_OUT | FFADE_MODULATE );
if( g_pGameRules->IsMultiplayer())
pev->solid = SOLID_NOT;
if( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS ) if( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS )
{ {
pev->solid = SOLID_NOT; pev->solid = SOLID_NOT;
@ -1346,23 +1378,30 @@ void CBasePlayer::PlayerDeathThink( void )
PackDeadPlayerItems(); PackDeadPlayerItems();
} }
if( pev->modelindex && ( !m_fSequenceFinished ) && ( pev->deadflag == DEAD_DYING ) ) if( pev->modelindex && ( !m_fSequenceFinished ) && ( pev->deadflag == DEAD_DYING ))
{ {
StudioFrameAdvance(); StudioFrameAdvance();
m_iRespawnFrames++; // Note, these aren't necessarily real "frames", so behavior is dependent on # of client movement commands m_flRespawnTimer = gpGlobals->frametime + m_flRespawnTimer; // Note, these aren't necessarily real "frames", so behavior is dependent on # of client movement commands
if( m_iRespawnFrames < 120 ) // Animations should be no longer than this if( m_flRespawnTimer < 4.0f ) // Animations should be no longer than this
return; return;
} }
if( pev->deadflag == DEAD_DYING )
{
if( g_pGameRules->IsMultiplayer() && m_fSequenceFinished && pev->movetype == MOVETYPE_NONE )
{
CopyToBodyQue( pev );
pev->modelindex = 0;
}
pev->deadflag = DEAD_DEAD;
}
// once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore // once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore
// this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn // this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn
if( pev->movetype != MOVETYPE_NONE && FBitSet( pev->flags, FL_ONGROUND ) ) if( pev->movetype != MOVETYPE_NONE && FBitSet( pev->flags, FL_ONGROUND ) )
pev->movetype = MOVETYPE_NONE; pev->movetype = MOVETYPE_NONE;
if( pev->deadflag == DEAD_DYING )
pev->deadflag = DEAD_DEAD;
StopAnimation(); StopAnimation();
pev->effects |= EF_NOINTERP; pev->effects |= EF_NOINTERP;
@ -1415,7 +1454,7 @@ void CBasePlayer::PlayerDeathThink( void )
//-- Martin Webrant //-- Martin Webrant
pev->button = 0; pev->button = 0;
m_iRespawnFrames = 0; m_flRespawnTimer = 0;
//ALERT( at_console, "Respawn\n" ); //ALERT( at_console, "Respawn\n" );
@ -1580,18 +1619,31 @@ void CBasePlayer::PlayerUse( void )
{ {
m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = TRAIN_NEW|TRAIN_OFF; m_iTrain = TRAIN_NEW|TRAIN_OFF;
CBaseEntity *pTrain = Instance( pev->groundentity );
if( pTrain && pTrain->Classify() == CLASS_VEHICLE )
{
( (CFuncVehicle *)pTrain )->m_pDriver = NULL;
}
return; return;
} }
else else
{ // Start controlling the train! { // Start controlling the train!
CBaseEntity *pTrain = CBaseEntity::Instance( pev->groundentity ); CBaseEntity *pTrain = CBaseEntity::Instance( pev->groundentity );
if( pTrain && !( pev->button & IN_JUMP ) && FBitSet( pev->flags, FL_ONGROUND ) && (pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE ) && pTrain->OnControls( pev ) ) if( pTrain && !( pev->button & IN_JUMP ) && FBitSet( pev->flags, FL_ONGROUND ) && ( pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE ) && pTrain->OnControls( pev ) )
{ {
m_afPhysicsFlags |= PFLAG_ONTRAIN; m_afPhysicsFlags |= PFLAG_ONTRAIN;
m_iTrain = TrainSpeed( (int)pTrain->pev->speed, pTrain->pev->impulse ); m_iTrain = TrainSpeed( (int)pTrain->pev->speed, pTrain->pev->impulse );
m_iTrain |= TRAIN_NEW; m_iTrain |= TRAIN_NEW;
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM );
if( pTrain->Classify() == CLASS_VEHICLE )
{
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "plats/vehicle_ignition.wav", 0.8, ATTN_NORM );
( (CFuncVehicle *)pTrain )->m_pDriver = this;
}
else
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM );
return; return;
} }
} }
@ -1705,9 +1757,17 @@ void CBasePlayer::Jump()
// If you're standing on a conveyor, add it's velocity to yours (for momentum) // If you're standing on a conveyor, add it's velocity to yours (for momentum)
entvars_t *pevGround = VARS( pev->groundentity ); entvars_t *pevGround = VARS( pev->groundentity );
if( pevGround && ( pevGround->flags & FL_CONVEYOR ) ) if( pevGround )
{ {
pev->velocity = pev->velocity + pev->basevelocity; if( pevGround->flags & FL_CONVEYOR )
{
pev->velocity = pev->velocity + pev->basevelocity;
}
if( FClassnameIs( pevGround, "func_vehicle" ))
{
pev->velocity = pevGround->velocity + pev->velocity;
}
} }
} }
@ -2019,30 +2079,62 @@ void CBasePlayer::PreThink( void )
//ALERT( at_error, "In train mode with no train!\n" ); //ALERT( at_error, "In train mode with no train!\n" );
m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = TRAIN_NEW|TRAIN_OFF; m_iTrain = TRAIN_NEW|TRAIN_OFF;
if( pTrain )
( (CFuncVehicle *)pTrain )->m_pDriver = NULL;
return; return;
} }
} }
else if( !FBitSet( pev->flags, FL_ONGROUND ) || FBitSet( pTrain->pev->spawnflags, SF_TRACKTRAIN_NOCONTROL ) || ( pev->button & ( IN_MOVELEFT | IN_MOVERIGHT ) ) ) else if( !FBitSet( pev->flags, FL_ONGROUND ) || FBitSet( pTrain->pev->spawnflags, SF_TRACKTRAIN_NOCONTROL )
|| ( ( pev->button & ( IN_MOVELEFT | IN_MOVERIGHT )) && pTrain->Classify() != CLASS_VEHICLE ))
{ {
// Turn off the train if you jump, strafe, or the train controls go dead // Turn off the train if you jump, strafe, or the train controls go dead
m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = TRAIN_NEW | TRAIN_OFF; m_iTrain = TRAIN_NEW | TRAIN_OFF;
( (CFuncVehicle *)pTrain )->m_pDriver = NULL;
return; return;
} }
pev->velocity = g_vecZero; pev->velocity = g_vecZero;
vel = 0; vel = 0;
if( m_afButtonPressed & IN_FORWARD )
{
vel = 1;
pTrain->Use( this, this, USE_SET, (float)vel );
}
else if( m_afButtonPressed & IN_BACK )
{
vel = -1;
pTrain->Use( this, this, USE_SET, (float)vel );
}
if( pTrain->Classify() == CLASS_VEHICLE )
{
if( pev->button & IN_FORWARD )
{
vel = 1;
pTrain->Use( this, this, USE_SET, vel );
}
if( pev->button & IN_BACK )
{
vel = -1;
pTrain->Use( this, this, USE_SET, vel );
}
if( pev->button & IN_MOVELEFT )
{
vel = 20;
pTrain->Use( this, this, USE_SET, vel );
}
if( pev->button & IN_MOVERIGHT )
{
vel = 30;
pTrain->Use( this, this, USE_SET, vel );
}
}
else
{
if( m_afButtonPressed & IN_FORWARD )
{
vel = 1;
pTrain->Use( this, this, USE_SET, vel );
}
else if( m_afButtonPressed & IN_BACK )
{
vel = -1;
pTrain->Use( this, this, USE_SET, vel );
}
}
iGearId = TrainSpeed( pTrain->pev->speed, pTrain->pev->impulse ); iGearId = TrainSpeed( pTrain->pev->speed, pTrain->pev->impulse );
if( iGearId != ( m_iTrain & 0x0F ) ) // Vit_amiN: speed changed if( iGearId != ( m_iTrain & 0x0F ) ) // Vit_amiN: speed changed
@ -2742,7 +2834,7 @@ void CBasePlayer::PostThink()
if( DEAD_NO == pev->deadflag || DEAD_RESPAWNABLE == pev->deadflag) if( DEAD_NO == pev->deadflag || DEAD_RESPAWNABLE == pev->deadflag)
{ {
pev->button = 0; pev->button = 0;
m_iRespawnFrames = 0; m_flRespawnTimer = 0;
pev->effects &= ~EF_NODRAW; pev->effects &= ~EF_NODRAW;
pev->takedamage = DAMAGE_YES; pev->takedamage = DAMAGE_YES;
@ -2897,7 +2989,7 @@ edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer )
{ {
pSpot = g_pLastSpawn; pSpot = g_pLastSpawn;
// Randomize the start spot // Randomize the start spot
for( int i = RANDOM_LONG( 1, 5 ); i > 0; i-- ) for( int i = RANDOM_LONG( 1, 9 ); i > 0; i-- )
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" ); pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
if( FNullEnt( pSpot ) ) // skip over the null point if( FNullEnt( pSpot ) ) // skip over the null point
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" ); pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
@ -2966,6 +3058,7 @@ ReturnSpot:
void CBasePlayer::Spawn( void ) void CBasePlayer::Spawn( void )
{ {
m_flStartCharge = gpGlobals->time;
pev->classname = MAKE_STRING( "player" ); pev->classname = MAKE_STRING( "player" );
pev->health = 100; pev->health = 100;
pev->armorvalue = 0; pev->armorvalue = 0;
@ -2998,6 +3091,8 @@ void CBasePlayer::Spawn( void )
m_fPlayerIdCheck = gpGlobals->time + 2; m_fPlayerIdCheck = gpGlobals->time + 2;
m_fLongjumpTimer = gpGlobals->time; m_fLongjumpTimer = gpGlobals->time;
//-- Martin Webrant //-- Martin Webrant
g_engfuncs.pfnSetPhysicsKeyValue( edict(), "fr", "1" );
pev->fov = m_iFOV = 0;// init field of view. pev->fov = m_iFOV = 0;// init field of view.
m_iClientFOV = -1; // make sure fov reset is sent m_iClientFOV = -1; // make sure fov reset is sent
@ -3202,6 +3297,9 @@ int CBasePlayer::Restore( CRestore &restore )
// Barring that, we clear it out here instead of using the incorrect restored time value. // Barring that, we clear it out here instead of using the incorrect restored time value.
m_flNextAttack = UTIL_WeaponTimeBase(); m_flNextAttack = UTIL_WeaponTimeBase();
#endif #endif
if( m_flFlashLightTime == 0.0f )
m_flFlashLightTime = 1.0f;
return status; return status;
} }
@ -3448,13 +3546,11 @@ void CBloodSplat::Spray( void )
{ {
TraceResult tr; TraceResult tr;
if( g_Language != LANGUAGE_GERMAN ) UTIL_MakeVectors( pev->angles );
{ UTIL_TraceLine( pev->origin, pev->origin + gpGlobals->v_forward * 128, ignore_monsters, pev->owner, & tr );
UTIL_MakeVectors( pev->angles );
UTIL_TraceLine( pev->origin, pev->origin + gpGlobals->v_forward * 128, ignore_monsters, pev->owner, & tr ); UTIL_BloodDecalTrace( &tr, BLOOD_COLOR_RED );
UTIL_BloodDecalTrace( &tr, BLOOD_COLOR_RED );
}
SetThink( &CBaseEntity::SUB_Remove ); SetThink( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1f; pev->nextthink = gpGlobals->time + 0.1f;
} }
@ -5033,6 +5129,31 @@ BOOL CBasePlayer::HasNamedPlayerItem( const char *pszItemName )
return FALSE; return FALSE;
} }
//=========================================================
// HasPlayerItemFromID
//=========================================================
BOOL CBasePlayer::HasPlayerItemFromID( int nID )
{
CBasePlayerItem *pItem;
int i;
for( i = 0; i < MAX_ITEM_TYPES; i++ )
{
pItem = m_rgpPlayerItems[i];
while( pItem )
{
if( nID == pItem->m_iId )
{
return TRUE;
}
pItem = pItem->m_pNext;
}
}
return FALSE;
}
//========================================================= //=========================================================
// //
//========================================================= //=========================================================

View File

@ -196,7 +196,7 @@ public:
Vector m_vecAutoAim; Vector m_vecAutoAim;
BOOL m_fOnTarget; BOOL m_fOnTarget;
int m_iDeaths; int m_iDeaths;
float m_iRespawnFrames; // used in PlayerDeathThink() to make sure players can always respawn float m_flRespawnTimer; // used in PlayerDeathThink() to make sure players can always respawn
int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE
@ -274,6 +274,7 @@ public:
void DropPlayerItem ( char *pszItemName ); void DropPlayerItem ( char *pszItemName );
BOOL HasPlayerItem( CBasePlayerItem *pCheckItem ); BOOL HasPlayerItem( CBasePlayerItem *pCheckItem );
BOOL HasNamedPlayerItem( const char *pszItemName ); BOOL HasNamedPlayerItem( const char *pszItemName );
BOOL HasPlayerItemFromID( int nID );
BOOL HasWeapons( void );// do I have ANY weapons? BOOL HasWeapons( void );// do I have ANY weapons?
void SelectPrevItem( int iItem ); void SelectPrevItem( int iItem );
void SelectNextItem( int iItem ); void SelectNextItem( int iItem );
@ -621,7 +622,8 @@ inline Vector CBasePlayer::GetKilledPosition()
inline bool CBasePlayer::ShouldWeaponSwitch() inline bool CBasePlayer::ShouldWeaponSwitch()
{ {
return 0 != m_iAutoWepSwitch; return ( 0 != m_iAutoWepSwitch && !( 2 == m_iAutoWepSwitch
&& ( m_afButtonLast & ( IN_ATTACK | IN_ATTACK2 ))));
}; };
inline void CBasePlayer::SetDisplayGamemode(float fTime) inline void CBasePlayer::SetDisplayGamemode(float fTime)

File diff suppressed because it is too large Load Diff

View File

@ -122,6 +122,25 @@ CRpgRocket *CRpgRocket::CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBa
return pRocket; return pRocket;
} }
void CRpgRocket::Explode( TraceResult *pTrace, int bitsDamageType )
{
if( CRpg *pLauncher = GetLauncher())
{
// my launcher is still around, tell it I'm dead.
pLauncher->m_cActiveRockets--;
m_hLauncher = 0;
}
STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" );
CGrenade::Explode( pTrace, bitsDamageType );
}
CRpg *CRpgRocket::GetLauncher( void )
{
return (CRpg*)( (CBaseEntity*)m_hLauncher );
}
//========================================================= //=========================================================
//========================================================= //=========================================================
void CRpgRocket::Spawn( void ) void CRpgRocket::Spawn( void )
@ -156,10 +175,11 @@ void CRpgRocket::Spawn( void )
//========================================================= //=========================================================
void CRpgRocket::RocketTouch( CBaseEntity *pOther ) void CRpgRocket::RocketTouch( CBaseEntity *pOther )
{ {
if( CRpg* pLauncher = (CRpg*)( (CBaseEntity*)( m_hLauncher ) ) ) if( CRpg *pLauncher = GetLauncher())
{ {
// my launcher is still around, tell it I'm dead. // my launcher is still around, tell it I'm dead.
pLauncher->m_cActiveRockets--; pLauncher->m_cActiveRockets--;
m_hLauncher = 0;
} }
STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" ); STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" );
@ -270,20 +290,23 @@ void CRpgRocket::FollowThink( void )
} }
pev->velocity = pev->velocity * 0.2f + vecTarget * flSpeed * 0.798f; pev->velocity = pev->velocity * 0.2f + vecTarget * flSpeed * 0.798f;
if( pev->waterlevel == 0 && pev->velocity.Length() < 1500.0f ) if( pev->waterlevel == 0 && pev->velocity.Length() < 1500.0f )
{
//++ BulliT
//Fixes the bug where it won't auto reload when it explodes coming out of the water
if( CRpg *pLauncher = (CRpg*)( (CBaseEntity*)( m_hLauncher ) ) )
{
// my launcher is still around, tell it I'm dead.
pLauncher->m_cActiveRockets--;
}
Detonate(); Detonate();
//-- Martin Webrant
}
} }
// ALERT( at_console, "%.0f\n", flSpeed ); // ALERT( at_console, "%.0f\n", flSpeed );
if( CRpg *pLauncher = GetLauncher())
{
if( ( pev->origin - pLauncher->pev->origin ).Length() > 8192 || gpGlobals->time - m_flIgniteTime > 6.0f )
{
// my launcher is still around, tell it I'm dead.
pLauncher->m_cActiveRockets--;
m_hLauncher = 0;
}
}
if( UTIL_PointContents( pev->origin ) == CONTENTS_SKY )
Detonate();
pev->nextthink = gpGlobals->time + 0.1f; pev->nextthink = gpGlobals->time + 0.1f;
} }
#endif #endif
@ -393,7 +416,7 @@ int CRpg::GetItemInfo( ItemInfo *p )
p->iSlot = 3; p->iSlot = 3;
p->iPosition = 0; p->iPosition = 0;
p->iId = m_iId = WEAPON_RPG; p->iId = m_iId = WEAPON_RPG;
p->iFlags = 0; p->iFlags = ITEM_FLAG_NOCHOICE;
p->iWeight = RPG_WEIGHT; p->iWeight = RPG_WEIGHT;
return 1; return 1;

View File

@ -22,6 +22,7 @@
#include "nodes.h" #include "nodes.h"
#include "player.h" #include "player.h"
#include "gamerules.h" #include "gamerules.h"
#include "game.h"
enum satchel_state enum satchel_state
{ {
@ -191,23 +192,39 @@ LINK_ENTITY_TO_CLASS( weapon_satchel, CSatchel )
//========================================================= //=========================================================
int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal ) int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal )
{ {
#if !CLIENT_DLL
CSatchel *pSatchel; CSatchel *pSatchel;
int nNumSatchels, nSatchelsInPocket;
CBaseEntity *ent;
#if CLIENT_DLL
if( bIsMultiplayer() )
#else
if( g_pGameRules->IsMultiplayer() ) if( g_pGameRules->IsMultiplayer() )
#endif
{ {
if( satchelfix.value )
{
if( !pOriginal->m_pPlayer )
return TRUE;
nNumSatchels = 0;
nSatchelsInPocket = pOriginal->m_pPlayer->m_rgAmmo[pOriginal->PrimaryAmmoIndex()];
ent = NULL;
while( ( ent = UTIL_FindEntityInSphere( ent, pOriginal->m_pPlayer->pev->origin, 4096 )) != NULL )
{
if( FClassnameIs( ent->pev, "monster_satchel" ))
nNumSatchels += ent->pev->owner == pOriginal->m_pPlayer->edict();
}
}
pSatchel = (CSatchel *)pOriginal; pSatchel = (CSatchel *)pOriginal;
if( pSatchel->m_chargeReady != SATCHEL_IDLE ) if( pSatchel->m_chargeReady != SATCHEL_IDLE
&& ( satchelfix.value && nSatchelsInPocket + nNumSatchels > SATCHEL_MAX_CARRY - 1 ))
{ {
// player has some satchels deployed. Refuse to add more. // player has some satchels deployed. Refuse to add more.
return FALSE; return FALSE;
} }
} }
#endif
return CBasePlayerWeapon::AddDuplicate( pOriginal ); return CBasePlayerWeapon::AddDuplicate( pOriginal );
} }
@ -330,8 +347,9 @@ void CSatchel::Holster( int skiplocal /* = 0 */ )
} }
} }
void CSatchel::PrimaryAttack() void CSatchel::PrimaryAttack( void )
{ {
#if SATCHEL_OLD_BEHAVIOUR
switch( m_chargeReady ) switch( m_chargeReady )
{ {
case SATCHEL_IDLE: case SATCHEL_IDLE:
@ -347,9 +365,9 @@ void CSatchel::PrimaryAttack()
CBaseEntity *pSatchel = NULL; CBaseEntity *pSatchel = NULL;
while( ( pSatchel = UTIL_FindEntityInSphere( pSatchel, m_pPlayer->pev->origin, 4096 ) ) != NULL ) while( ( pSatchel = UTIL_FindEntityInSphere( pSatchel, m_pPlayer->pev->origin, 4096 )) != NULL )
{ {
if( FClassnameIs( pSatchel->pev, "monster_satchel" ) ) if( FClassnameIs( pSatchel->pev, "monster_satchel" ))
{ {
if( pSatchel->pev->owner == pPlayer ) if( pSatchel->pev->owner == pPlayer )
{ {
@ -368,14 +386,56 @@ void CSatchel::PrimaryAttack()
// we're reloading, don't allow fire // we're reloading, don't allow fire
break; break;
} }
} #else
void CSatchel::SecondaryAttack( void )
{
if( m_chargeReady != SATCHEL_RELOAD ) if( m_chargeReady != SATCHEL_RELOAD )
{ {
Throw(); Throw();
} }
#endif
}
void CSatchel::SecondaryAttack( void )
{
#if SATCHEL_OLD_BEHAVIOUR
if( m_chargeReady != SATCHEL_RELOAD )
{
Throw();
}
#else
switch( m_chargeReady )
{
case SATCHEL_IDLE:
break;
case SATCHEL_READY:
{
SendWeaponAnim( SATCHEL_RADIO_FIRE );
edict_t *pPlayer = m_pPlayer->edict();
CBaseEntity *pSatchel = NULL;
while( ( pSatchel = UTIL_FindEntityInSphere( pSatchel, m_pPlayer->pev->origin, 4096 )) != NULL )
{
if( FClassnameIs( pSatchel->pev, "monster_satchel" ))
{
if( pSatchel->pev->owner == pPlayer )
{
pSatchel->Use( m_pPlayer, m_pPlayer, USE_ON, 0 );
}
}
}
m_chargeReady = SATCHEL_RELOAD;
m_flNextPrimaryAttack = GetNextAttackDelay( 0.5f );
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5f;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5f;
break;
}
case SATCHEL_RELOAD:
// we're reloading, don't allow fire
break;
}
#endif
} }
void CSatchel::Throw( void ) void CSatchel::Throw( void )

View File

@ -29,6 +29,8 @@
#define NUM_SCIENTIST_HEADS 4 // four heads available for scientist model #define NUM_SCIENTIST_HEADS 4 // four heads available for scientist model
static cvar_t *g_psv_override_scientist_mdl;
enum enum
{ {
HEAD_GLASSES = 0, HEAD_GLASSES = 0,
@ -113,6 +115,8 @@ public:
CUSTOM_SCHEDULES CUSTOM_SCHEDULES
private: private:
const char *GetScientistModel( void );
float m_painTime; float m_painTime;
float m_healTime; float m_healTime;
float m_fearTime; float m_fearTime;
@ -422,6 +426,20 @@ void CScientist::DeclineFollowing( void )
PlaySentence( "SC_POK", 2, VOL_NORM, ATTN_NORM ); PlaySentence( "SC_POK", 2, VOL_NORM, ATTN_NORM );
} }
const char *CScientist::GetScientistModel( void )
{
if( !g_psv_override_scientist_mdl )
g_psv_override_scientist_mdl = CVAR_GET_POINTER( "_sv_override_scientist_mdl" );
if( !( g_psv_override_scientist_mdl && g_psv_override_scientist_mdl->string ))
return "models/scientist.mdl";
if( strlen( g_psv_override_scientist_mdl->string ) < sizeof( "01.mdl" ) - 1 )
return "models/scientist.mdl";
return g_psv_override_scientist_mdl->string;
}
void CScientist::Scream( void ) void CScientist::Scream( void )
{ {
if( FOkToSpeak() ) if( FOkToSpeak() )
@ -648,7 +666,7 @@ void CScientist::Spawn( void )
Precache(); Precache();
SET_MODEL( ENT( pev ), "models/scientist.mdl" ); SET_MODEL( ENT( pev ), GetScientistModel());
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX ); UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
pev->solid = SOLID_SLIDEBOX; pev->solid = SOLID_SLIDEBOX;
@ -679,7 +697,7 @@ void CScientist::Spawn( void )
//========================================================= //=========================================================
void CScientist::Precache( void ) void CScientist::Precache( void )
{ {
PRECACHE_MODEL( "models/scientist.mdl" ); PRECACHE_MODEL( GetScientistModel());
PRECACHE_SOUND( "scientist/sci_pain1.wav" ); PRECACHE_SOUND( "scientist/sci_pain1.wav" );
PRECACHE_SOUND( "scientist/sci_pain2.wav" ); PRECACHE_SOUND( "scientist/sci_pain2.wav" );
PRECACHE_SOUND( "scientist/sci_pain3.wav" ); PRECACHE_SOUND( "scientist/sci_pain3.wav" );
@ -1097,6 +1115,9 @@ public:
void KeyValue( KeyValueData *pkvd ); void KeyValue( KeyValueData *pkvd );
int m_iPose;// which sequence to display int m_iPose;// which sequence to display
static const char *m_szPoses[7]; static const char *m_szPoses[7];
private:
const char *GetScientistModel( void );
}; };
const char *CDeadScientist::m_szPoses[] = const char *CDeadScientist::m_szPoses[] =
@ -1127,8 +1148,10 @@ LINK_ENTITY_TO_CLASS( monster_scientist_dead, CDeadScientist )
// //
void CDeadScientist::Spawn() void CDeadScientist::Spawn()
{ {
PRECACHE_MODEL( "models/scientist.mdl" ); const char *pszModel = GetScientistModel();
SET_MODEL( ENT( pev ), "models/scientist.mdl" );
PRECACHE_MODEL( pszModel );
SET_MODEL( ENT( pev ), pszModel );
pev->effects = 0; pev->effects = 0;
pev->sequence = 0; pev->sequence = 0;
@ -1160,6 +1183,20 @@ void CDeadScientist::Spawn()
MonsterInitDead(); MonsterInitDead();
} }
const char *CDeadScientist::GetScientistModel( void )
{
if( !g_psv_override_scientist_mdl )
g_psv_override_scientist_mdl = CVAR_GET_POINTER( "_sv_override_scientist_mdl" );
if( !( g_psv_override_scientist_mdl && g_psv_override_scientist_mdl->string ))
return "models/scientist.mdl";
if( strlen( g_psv_override_scientist_mdl->string ) < sizeof( "01.mdl" ) - 1 )
return "models/scientist.mdl";
return g_psv_override_scientist_mdl->string;
}
//========================================================= //=========================================================
// Sitting Scientist PROP // Sitting Scientist PROP
//========================================================= //=========================================================

View File

@ -902,9 +902,9 @@ public:
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
CBaseMonster *FindEntity( void ); CBaseToggle *FindEntity( void );
BOOL AcceptableSpeaker( CBaseMonster *pMonster ); BOOL AcceptableSpeaker( CBaseToggle *pTarget );
BOOL StartSentence( CBaseMonster *pTarget ); BOOL StartSentence( CBaseToggle *pTarget );
private: private:
string_t m_iszSentence; // string index for idle animation string_t m_iszSentence; // string index for idle animation
@ -1036,20 +1036,20 @@ void CScriptedSentence::Spawn( void )
void CScriptedSentence::FindThink( void ) void CScriptedSentence::FindThink( void )
{ {
CBaseMonster *pMonster = FindEntity(); CBaseToggle *pTarget = FindEntity();
if( pMonster ) if( pTarget )
{ {
StartSentence( pMonster ); StartSentence( pTarget );
if( pev->spawnflags & SF_SENTENCE_ONCE ) if( pev->spawnflags & SF_SENTENCE_ONCE )
UTIL_Remove( this ); UTIL_Remove( this );
SetThink( &CScriptedSentence::DelayThink ); SetThink( &CScriptedSentence::DelayThink );
pev->nextthink = gpGlobals->time + m_flDuration + m_flRepeat; pev->nextthink = gpGlobals->time + m_flDuration + m_flRepeat;
m_active = FALSE; m_active = FALSE;
//ALERT( at_console, "%s: found monster %s\n", STRING( m_iszSentence ), STRING( m_iszEntity ) ); //ALERT( at_console, "%s: found target %s\n", STRING( m_iszSentence ), STRING( m_iszEntity ) );
} }
else else
{ {
//ALERT( at_console, "%s: can't find monster %s\n", STRING( m_iszSentence ), STRING( m_iszEntity ) ); //ALERT( at_console, "%s: can't find target %s\n", STRING( m_iszSentence ), STRING( m_iszEntity ) );
pev->nextthink = gpGlobals->time + m_flRepeat + 0.5f; pev->nextthink = gpGlobals->time + m_flRepeat + 0.5f;
} }
} }
@ -1062,45 +1062,57 @@ void CScriptedSentence::DelayThink( void )
SetThink( &CScriptedSentence::FindThink ); SetThink( &CScriptedSentence::FindThink );
} }
BOOL CScriptedSentence::AcceptableSpeaker( CBaseMonster *pMonster ) BOOL CScriptedSentence::AcceptableSpeaker( CBaseToggle *pTarget )
{ {
if( pMonster ) CBaseMonster *pMonster;
EHANDLE hTarget;
if( pTarget )
{ {
if( pev->spawnflags & SF_SENTENCE_FOLLOWERS ) hTarget = pTarget->MyMonsterPointer();
if( hTarget != 0 )
{ {
if( pMonster->m_hTargetEnt == 0 || !pMonster->m_hTargetEnt->IsPlayer() ) CBaseMonster *pMonster = (CBaseMonster*)( (CBaseEntity*)hTarget );
return FALSE; if( pev->spawnflags & SF_SENTENCE_FOLLOWERS )
{
if( pMonster->m_hTargetEnt == 0 || !pMonster->m_hTargetEnt->IsPlayer() )
return FALSE;
}
BOOL override;
if( pev->spawnflags & SF_SENTENCE_INTERRUPT )
override = TRUE;
else
override = FALSE;
if( pMonster->CanPlaySentence( override ) )
return TRUE;
} }
BOOL override;
if( pev->spawnflags & SF_SENTENCE_INTERRUPT )
override = TRUE;
else else
override = FALSE; return pTarget->IsAllowedToSpeak();
if( pMonster->CanPlaySentence( override ) )
return TRUE;
} }
return FALSE; return FALSE;
} }
CBaseMonster *CScriptedSentence::FindEntity( void ) CBaseToggle *CScriptedSentence::FindEntity( void )
{ {
edict_t *pentTarget; edict_t *pentTarget;
CBaseMonster *pMonster; CBaseToggle *pTarget;
pentTarget = FIND_ENTITY_BY_TARGETNAME( NULL, STRING( m_iszEntity ) ); pentTarget = FIND_ENTITY_BY_TARGETNAME( NULL, STRING( m_iszEntity ) );
pMonster = NULL; pTarget = NULL;
while( !FNullEnt( pentTarget ) ) while( !FNullEnt( pentTarget ) )
{ {
pMonster = GetMonsterPointer( pentTarget ); pTarget = (CBaseToggle*)CBaseEntity::Instance( pentTarget );
if( pMonster != NULL ) if( pTarget != NULL )
{ {
if( AcceptableSpeaker( pMonster ) ) if( AcceptableSpeaker( pTarget ) )
return pMonster; return pTarget;
//ALERT( at_console, "%s (%s), not acceptable\n", STRING( pMonster->pev->classname ), STRING( pMonster->pev->targetname ) ); //ALERT( at_console, "%s (%s), not acceptable\n", STRING( pTarget->pev->classname ), STRING( pTarget->pev->targetname ) );
} }
pentTarget = FIND_ENTITY_BY_TARGETNAME( pentTarget, STRING( m_iszEntity ) ); pentTarget = FIND_ENTITY_BY_TARGETNAME( pentTarget, STRING( m_iszEntity ) );
} }
@ -1112,9 +1124,9 @@ CBaseMonster *CScriptedSentence::FindEntity( void )
{ {
if( FBitSet( pEntity->pev->flags, FL_MONSTER ) ) if( FBitSet( pEntity->pev->flags, FL_MONSTER ) )
{ {
pMonster = pEntity->MyMonsterPointer(); pTarget = pEntity->MyTogglePointer();
if( AcceptableSpeaker( pMonster ) ) if( AcceptableSpeaker( pTarget ) )
return pMonster; return pTarget;
} }
} }
} }
@ -1122,7 +1134,7 @@ CBaseMonster *CScriptedSentence::FindEntity( void )
return NULL; return NULL;
} }
BOOL CScriptedSentence::StartSentence( CBaseMonster *pTarget ) BOOL CScriptedSentence::StartSentence( CBaseToggle *pTarget )
{ {
if( !pTarget ) if( !pTarget )
{ {

View File

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

View File

@ -1341,6 +1341,15 @@ void SENTENCEG_Init()
g_engfuncs.pfnFreeFile( pMemFile ); g_engfuncs.pfnFreeFile( pMemFile );
if( gcallsentences > CVOXFILESENTENCEMAX_GOLDSOURCE_ANNIVERSARY_25 )
{
ALERT( at_warning, "NOTE: this mod might not work properly under GoldSource (post-anniversary update) engine: more than %d sentences\n", CVOXFILESENTENCEMAX_GOLDSOURCE_ANNIVERSARY_25 );
}
else if( gcallsentences > CVOXFILESENTENCEMAX_GOLDSOURCE_LEGACY )
{
ALERT( at_warning, "NOTE: this mod might not work properly under GoldSource (pre-anniversary update) engine: more than %d sentences\n", CVOXFILESENTENCEMAX_GOLDSOURCE_LEGACY );
}
fSentencesInit = TRUE; fSentencesInit = TRUE;
// init lru lists // init lru lists

View File

@ -349,7 +349,8 @@ void CSqueakGrenade::SuperBounceTouch( CBaseEntity *pOther )
// higher pitch as squeeker gets closer to detonation time // higher pitch as squeeker gets closer to detonation time
flpitch = 155.0f - 60.0f * ( ( m_flDie - gpGlobals->time ) / SQUEEK_DETONATE_DELAY ); flpitch = 155.0f - 60.0f * ( ( m_flDie - gpGlobals->time ) / SQUEEK_DETONATE_DELAY );
if( pOther->pev->takedamage && m_flNextAttack < gpGlobals->time ) if( !FBitSet( pOther->pev->flags, FL_WORLDBRUSH )
&& pOther->pev->takedamage && m_flNextAttack < gpGlobals->time )
{ {
// attack! // attack!
@ -504,20 +505,35 @@ void CSqueak::PrimaryAttack()
{ {
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] ) if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{ {
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
TraceResult tr; TraceResult tr;
Vector trace_origin; Vector trace_origin, forward;
float flVel;
UTIL_MakeVectors( Vector( 0, m_pPlayer->pev->v_angle.y, m_pPlayer->pev->v_angle.z ));
forward = gpGlobals->v_forward;
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
if( m_pPlayer->pev->v_angle.x <= 0 )
{
flVel = 1;
}
else
{
flVel = m_pPlayer->pev->v_angle.x / 90.0f;
}
// HACK HACK: Ugly hacks to handle change in origin based on new physics code for players // HACK HACK: Ugly hacks to handle change in origin based on new physics code for players
// Move origin up if crouched and start trace a bit outside of body ( 20 units instead of 16 ) // Move origin up if crouched and start trace a bit outside of body ( 20 units instead of 16 )
trace_origin = m_pPlayer->pev->origin; trace_origin = m_pPlayer->pev->origin;
if( m_pPlayer->pev->flags & FL_DUCKING ) if( m_pPlayer->pev->flags & FL_DUCKING )
{ {
trace_origin = trace_origin - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN ); trace_origin = trace_origin - Vector( 0, 0, 1 ) * ( flVel + 1.0f ) * -18;
} }
forward = forward * flVel + gpGlobals->v_forward * ( 1 - flVel );
// find place to toss monster // find place to toss monster
UTIL_TraceLine( trace_origin + gpGlobals->v_forward * 20.0f, trace_origin + gpGlobals->v_forward * 64.0f, dont_ignore_monsters, NULL, &tr ); UTIL_TraceLine( trace_origin + forward * 24.0f, trace_origin + gpGlobals->v_forward * 60.0f, dont_ignore_monsters, NULL, &tr );
int flags; int flags;
#if CLIENT_WEAPONS #if CLIENT_WEAPONS
@ -527,13 +543,13 @@ void CSqueak::PrimaryAttack()
#endif #endif
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0f, g_vecZero, g_vecZero, 0.0f, 0.0f, 0, 0, 0, 0 ); PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0f, g_vecZero, g_vecZero, 0.0f, 0.0f, 0, 0, 0, 0 );
if( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25f ) if( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0 )
{ {
// player "shoot" animation // player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
#if !CLIENT_DLL #if !CLIENT_DLL
CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict() ); CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pSqueak->pev->velocity = gpGlobals->v_forward * 200.0f + m_pPlayer->pev->velocity; pSqueak->pev->velocity = forward * 200.0f + m_pPlayer->pev->velocity;
#endif #endif
// play hunt sound // play hunt sound
float flRndSound = RANDOM_FLOAT( 0.0f, 1.0f ); float flRndSound = RANDOM_FLOAT( 0.0f, 1.0f );

View File

@ -520,6 +520,27 @@ float CBaseToggle::AxisDelta( int flags, const Vector &angle1, const Vector &ang
return angle1.y - angle2.y; return angle1.y - angle2.y;
} }
void CBaseToggle::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation )
{
if( pszSentence && IsAllowedToSpeak())
{
if( pszSentence[0] == '!' )
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, PITCH_NORM );
else
SENTENCEG_PlayRndSz( edict(), pszSentence, volume, attenuation, 0, PITCH_NORM );
}
}
void CBaseToggle::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener )
{
PlaySentence( pszSentence, duration, volume, attenuation );
}
void CBaseToggle::SentenceStop( void )
{
EMIT_SOUND( edict(), CHAN_VOICE, "common/null.wav", 1.0, ATTN_IDLE );
}
/* /*
============= =============
FEntIsVisible FEntIsVisible

View File

@ -791,7 +791,7 @@ CBaseEntity *CTalkMonster::FindNearestFriend( BOOL fPlayer )
// for each friend in this bsp... // for each friend in this bsp...
while( ( pFriend = UTIL_FindEntityByClassname( pFriend, pszFriend ) ) ) while( ( pFriend = UTIL_FindEntityByClassname( pFriend, pszFriend ) ) )
{ {
if( pFriend == this || !pFriend->IsAlive() ) if( pFriend == this || !pFriend->IsAlive() || pFriend->pev->deadflag != DEAD_NO )
// don't talk to self or dead people // don't talk to self or dead people
continue; continue;
@ -1344,7 +1344,7 @@ void CTalkMonster::StartFollowing( CBaseEntity *pLeader )
BOOL CTalkMonster::CanFollow( void ) BOOL CTalkMonster::CanFollow( void )
{ {
if( m_MonsterState == MONSTERSTATE_SCRIPT ) if( m_MonsterState == MONSTERSTATE_SCRIPT || m_IdealMonsterState == MONSTERSTATE_SCRIPT )
{ {
if( !m_pCine ) if( !m_pCine )
return FALSE; return FALSE;

View File

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

View File

@ -994,7 +994,12 @@ void CBaseTrigger::HurtTouch( CBaseEntity *pOther )
} }
#endif #endif
if( fldmg < 0 ) if( fldmg < 0 )
pOther->TakeHealth( -fldmg, m_bitsDamageInflict ); {
if( !( g_pGameRules->IsMultiplayer()
&& pOther->IsPlayer()
&& pOther->pev->deadflag ))
pOther->TakeHealth( -fldmg, m_bitsDamageInflict );
}
else else
pOther->TakeDamage( pev, pev, fldmg, m_bitsDamageInflict ); pOther->TakeDamage( pev, pev, fldmg, m_bitsDamageInflict );

View File

@ -1100,9 +1100,6 @@ void UTIL_BloodStream( const Vector &origin, const Vector &direction, int color,
if( !UTIL_ShouldShowBlood( color ) ) if( !UTIL_ShouldShowBlood( color ) )
return; return;
if( g_Language == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED )
color = 0;
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, origin ); MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, origin );
WRITE_BYTE( TE_BLOODSTREAM ); WRITE_BYTE( TE_BLOODSTREAM );
WRITE_COORD( origin.x ); WRITE_COORD( origin.x );
@ -1124,9 +1121,6 @@ void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color,
if( color == DONT_BLEED || amount == 0 ) if( color == DONT_BLEED || amount == 0 )
return; return;
if( g_Language == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED )
color = 0;
if( g_pGameRules->IsMultiplayer() ) if( g_pGameRules->IsMultiplayer() )
{ {
// scale up blood effect in multiplayer for better visibility // scale up blood effect in multiplayer for better visibility
@ -1729,26 +1723,11 @@ void CSaveRestoreBuffer::BufferRewind( int size )
m_pdata->size -= size; m_pdata->size -= size;
} }
#if !_WIN32 && !__WATCOMC__ #if !XASH_WIN32 && !__WATCOMC__
extern "C" { static unsigned _rotr( unsigned val, int shift )
unsigned _rotr( unsigned val, int shift )
{ {
unsigned lobit; /* non-zero means lo bit set */ // Any modern compiler will generate one single ror instruction for x86, arm and mips here.
unsigned num = val; /* number to rotate */ return ( val >> shift ) | ( val << ( 32 - shift ));
shift &= 0x1f; /* modulo 32 -- this will also make
negative shifts work */
while( shift-- )
{
lobit = num & 1; /* get high bit */
num >>= 1; /* shift right one bit */
if( lobit )
num |= 0x80000000; /* set hi bit if lo bit was set */
}
return num;
}
} }
#endif #endif
@ -2238,7 +2217,7 @@ int CRestore::ReadField( void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCou
break; break;
case FIELD_EHANDLE: case FIELD_EHANDLE:
// Input and Output sizes are different! // Input and Output sizes are different!
pOutputData = (char *)pOutputData + j * ( sizeof(EHANDLE) - gSizes[pTest->fieldType] ); pInputData = (char*)pData + j * gSizes[pTest->fieldType];
entityIndex = *(int *)pInputData; entityIndex = *(int *)pInputData;
pent = EntityFromIndex( entityIndex ); pent = EntityFromIndex( entityIndex );
if( pent ) if( pent )

View File

@ -407,18 +407,6 @@ void DBG_AssertFunction(BOOL fExpr, const char* szExpr, const char* szFile, int
extern DLL_GLOBAL const Vector g_vecZero; extern DLL_GLOBAL const Vector g_vecZero;
//
// Constants that were used only by QC (maybe not used at all now)
//
// Un-comment only as needed
//
#define LANGUAGE_ENGLISH 0
#define LANGUAGE_GERMAN 1
#define LANGUAGE_FRENCH 2
#define LANGUAGE_BRITISH 3
extern DLL_GLOBAL int g_Language;
#define AMBIENT_SOUND_STATIC 0 // medium radius attenuation #define AMBIENT_SOUND_STATIC 0 // medium radius attenuation
#define AMBIENT_SOUND_EVERYWHERE 1 #define AMBIENT_SOUND_EVERYWHERE 1
#define AMBIENT_SOUND_SMALLRADIUS 2 #define AMBIENT_SOUND_SMALLRADIUS 2
@ -508,7 +496,11 @@ void UTIL_SendDirectorMessage( edict_t *ent1, edict_t *ent2, int priority_and_fl
// sentence groups // sentence groups
#define CBSENTENCENAME_MAX 16 #define CBSENTENCENAME_MAX 16
#define CVOXFILESENTENCEMAX 1536 // max number of sentences in game. NOTE: this must match
#define CVOXFILESENTENCEMAX_GOLDSOURCE_LEGACY 1536
#define CVOXFILESENTENCEMAX_GOLDSOURCE_ANNIVERSARY_25 2048
#define CVOXFILESENTENCEMAX_XASH3D 4096
#define CVOXFILESENTENCEMAX CVOXFILESENTENCEMAX_XASH3D // max number of sentences in game. NOTE: this must match
// CVOXFILESENTENCEMAX in engine\sound.h!!! // CVOXFILESENTENCEMAX in engine\sound.h!!!
extern char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX]; extern char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX];

996
dlls/vehicle.cpp Normal file
View File

@ -0,0 +1,996 @@
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "trains.h"
#include "saverestore.h"
#define VEHICLE_SPEED0_ACCELERATION 0.005000000000000000
#define VEHICLE_SPEED1_ACCELERATION 0.002142857142857143
#define VEHICLE_SPEED2_ACCELERATION 0.003333333333333334
#define VEHICLE_SPEED3_ACCELERATION 0.004166666666666667
#define VEHICLE_SPEED4_ACCELERATION 0.004000000000000000
#define VEHICLE_SPEED5_ACCELERATION 0.003800000000000000
#define VEHICLE_SPEED6_ACCELERATION 0.004500000000000000
#define VEHICLE_SPEED7_ACCELERATION 0.004250000000000000
#define VEHICLE_SPEED8_ACCELERATION 0.002666666666666667
#define VEHICLE_SPEED9_ACCELERATION 0.002285714285714286
#define VEHICLE_SPEED10_ACCELERATION 0.001875000000000000
#define VEHICLE_SPEED11_ACCELERATION 0.001444444444444444
#define VEHICLE_SPEED12_ACCELERATION 0.001200000000000000
#define VEHICLE_SPEED13_ACCELERATION 0.000916666666666666
#define VEHICLE_STARTPITCH 60
#define VEHICLE_MAXPITCH 200
#define VEHICLE_MAXSPEED 1500
TYPEDESCRIPTION CFuncVehicle::m_SaveData[] =
{
DEFINE_FIELD( CFuncVehicle, m_ppath, FIELD_CLASSPTR ),
DEFINE_FIELD( CFuncVehicle, m_length, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_height, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_speed, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_dir, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_startSpeed, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_controlMins, FIELD_VECTOR ),
DEFINE_FIELD( CFuncVehicle, m_controlMaxs, FIELD_VECTOR ),
DEFINE_FIELD( CFuncVehicle, m_sounds, FIELD_INTEGER ),
DEFINE_FIELD( CFuncVehicle, m_flVolume, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_flBank, FIELD_FLOAT ),
DEFINE_FIELD( CFuncVehicle, m_oldSpeed, FIELD_FLOAT ),
};
static float Fix2( float angle )
{
while( angle < 0 )
angle += 360;
while( angle > 360 )
angle -= 360;
return angle;
}
static void FixupAngles2( Vector &v )
{
v.x = Fix2( v.x );
v.y = Fix2( v.y );
v.z = Fix2( v.z );
}
IMPLEMENT_SAVERESTORE( CFuncVehicle, CBaseEntity )
LINK_ENTITY_TO_CLASS( func_vehicle, CFuncVehicle )
void CFuncVehicle::KeyValue( KeyValueData *pkvd )
{
if( FStrEq( pkvd->szKeyName, "length" ))
{
m_length = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "width" ))
{
m_width = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "height" ))
{
m_height = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "startspeed" ))
{
m_startSpeed = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "sounds" ))
{
m_sounds = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "volume" ))
{
m_flVolume = (float)atoi( pkvd->szValue );
m_flVolume *= 0.1f;
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "bank" ))
{
m_flBank = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "acceleration" ))
{
m_acceleration = atoi( pkvd->szValue );
if( m_acceleration < 1 )
m_acceleration = 1;
else if( m_acceleration > 10 )
m_acceleration = 10;
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
void CFuncVehicle::NextThink( float thinkTime, BOOL alwaysThink )
{
if( alwaysThink )
pev->flags |= FL_ALWAYSTHINK;
else
pev->flags &= ~FL_ALWAYSTHINK;
pev->nextthink = thinkTime;
}
void CFuncVehicle::Blocked( CBaseEntity *pOther )
{
entvars_t *pevOther = pOther->pev;
if( ( pevOther->flags & FL_ONGROUND ) && VARS( pevOther->groundentity ) == pev )
{
pevOther->velocity = pev->velocity;
return;
}
pevOther->velocity = ( pevOther->origin - pev->origin ).Normalize() * pev->dmg;
pevOther->velocity.z += 300;
pev->velocity = pev->velocity * 0.85f;
ALERT( at_aiconsole, "TRAIN(%s): Blocked by %s (dmg:%.2f)\n", STRING( pev->targetname ), STRING( pOther->pev->classname ), pev->dmg );
UTIL_MakeVectors( pev->angles );
Vector forward, right, vOrigin;
Vector vFrontLeft = ( gpGlobals->v_forward * -1 ) * ( m_length * 0.5f );
Vector vFrontRight = ( gpGlobals->v_right * -1 ) * ( m_width * 0.5f );
Vector vBackLeft = pev->origin + vFrontLeft - vFrontRight;
Vector vBackRight = pev->origin - vFrontLeft + vFrontRight;
float minx = Q_min( vBackLeft.x, vBackRight.x );
float miny = Q_min( vBackLeft.y, vBackRight.y );
float maxx = Q_max( vBackLeft.x, vBackRight.x );
float maxy = Q_max( vBackLeft.y, vBackRight.y );
float minz = pev->origin.z;
float maxz = pev->origin.z + ( 2 * abs( (int)( pev->mins.z - pev->maxs.z )));
if ( pOther->pev->origin.x < minx
|| pOther->pev->origin.x > maxx
|| pOther->pev->origin.y < miny
|| pOther->pev->origin.y > maxy
|| pOther->pev->origin.z < pev->origin.z
|| pOther->pev->origin.z > maxz )
{
pOther->TakeDamage( pev, pev, 150, DMG_CRUSH );
}
}
void CFuncVehicle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
float delta = value;
if( useType != USE_SET )
{
if( ShouldToggle( useType, pev->speed != 0 ))
{
if( pev->speed == 0 )
{
pev->speed = m_dir * m_speed;
Next();
}
else
{
pev->speed = 0;
pev->velocity = g_vecZero;
pev->avelocity = g_vecZero;
StopSound();
SetThink( NULL );
}
}
return;
}
if( delta < 10 )
{
if( delta < 0 )
{
if( pev->speed > 145 )
{
StopSound();
}
}
float flSpeedRatio = delta;
if( delta > 0 )
{
flSpeedRatio = (float)( pev->speed / m_speed );
if( pev->speed < 0 ) flSpeedRatio = m_acceleration * 0.0005 + flSpeedRatio + VEHICLE_SPEED0_ACCELERATION;
else if( pev->speed < 10 ) flSpeedRatio = m_acceleration * 0.0006 + flSpeedRatio + VEHICLE_SPEED1_ACCELERATION;
else if( pev->speed < 20 ) flSpeedRatio = m_acceleration * 0.0007 + flSpeedRatio + VEHICLE_SPEED2_ACCELERATION;
else if( pev->speed < 30 ) flSpeedRatio = m_acceleration * 0.0007 + flSpeedRatio + VEHICLE_SPEED3_ACCELERATION;
else if( pev->speed < 45 ) flSpeedRatio = m_acceleration * 0.0007 + flSpeedRatio + VEHICLE_SPEED4_ACCELERATION;
else if( pev->speed < 60 ) flSpeedRatio = m_acceleration * 0.0008 + flSpeedRatio + VEHICLE_SPEED5_ACCELERATION;
else if( pev->speed < 80 ) flSpeedRatio = m_acceleration * 0.0008 + flSpeedRatio + VEHICLE_SPEED6_ACCELERATION;
else if( pev->speed < 100 ) flSpeedRatio = m_acceleration * 0.0009 + flSpeedRatio + VEHICLE_SPEED7_ACCELERATION;
else if( pev->speed < 150 ) flSpeedRatio = m_acceleration * 0.0008 + flSpeedRatio + VEHICLE_SPEED8_ACCELERATION;
else if( pev->speed < 225 ) flSpeedRatio = m_acceleration * 0.0007 + flSpeedRatio + VEHICLE_SPEED9_ACCELERATION;
else if( pev->speed < 300 ) flSpeedRatio = m_acceleration * 0.0006 + flSpeedRatio + VEHICLE_SPEED10_ACCELERATION;
else if( pev->speed < 400 ) flSpeedRatio = m_acceleration * 0.0005 + flSpeedRatio + VEHICLE_SPEED11_ACCELERATION;
else if( pev->speed < 550 ) flSpeedRatio = m_acceleration * 0.0005 + flSpeedRatio + VEHICLE_SPEED12_ACCELERATION;
else if( pev->speed < 800 ) flSpeedRatio = m_acceleration * 0.0005 + flSpeedRatio + VEHICLE_SPEED13_ACCELERATION;
}
else if( delta < 0 )
{
flSpeedRatio = pev->speed / m_speed;
// TODO: fix float for test demo
if( flSpeedRatio > 0 ) flSpeedRatio = (float)flSpeedRatio - 0.0125f;
else if( flSpeedRatio <= 0 && flSpeedRatio > -0.05f ) flSpeedRatio = (float)flSpeedRatio - 0.0075f;
else if( flSpeedRatio <= 0.05f && flSpeedRatio > -0.1f ) flSpeedRatio = (float)flSpeedRatio - 0.01f;
else if( flSpeedRatio <= 0.15f && flSpeedRatio > -0.15f ) flSpeedRatio = (float)flSpeedRatio - 0.0125f;
else if( flSpeedRatio <= 0.15f && flSpeedRatio > -0.22f ) flSpeedRatio = (float)flSpeedRatio - 0.01375f;
else if( flSpeedRatio <= 0.22f && flSpeedRatio > -0.3f ) flSpeedRatio = (float)flSpeedRatio - 0.0175f;
else if( flSpeedRatio <= 0.3f ) flSpeedRatio = (float)flSpeedRatio - 0.0125f;
}
if( flSpeedRatio > 1 )
{
flSpeedRatio = 1;
}
else if( flSpeedRatio < -0.35f )
{
flSpeedRatio = -0.35f;
}
pev->speed = flSpeedRatio * m_speed;
Next();
m_flAcceleratorDecay = gpGlobals->time + 0.25f;
}
else if( m_flCanTurnNow < gpGlobals->time )
{
if( delta == 20 )
{
m_iTurnAngle++;
m_flSteeringWheelDecay = gpGlobals->time + 0.075f;
if (m_iTurnAngle > 8)
{
m_iTurnAngle = 8;
}
}
else if( delta == 30 )
{
m_iTurnAngle--;
m_flSteeringWheelDecay = gpGlobals->time + 0.075f;
if( m_iTurnAngle < -8 )
{
m_iTurnAngle = -8;
}
}
m_flCanTurnNow = gpGlobals->time + 0.05f;
}
}
void CFuncVehicle::StopSound()
{
if( m_soundPlaying && pev->noise )
{
unsigned short us_sound = ( (unsigned short)m_sounds & 0x0007 ) << 12;
unsigned short us_encode = us_sound;
PLAYBACK_EVENT_FULL( FEV_RELIABLE | FEV_UPDATE, edict(), m_usAdjustPitch, 0, g_vecZero, g_vecZero, 0, 0, us_encode, 0, 1, 0 );
}
m_soundPlaying = 0;
}
void CFuncVehicle::UpdateSound()
{
if( !pev->noise )
return;
float flpitch = VEHICLE_STARTPITCH + ( abs( (int)pev->speed ) * ( VEHICLE_MAXPITCH - VEHICLE_STARTPITCH ) / VEHICLE_MAXSPEED );
if( flpitch > 200 )
flpitch = 200;
if( !m_soundPlaying )
{
if( m_sounds < 5 )
{
EMIT_SOUND_DYN( ENT(pev), CHAN_ITEM, "plats/vehicle_brake1.wav", m_flVolume, ATTN_NORM, 0, PITCH_NORM );
}
EMIT_SOUND_DYN( ENT( pev ), CHAN_STATIC, STRING( pev->noise ), m_flVolume, ATTN_NORM, 0, (int)flpitch );
m_soundPlaying = 1;
}
else
{
unsigned short us_sound = ( (unsigned short)( m_sounds ) & 0x0007 ) << 12;
unsigned short us_pitch = ( (unsigned short)( flpitch / 10.0 ) & 0x003F ) << 6;
unsigned short us_volume = ( (unsigned short)( m_flVolume * 40 ) & 0x003F );
unsigned short us_encode = us_sound | us_pitch | us_volume;
PLAYBACK_EVENT_FULL( FEV_UPDATE, edict(), m_usAdjustPitch, 0.0, g_vecZero, g_vecZero, 0.0, 0.0, us_encode, 0, 0, 0 );
}
}
void CFuncVehicle::CheckTurning()
{
float maxspeed;
TraceResult tr;
bool bTurnIntoWall = false;
if( m_iTurnAngle < 0 )
{
if( pev->speed > 0 )
{
UTIL_TraceLine( m_vFrontRight, m_vFrontRight - ( gpGlobals->v_right * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
}
else if( pev->speed < 0 )
{
UTIL_TraceLine( m_vBackLeft, m_vBackLeft + ( gpGlobals->v_right * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
}
if( tr.flFraction != 1.0f )
{
m_iTurnAngle = 1;
}
}
else if( m_iTurnAngle > 0 )
{
if( pev->speed > 0 )
{
UTIL_TraceLine( m_vFrontLeft, m_vFrontLeft + ( gpGlobals->v_right * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
}
else if( pev->speed < 0 )
{
UTIL_TraceLine( m_vBackRight, m_vBackRight - ( gpGlobals->v_right * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
}
if( tr.flFraction != 1.0f )
{
m_iTurnAngle = -1;
}
}
if( pev->speed > 0 )
{
int iCountTurn = abs( m_iTurnAngle );
if( iCountTurn > 4 )
{
if ( m_flTurnStartTime != -1 )
{
float flTurnTime = gpGlobals->time - m_flTurnStartTime;
if( flTurnTime >= 0 ) maxspeed = m_speed * 0.98f;
else if( flTurnTime > 0.3f ) maxspeed = m_speed * 0.95f;
else if( flTurnTime > 0.6f ) maxspeed = m_speed * 0.9f;
else if( flTurnTime > 0.8f ) maxspeed = m_speed * 0.8f;
else if( flTurnTime > 1 ) maxspeed = m_speed * 0.7f;
else if( flTurnTime > 1.2f ) maxspeed = m_speed * 0.5f;
else maxspeed = flTurnTime;
}
else
{
m_flTurnStartTime = gpGlobals->time;
maxspeed = m_speed;
}
}
else
{
m_flTurnStartTime = -1;
if( iCountTurn > 2 )
maxspeed = m_speed * 0.9f;
else
maxspeed = m_speed;
}
if( maxspeed < pev->speed )
{
pev->speed -= m_speed * 0.1f;
}
}
}
void CFuncVehicle::CollisionDetection()
{
TraceResult tr;
bool bHitSomething = false;
if( pev->speed < 0 )
{
UTIL_TraceLine( m_vBackLeft, m_vBackLeft + ( gpGlobals->v_forward * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction == 1.0f )
{
UTIL_TraceLine( m_vBackRight, m_vBackRight + ( gpGlobals->v_forward * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction == 1.0f )
{
UTIL_TraceLine( m_vBack, m_vBack + ( gpGlobals->v_forward * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction == 1.0f )
{
return;
}
}
if( DotProduct( gpGlobals->v_forward, tr.vecPlaneNormal * -1.0f ) < 0.7f && tr.vecPlaneNormal.z < 0.1f )
{
m_vSurfaceNormal = tr.vecPlaneNormal;
m_vSurfaceNormal.z = 0;
pev->speed *= 0.99f;
}
else if( tr.vecPlaneNormal.z < 0.65f || tr.fStartSolid )
{
pev->speed *= -1.0f;
}
else
{
m_vSurfaceNormal = tr.vecPlaneNormal;
}
}
else
{
if( DotProduct( gpGlobals->v_forward, tr.vecPlaneNormal * -1.0f ) < 0.7f && tr.vecPlaneNormal.z < 0.1f )
{
m_vSurfaceNormal = tr.vecPlaneNormal;
m_vSurfaceNormal.z = 0;
pev->speed *= 0.99f;
}
else if( tr.vecPlaneNormal[2] < 0.65f || tr.fStartSolid )
{
pev->speed *= -1.0f;
}
else
{
m_vSurfaceNormal = tr.vecPlaneNormal;
}
CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit );
if( pHit && pHit->Classify() == CLASS_VEHICLE )
{
bHitSomething = true;
ALERT( at_console, "I hit another vehicle\n" );
}
}
}
else if( pev->speed > 0 )
{
UTIL_TraceLine( m_vFrontLeft, m_vFrontLeft - ( gpGlobals->v_forward * 16.0f ), dont_ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction == 1.0f )
{
UTIL_TraceLine( m_vFrontRight, m_vFrontRight - ( gpGlobals->v_forward * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction == 1.0f )
{
UTIL_TraceLine( m_vFront, m_vFront - ( gpGlobals->v_forward * 16.0f ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction == 1.0f )
{
return;
}
}
}
if( DotProduct( gpGlobals->v_forward, tr.vecPlaneNormal * -1.0f ) > -0.7f && tr.vecPlaneNormal.z < 0.1f )
{
m_vSurfaceNormal = tr.vecPlaneNormal;
m_vSurfaceNormal.z = 0;
pev->speed *= 0.99f;
}
else if( tr.vecPlaneNormal.z < 0.65f || tr.fStartSolid )
{
pev->speed *= -1.0f;
}
else
{
m_vSurfaceNormal = tr.vecPlaneNormal;
}
}
}
void CFuncVehicle::TerrainFollowing()
{
TraceResult tr;
UTIL_TraceLine( pev->origin, pev->origin + Vector( 0, 0, ( m_height + 48 ) * -1 ), ignore_monsters, dont_ignore_glass, ENT( pev ), &tr );
if( tr.flFraction != 1.0f )
{
m_vSurfaceNormal = tr.vecPlaneNormal;
}
else if( tr.fInWater )
{
m_vSurfaceNormal = Vector( 0, 0, 1 );
}
}
void CFuncVehicle::Next()
{
Vector vGravityVector, forward, right, up;
float time = 0.1f;
vGravityVector = g_vecZero;
UTIL_MakeVectors( pev->angles );
forward = ( gpGlobals->v_forward * -1 ) * ( m_length * 0.5f );
right = ( gpGlobals->v_right * -1 ) * ( m_width * 0.5f );
up = gpGlobals->v_up * 16;
m_vFrontLeft = pev->origin + forward - right + up;
m_vFrontRight = pev->origin + forward + right + up;
m_vFront = pev->origin + forward + up;
m_vBackLeft = pev->origin - forward - right + up;
m_vBackRight = pev->origin - forward + right + up;
m_vBack = pev->origin - forward + up;
m_vSurfaceNormal = g_vecZero;
CheckTurning();
if( m_flSteeringWheelDecay < gpGlobals->time )
{
m_flSteeringWheelDecay = gpGlobals->time + 0.1f;
if( m_iTurnAngle < 0 )
m_iTurnAngle++;
else if( m_iTurnAngle > 0 )
m_iTurnAngle--;
}
if( m_flAcceleratorDecay < gpGlobals->time )
{
m_flAcceleratorDecay = gpGlobals->time + 0.1f;
if( pev->speed < 0 )
{
pev->speed += 20;
if( pev->speed > 0 )
pev->speed = 0;
}
else if( pev->speed > 0 )
{
pev->speed -= 20;
if( pev->speed < 0 )
pev->speed = 0;
}
}
if( pev->speed == 0 )
{
m_iTurnAngle = 0;
pev->avelocity = g_vecZero;
pev->velocity = g_vecZero;
SetThink( &CFuncVehicle::Next );
NextThink( pev->ltime + time, TRUE );
return;
}
TerrainFollowing();
CollisionDetection();
Vector temp;
if( m_vSurfaceNormal != g_vecZero )
{
Vector vTargetAngle, vAngle;
float vx;
float vy;
m_vVehicleDirection = CrossProduct( m_vSurfaceNormal, gpGlobals->v_forward );
m_vVehicleDirection = CrossProduct( m_vSurfaceNormal, m_vVehicleDirection );
vTargetAngle = UTIL_VecToAngles( m_vVehicleDirection );
vAngle = pev->angles;
vTargetAngle.y += 180;
if( m_iTurnAngle != 0 )
{
vTargetAngle.y += m_iTurnAngle;
}
FixupAngles2( vTargetAngle );
FixupAngles2( vAngle );
vx = UTIL_AngleDistance( vTargetAngle.x, vAngle.x );
vy = UTIL_AngleDistance( vTargetAngle.y, vAngle.y );
if( vx > 10 )
vx = 10;
else if( vx < -10 )
vx = -10;
if( vy > 10 )
vy = 10;
else if( vy < -10 )
vy = -10;
pev->avelocity.y = (int)( vy * 10 );
pev->avelocity.x = (int)( vx * 10 );
m_flLaunchTime = -1;
m_flLastNormalZ = m_vSurfaceNormal.z;
}
else
{
if( m_flLaunchTime != -1 )
{
vGravityVector.x = 0;
vGravityVector.y = 0;
vGravityVector.z = ( gpGlobals->time - m_flLaunchTime ) * -35;
if( vGravityVector.z < -400 )
{
vGravityVector.z = -400;
}
}
else
{
m_flLaunchTime = gpGlobals->time;
vGravityVector = Vector( 0, 0, 0 );
pev->velocity = pev->velocity * 1.5f;
}
m_vVehicleDirection = gpGlobals->v_forward * -1;
}
UTIL_VecToAngles( m_vVehicleDirection );
if( m_flUpdateSound < gpGlobals->time )
{
UpdateSound();
m_flUpdateSound = gpGlobals->time + 1.0f;
}
if( m_vSurfaceNormal != g_vecZero )
{
pev->velocity = m_vVehicleDirection.Normalize() * pev->speed;
}
else
{
pev->velocity = pev->velocity + vGravityVector;
}
SetThink( &CFuncVehicle::Next );
NextThink( pev->ltime + time, TRUE );
}
void CFuncVehicle::DeadEnd()
{
CPathTrack *pTrack = m_ppath;
ALERT( at_aiconsole, "TRAIN(%s): Dead end ", STRING( pev->targetname ));
if( pTrack != NULL )
{
CPathTrack *pNext;
if( m_oldSpeed < 0 )
{
do
{
pNext = pTrack->ValidPath( pTrack->GetPrevious(), TRUE );
if( pNext != NULL )
{
pTrack = pNext;
}
}
while( pNext != NULL );
}
else
{
do
{
pNext = pTrack->ValidPath( pTrack->GetNext(), TRUE );
if( pNext != NULL )
{
pTrack = pNext;
}
}
while( pNext != NULL );
}
}
pev->velocity = g_vecZero;
pev->avelocity = g_vecZero;
if( pTrack != NULL )
{
ALERT( at_aiconsole, "at %s\n", STRING( pTrack->pev->targetname ));
if( !FStringNull( pTrack->pev->netname ))
{
FireTargets( STRING( pTrack->pev->netname ), this, this, USE_TOGGLE, 0 );
}
}
else
ALERT( at_aiconsole, "\n" );
}
void CFuncVehicle::SetControls(entvars_t *pevControls)
{
Vector offset = pevControls->origin - pev->oldorigin;
m_controlMins = pevControls->mins + offset;
m_controlMaxs = pevControls->maxs + offset;
}
BOOL CFuncVehicle::OnControls(entvars_t *pevTest)
{
if( pev->spawnflags & SF_TRACKTRAIN_NOCONTROL )
return FALSE;
Vector offset = pevTest->origin - pev->origin;
UTIL_MakeVectors( pev->angles );
Vector local;
local.x = DotProduct( offset, gpGlobals->v_forward );
local.y = -DotProduct( offset, gpGlobals->v_right );
local.z = DotProduct( offset, gpGlobals->v_up );
return ( local.x >= m_controlMins.x && local.y >= m_controlMins.y && local.z >= m_controlMins.z
&& local.x <= m_controlMaxs.x && local.y <= m_controlMaxs.y && local.z <= m_controlMaxs.z );
}
void CFuncVehicle::Find()
{
m_ppath = CPathTrack::Instance( FIND_ENTITY_BY_TARGETNAME( NULL, STRING( pev->target )));
if( !m_ppath )
return;
entvars_t *pevTarget = m_ppath->pev;
if( !FClassnameIs( pevTarget, "path_track" ))
{
ALERT( at_error, "func_track_train must be on a path of path_track\n" );
m_ppath = NULL;
return;
}
Vector nextPos = pevTarget->origin;
nextPos.z += m_height;
Vector look = nextPos;
look.z -= m_height;
m_ppath->LookAhead( &look, m_length, 0 );
look.z += m_height;
pev->angles = UTIL_VecToAngles( look - nextPos );
pev->angles.y += 180;
if( pev->spawnflags & SF_TRACKTRAIN_NOPITCH )
{
pev->angles.x = 0;
}
UTIL_SetOrigin( pev, nextPos );
NextThink( pev->ltime + 0.1f, FALSE );
SetThink( &CFuncVehicle::Next );
pev->speed = m_startSpeed;
UpdateSound();
}
void CFuncVehicle::NearestPath()
{
CBaseEntity *pTrack = NULL;
CBaseEntity *pNearest = NULL;
float dist;
float closest = 1024;
while( ( pTrack = UTIL_FindEntityInSphere( pTrack, pev->origin, 1024 )) != NULL )
{
if( !( pTrack->pev->flags & ( FL_CLIENT | FL_MONSTER )) && FClassnameIs( pTrack->pev, "path_track" ))
{
dist = ( pev->origin - pTrack->pev->origin ).Length();
if( dist < closest )
{
closest = dist;
pNearest = pTrack;
}
}
}
if( !pNearest )
{
ALERT( at_console, "Can't find a nearby track !!!\n" );
SetThink( NULL );
return;
}
ALERT( at_aiconsole, "TRAIN: %s, Nearest track is %s\n", STRING( pev->targetname ), STRING( pNearest->pev->targetname ));
pTrack = ( (CPathTrack *)pNearest )->GetNext();
if( pTrack != NULL )
{
if( ( pev->origin - pTrack->pev->origin ).Length() < ( pev->origin - pNearest->pev->origin ).Length())
{
pNearest = pTrack;
}
}
m_ppath = (CPathTrack *)pNearest;
if( pev->speed != 0 )
{
NextThink( pev->ltime + 0.1f, FALSE );
SetThink( &CFuncVehicle::Next );
}
}
void CFuncVehicle::OverrideReset()
{
NextThink( pev->ltime + 0.1f, FALSE );
SetThink( &CFuncVehicle::NearestPath );
}
CFuncVehicle *CFuncVehicle::Instance(edict_t *pent)
{
if( FClassnameIs( pent, "func_vehicle" ))
{
return (CFuncVehicle *)GET_PRIVATE( pent );
}
return NULL;
}
int CFuncVehicle::Classify()
{
return CLASS_VEHICLE;
}
void CFuncVehicle::Spawn()
{
if( pev->speed == 0 )
m_speed = 165;
else
m_speed = pev->speed;
if( !m_sounds )
m_sounds = 3;
ALERT( at_console, "M_speed = %f\n", m_speed );
pev->speed = 0;
pev->velocity = g_vecZero;
pev->avelocity = g_vecZero;
pev->impulse = (int)m_speed;
m_acceleration = 5;
m_dir = 1;
m_flTurnStartTime = -1;
if( FStringNull( pev->target ))
{
ALERT( at_console, "Vehicle with no target" );
}
if( pev->spawnflags & SF_TRACKTRAIN_PASSABLE )
pev->solid = SOLID_NOT;
else
pev->solid = SOLID_BSP;
pev->movetype = MOVETYPE_PUSH;
SET_MODEL( ENT( pev ), STRING(pev->model ));
UTIL_SetSize( pev, pev->mins, pev->maxs );
UTIL_SetOrigin( pev, pev->origin );
pev->oldorigin = pev->origin;
m_controlMins = pev->mins;
m_controlMaxs = pev->maxs;
m_controlMaxs.z += 72;
NextThink( pev->ltime + 0.1f, FALSE );
SetThink( &CFuncVehicle::Find );
Precache();
}
void CFuncVehicle::Restart()
{
ALERT( at_console, "M_speed = %f\n", m_speed );
pev->speed = 0;
pev->velocity = g_vecZero;
pev->avelocity = g_vecZero;
pev->impulse = (int)m_speed;
m_flTurnStartTime = -1;
m_flUpdateSound = -1;
m_dir = 1;
m_pDriver = NULL;
if( FStringNull( pev->target ))
{
ALERT( at_console, "Vehicle with no target" );
}
UTIL_SetOrigin( pev, pev->oldorigin );
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noise ));
NextThink( pev->ltime + 0.1f, FALSE );
SetThink( &CFuncVehicle::Find );
}
void CFuncVehicle::Precache()
{
if( m_flVolume == 0.0f )
m_flVolume = 1.0f;
switch( m_sounds )
{
case 1: PRECACHE_SOUND( "plats/vehicle1.wav" );pev->noise = MAKE_STRING( "plats/vehicle1.wav" ); break;
case 2: PRECACHE_SOUND( "plats/vehicle2.wav" );pev->noise = MAKE_STRING( "plats/vehicle2.wav" ); break;
case 3: PRECACHE_SOUND( "plats/vehicle3.wav" );pev->noise = MAKE_STRING( "plats/vehicle3.wav" ); break;
case 4: PRECACHE_SOUND( "plats/vehicle4.wav" );pev->noise = MAKE_STRING( "plats/vehicle4.wav" ); break;
case 5: PRECACHE_SOUND( "plats/vehicle6.wav" );pev->noise = MAKE_STRING( "plats/vehicle6.wav" ); break;
case 6: PRECACHE_SOUND( "plats/vehicle7.wav" );pev->noise = MAKE_STRING( "plats/vehicle7.wav" ); break;
}
PRECACHE_SOUND( "plats/vehicle_brake1.wav" );
PRECACHE_SOUND( "plats/vehicle_start1.wav" );
m_usAdjustPitch = PRECACHE_EVENT( 1, "events/vehicle.sc" );
}
LINK_ENTITY_TO_CLASS( func_vehiclecontrols, CFuncVehicleControls );
void CFuncVehicleControls::Find()
{
edict_t *pTarget = NULL;
do
{
pTarget = FIND_ENTITY_BY_TARGETNAME( pTarget, STRING( pev->target ));
}
while( !FNullEnt( pTarget ) && !FClassnameIs( pTarget, "func_vehicle" ));
if( FNullEnt( pTarget ))
{
ALERT( at_console, "No vehicle %s\n", STRING( pev->target ));
return;
}
CFuncVehicle *pvehicle = CFuncVehicle::Instance( pTarget );
pvehicle->SetControls( pev );
UTIL_Remove( this );
}
void CFuncVehicleControls::Spawn()
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE;
SET_MODEL( ENT( pev ), STRING( pev->model ));
UTIL_SetSize( pev, pev->mins, pev->maxs );
UTIL_SetOrigin( pev, pev->origin );
SetThink( &CFuncVehicleControls::Find );
pev->nextthink = gpGlobals->time;
}

View File

@ -30,6 +30,7 @@
#include "soundent.h" #include "soundent.h"
#include "decals.h" #include "decals.h"
#include "gamerules.h" #include "gamerules.h"
#include "multi_gamerules.h"
extern CGraph WorldGraph; extern CGraph WorldGraph;
extern int gEvilImpulse101; extern int gEvilImpulse101;
@ -501,6 +502,19 @@ void CBasePlayerItem::FallThink( void )
Materialize(); Materialize();
} }
else if( m_pPlayer )
{
SetThink( NULL );
}
if( g_pGameRules->IsBustingGame())
{
if( !FNullEnt( pev->owner ))
return;
if( FClassnameIs( pev, "weapon_egon" ))
UTIL_Remove( this );
}
} }
//========================================================= //=========================================================
@ -1113,7 +1127,7 @@ void CBasePlayerAmmo::Materialize( void )
void CBasePlayerAmmo::DefaultTouch( CBaseEntity *pOther ) void CBasePlayerAmmo::DefaultTouch( CBaseEntity *pOther )
{ {
if( !pOther->IsPlayer() ) if( !pOther->IsPlayer() || IsPlayerBusting( pOther ))
{ {
return; return;
} }

View File

@ -37,7 +37,7 @@ public:
static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code ); static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code );
void Explode( Vector vecSrc, Vector vecAim ); void Explode( Vector vecSrc, Vector vecAim );
void Explode( TraceResult *pTrace, int bitsDamageType ); virtual void Explode( TraceResult *pTrace, int bitsDamageType );
void EXPORT Smoke( void ); void EXPORT Smoke( void );
void EXPORT BounceTouch( CBaseEntity *pOther ); void EXPORT BounceTouch( CBaseEntity *pOther );
@ -95,7 +95,7 @@ public:
#define RPG_WEIGHT 20 #define RPG_WEIGHT 20
#define GAUSS_WEIGHT 20 #define GAUSS_WEIGHT 20
#define EGON_WEIGHT 20 #define EGON_WEIGHT 20
#define HORNETGUN_WEIGHT 10 #define HORNETGUN_WEIGHT 15
#define HANDGRENADE_WEIGHT 5 #define HANDGRENADE_WEIGHT 5
#define SNARK_WEIGHT 5 #define SNARK_WEIGHT 5
#define SATCHEL_WEIGHT -10 #define SATCHEL_WEIGHT -10
@ -137,6 +137,7 @@ public:
#define GLOCK_DEFAULT_GIVE 17 #define GLOCK_DEFAULT_GIVE 17
#define PYTHON_DEFAULT_GIVE 6 #define PYTHON_DEFAULT_GIVE 6
#define MP5_DEFAULT_GIVE 25 #define MP5_DEFAULT_GIVE 25
#define MP5_DEFAULT_GIVE_MP MP5_MAX_CLIP
#define MP5_M203_DEFAULT_GIVE 0 #define MP5_M203_DEFAULT_GIVE 0
#define SHOTGUN_DEFAULT_GIVE 12 #define SHOTGUN_DEFAULT_GIVE 12
#define CROSSBOW_DEFAULT_GIVE 5 #define CROSSBOW_DEFAULT_GIVE 5
@ -182,6 +183,7 @@ typedef enum
#define ITEM_FLAG_NOAUTOSWITCHEMPTY 4 #define ITEM_FLAG_NOAUTOSWITCHEMPTY 4
#define ITEM_FLAG_LIMITINWORLD 8 #define ITEM_FLAG_LIMITINWORLD 8
#define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon #define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon
#define ITEM_FLAG_NOCHOICE 32
#define WEAPON_IS_ONTARGET 0x40 #define WEAPON_IS_ONTARGET 0x40
@ -723,6 +725,8 @@ public:
void EXPORT IgniteThink( void ); void EXPORT IgniteThink( void );
void EXPORT RocketTouch( CBaseEntity *pOther ); void EXPORT RocketTouch( CBaseEntity *pOther );
static CRpgRocket *CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher ); static CRpgRocket *CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher );
void Explode( TraceResult *pTrace, int bitsDamageType );
inline CRpg *GetLauncher( void );
int m_iTrail; int m_iTrail;
float m_flIgniteTime; float m_flIgniteTime;
@ -791,13 +795,13 @@ public:
int AddToPlayer( CBasePlayer *pPlayer ); int AddToPlayer( CBasePlayer *pPlayer );
BOOL Deploy( void ); BOOL Deploy( void );
BOOL CanHolster( void );
void Holster( int skiplocal = 0 ); void Holster( int skiplocal = 0 );
void UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend ); void UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend );
void CreateEffect ( void ); void CreateEffect ( void );
void DestroyEffect ( void ); void DestroyEffect ( void );
void EndAttack( void ); void EndAttack( void );
void Attack( void ); void Attack( void );
void PrimaryAttack( void ); void PrimaryAttack( void );

View File

@ -226,7 +226,7 @@ static void InitBodyQue( void )
// //
void CopyToBodyQue( entvars_t *pev ) void CopyToBodyQue( entvars_t *pev )
{ {
if( pev->effects & EF_NODRAW ) if( ( pev->effects & EF_NODRAW ) || !pev->modelindex )
return; return;
entvars_t *pevHead = VARS( g_pBodyQueueHead ); entvars_t *pevHead = VARS( g_pBodyQueueHead );
@ -513,16 +513,8 @@ void CWorld::Precache( void )
PRECACHE_SOUND( "common/bodydrop3.wav" );// dead bodies hitting the ground (animation events) PRECACHE_SOUND( "common/bodydrop3.wav" );// dead bodies hitting the ground (animation events)
PRECACHE_SOUND( "common/bodydrop4.wav" ); PRECACHE_SOUND( "common/bodydrop4.wav" );
g_Language = (int)CVAR_GET_FLOAT( "sv_language" ); PRECACHE_MODEL( "models/hgibs.mdl" );
if( g_Language == LANGUAGE_GERMAN ) PRECACHE_MODEL( "models/agibs.mdl" );
{
PRECACHE_MODEL( "models/germangibs.mdl" );
}
else
{
PRECACHE_MODEL( "models/hgibs.mdl" );
PRECACHE_MODEL( "models/agibs.mdl" );
}
PRECACHE_SOUND( "weapons/ric1.wav" ); PRECACHE_SOUND( "weapons/ric1.wav" );
PRECACHE_SOUND( "weapons/ric2.wav" ); PRECACHE_SOUND( "weapons/ric2.wav" );

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