diff --git a/.gitignore b/.gitignore index a0bc5604..a5ff9b35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# Binaries +.vscode/ *.o *.so */*.o @@ -17,3 +17,4 @@ cmake_install.cmake *.vsxproj *.vsproj *.sln +*.cmd \ No newline at end of file diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 00000000..64bd4fc1 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,31 @@ +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ +/*/build/ + +# Native files +obj/ +libs/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 00000000..3005a92f --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + diff --git a/android/HOWTO.txt b/android/HOWTO.txt new file mode 100644 index 00000000..c21aed4d --- /dev/null +++ b/android/HOWTO.txt @@ -0,0 +1,24 @@ +### Android/Java part + * AndroidManifest.xml: + * * Rename manifest package + * * Change appliction label + * * Uncomment icon and InstallReceiver if used + * src/in/celest/xash3d/LauncherActivity.java + * * Set mod gamedir + * * Set mod and launch button title + * * Set library loading options + * * Enable extras.pak extracting + * * Pass envieoment variables + * src/in/celest/xash3d/ExtractAssets.java + * * Add extra files to unpack + +### Native part + * Place folders with your mod project to jni/ + + * You may provide extras.pak for additional files + * You may use client from other package for server mods (read comments in LauncherActivity) + * You may use original server libraries for bots by loading it directly from native part + * Use getenv("XASH3D_GAMELIBDIR") and getenv("XASH3D_ENGLIBDIR") to get mod and half-life libraries path + * You may add options and pass it as enviroment variables (read comments in LauncherActivity) + * Place icon to res/drawable/ic_launcher.png and uncomment lines in AndroidManifest + \ No newline at end of file diff --git a/android/build-manual.sh b/android/build-manual.sh new file mode 100644 index 00000000..2c05b65a --- /dev/null +++ b/android/build-manual.sh @@ -0,0 +1,13 @@ +ANDROID_JAR=../android-13.jar +AAPT=./../aapt +DX=./../dx +APKBUILDER=./../apkbuilder +NAME=mod +mkdir bin +mkdir bin/classes +$AAPT package -M AndroidManifest.xml -m -S res -I $ANDROID_JAR +$JAVA_HOME/bin/javac -d bin/classes -s bin/classes -cp $ANDROID_JAR src/in/celest/xash3d/LauncherActivity.java +$DX --dex --output=bin/classes.dex bin/classes/ +/mnt/app/apktool/aapt package -f -M AndroidManifest.xml -S res -I $ANDROID_JAR -F bin/$NAME.apk.unaligned +$APKBUILDER bin/$NAME.apk -u -nf libs/ -rj libs -f bin/classes.dex -z bin/$NAME.apk.unaligned +java -jar /mnt/app/apktool/signapk.jar /mnt/app/apktool/testkey.x509.pem /mnt/app/apktool/testkey.pk8 bin/$NAME.apk bin/$NAME-signed.apk diff --git a/android/build.sh b/android/build.sh new file mode 100644 index 00000000..28b24e57 --- /dev/null +++ b/android/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +ndk-build NDK_TOOLCHAIN_VERSION=4.8 NDK_DEBUG=1 V=1 -j5 APP_CFLAGS="-w" +ant debug +#jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../myks.keystore bin/mod-unsigned.apk xashdroid -tsa https://timestamp.geotrust.com/tsa +#zipalign 4 bin/cs16-client-unsigned.apk bin/mod.apk diff --git a/android/build.xml b/android/build.xml new file mode 100644 index 00000000..88f6fb88 --- /dev/null +++ b/android/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/jni/Android.mk b/android/jni/Android.mk new file mode 100644 index 00000000..0b5a0be9 --- /dev/null +++ b/android/jni/Android.mk @@ -0,0 +1,6 @@ +override TARGET_arm_release_CFLAGS := +override TARGET_thumb_release_CFLAGS := +override TARGET_arm_debug_CFLAGS := +override TARGET_thumb_debug_CFLAGS := +override TARGET_CFLAGS := +include $(call my-dir)/../../cl_dll/Android.mk diff --git a/android/jni/Application.mk b/android/jni/Application.mk new file mode 100644 index 00000000..ecbc0914 --- /dev/null +++ b/android/jni/Application.mk @@ -0,0 +1,11 @@ +CFLAGS_OPT := -O3 -fomit-frame-pointer -ggdb -funsafe-math-optimizations -ftree-vectorize -fgraphite-identity -floop-interchange -floop-block -funsafe-loop-optimizations -finline-limit=1024 +CFLAGS_OPT_ARM := -mthumb -mfpu=neon -mcpu=cortex-a9 -pipe -mvectorize-with-neon-quad -DVECTORIZE_SINCOS +CFLAGS_OPT_ARMv5 :=-march=armv6 -mfpu=vfp -marm -pipe +CFLAGS_OPT_X86 := -mtune=atom -march=atom -mssse3 -mfpmath=sse -funroll-loops -pipe -DVECTORIZE_SINCOS +CFLAGS_HARDFP := -D_NDK_MATH_NO_SOFTFP=1 -mhard-float -mfloat-abi=hard -DLOAD_HARDFP -DSOFTFP_LINK +APPLICATIONMK_PATH = $(call my-dir) + +XASH3D_CONFIG := $(APPLICATIONMK_PATH)/mod_config.mk + +APP_ABI := x86 armeabi-v7a-hard armeabi +APP_MODULES := client diff --git a/android/jni/mod_config.mk b/android/jni/mod_config.mk new file mode 100644 index 00000000..5c0dc6bf --- /dev/null +++ b/android/jni/mod_config.mk @@ -0,0 +1,14 @@ +LOCAL_CFLAGS += $(CFLAGS_OPT) +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a-hard) +LOCAL_CFLAGS += $(CFLAGS_OPT_ARM) $(CFLAGS_HARDFP) +endif +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) +LOCAL_CFLAGS += $(CFLAGS_OPT_ARM) -mfloat-abi=softfp +endif +ifeq ($(TARGET_ARCH_ABI),armeabi) +LOCAL_CFLAGS += $(CFLAGS_OPT_ARMv5) +endif +ifeq ($(TARGET_ARCH_ABI),x86) +LOCAL_CFLAGS += $(CFLAGS_OPT_X86) +endif + diff --git a/android/project.properties b/android/project.properties new file mode 100644 index 00000000..0b9250e0 --- /dev/null +++ b/android/project.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 00000000..e11a9eab Binary files /dev/null and b/android/res/drawable-hdpi/ic_launcher.png differ diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 00000000..ef9a8d81 Binary files /dev/null and b/android/res/drawable-mdpi/ic_launcher.png differ diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 00000000..02be2b29 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_launcher.png differ diff --git a/android/res/drawable-xxhdpi/ic_launcher.png b/android/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..34fd18fe Binary files /dev/null and b/android/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/android/res/drawable-xxxhdpi/ic_launcher.png b/android/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..1f156ae5 Binary files /dev/null and b/android/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/android/src/in/celest/xash3d/ExtractAssets.java b/android/src/in/celest/xash3d/ExtractAssets.java new file mode 100644 index 00000000..50b8864e --- /dev/null +++ b/android/src/in/celest/xash3d/ExtractAssets.java @@ -0,0 +1,96 @@ +package in.celest.xash3d; +import android.content.SharedPreferences; +import java.io.FileOutputStream; +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.Method; +import android.util.Log; +import android.content.Context; + +public class ExtractAssets +{ + public static String TAG = "ExtractAssets"; + static SharedPreferences mPref; + public static int PAK_VERSION = 0; + + private static int chmod(String path, int mode) { + int ret = -1; + try + { + ret = Runtime.getRuntime().exec("chmod " + Integer.toOctalString(mode) + " " + path).waitFor(); + Log.d(TAG, "chmod " + Integer.toOctalString(mode) + " " + path + ": " + ret ); + } + catch(Exception e) + { + ret = -1; + Log.d(TAG, "chmod: Runtime not worked: " + e.toString() ); + } + try + { + Class fileUtils = Class.forName("android.os.FileUtils"); + Method setPermissions = fileUtils.getMethod("setPermissions", + String.class, int.class, int.class, int.class); + ret = (Integer) setPermissions.invoke(null, path, + mode, -1, -1); + } + catch(Exception e) + { + ret = -1; + Log.d(TAG, "chmod: FileUtils not worked: " + e.toString() ); + } + return ret; + } + + private static void extractFile(Context context, String path) + { + try + { + InputStream is = null; + FileOutputStream os = null; + is = context.getAssets().open(path); + File out = new File(context.getFilesDir().getPath()+'/'+path); + out.getParentFile().mkdirs(); + chmod( out.getParent(), 0777 ); + os = new FileOutputStream(out); + byte[] buffer = new byte[1024]; + int length; + while ((length = is.read(buffer)) > 0) + { + os.write(buffer, 0, length); + } + os.close(); + is.close(); + chmod( context.getFilesDir().getPath()+'/'+path, 0777 ); + } + catch( Exception e ) + { + Log.e( TAG, "Failed to extract file:" + e.toString() ); + e.printStackTrace(); + } + } + + public static synchronized void extractPAK(Context context, Boolean force) + { + InputStream is = null; + FileOutputStream os = null; + try + { + if( mPref == null ) + mPref = context.getSharedPreferences("mod", 0); + synchronized( mPref ) + { + if( mPref.getInt( "pakversion", 0 ) == PAK_VERSION && !force ) + return; + extractFile(context, "extras.pak"); + // add custom files here + SharedPreferences.Editor editor = mPref.edit(); + editor.putInt( "pakversion", PAK_VERSION ); + editor.commit(); + } + } + catch( Exception e ) + { + Log.e( TAG, "Failed to extract PAK:" + e.toString() ); + } + } +} diff --git a/android/src/in/celest/xash3d/InstallReceiver.java b/android/src/in/celest/xash3d/InstallReceiver.java new file mode 100644 index 00000000..c2137fa7 --- /dev/null +++ b/android/src/in/celest/xash3d/InstallReceiver.java @@ -0,0 +1,17 @@ +package in.celest.xash3d; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +public class InstallReceiver extends BroadcastReceiver +{ + private static final String TAG = "InstallReceiver"; + + @Override + public void onReceive( Context context, Intent arg1 ) + { + Log.d( TAG, "Install received, extracting PAK" ); + ExtractAssets.extractPAK( context, true ); + } +} diff --git a/android/src/in/celest/xash3d/LauncherActivity.java b/android/src/in/celest/xash3d/LauncherActivity.java new file mode 100644 index 00000000..95ae18d2 --- /dev/null +++ b/android/src/in/celest/xash3d/LauncherActivity.java @@ -0,0 +1,229 @@ +package in.celest.xash3d; + +import android.app.*; +import android.content.*; +import android.graphics.*; +import android.os.*; +import android.text.*; +import android.text.style.*; +import android.view.*; +import android.widget.*; +import android.widget.LinearLayout.*; + +public class LauncherActivity extends Activity { + static EditText cmdArgs; + static SharedPreferences mPref; + public static final int sdk = Integer.valueOf(Build.VERSION.SDK); + + public SpannableString styleButtonString(String str) + { + if(sdk < 21) + str = str.toUpperCase(); + + SpannableString spanString = new SpannableString(str.toUpperCase()); + + if(sdk < 21) + spanString.setSpan(new StyleSpan(Typeface.BOLD), 0, str.length(), 0); + + return spanString; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.requestWindowFeature(Window.FEATURE_NO_TITLE); + + // set theme + if ( sdk >= 21 ) + super.setTheme( 0x01030224 ); + else super.setTheme( 0x01030005 ); + + // Build layout + LinearLayout launcher = new LinearLayout(this); + launcher.setOrientation(LinearLayout.VERTICAL); + launcher.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + + launcher.setBackgroundColor(0xFF252525); + TextView launcherTitle = new TextView(this); + LayoutParams titleparams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + titleparams.setMargins(5,20,5,1); + LayoutParams buttonparams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + buttonparams.setMargins(10,20,10,20); + launcherTitle.setLayoutParams(titleparams); + launcherTitle.setText("TFC15-Client"); + launcherTitle.setTextAppearance(this, android.R.attr.textAppearanceMedium); + launcherTitle.setTextSize(25); + launcherTitle.setBackgroundColor(0xFF555555); + launcherTitle.setCompoundDrawablePadding(10); + try + { + launcherTitle.setCompoundDrawablesWithIntrinsicBounds(getApplicationContext().getPackageManager().getApplicationIcon(getPackageName()),null,null,null); + launcherTitle.setPadding(6,9,6,0); + } + catch(Exception e) + { + launcherTitle.setPadding(6,6,6,6); + } + launcher.addView(launcherTitle); + LinearLayout launcherBody = new LinearLayout(this); + launcherBody.setOrientation(LinearLayout.VERTICAL); + launcherBody.setLayoutParams(titleparams); + launcherBody.setBackgroundColor(0xFF454545); + LinearLayout launcherBorder = new LinearLayout(this); + launcherBorder.setLayoutParams(titleparams); + launcherBorder.setBackgroundColor(0xFF555555); + launcherBorder.setOrientation(LinearLayout.VERTICAL); + + LinearLayout launcherBorder2 = new LinearLayout(this); + launcherBorder2.setLayoutParams(titleparams); + launcherBorder2.setOrientation(LinearLayout.VERTICAL); + launcherBorder2.setBackgroundColor(0xFF353535); + launcherBorder2.addView(launcherBody); + launcherBorder2.setPadding(10,0,10,10); + launcherBorder.addView(launcherBorder2); + launcherBorder.setPadding(10,0,10,20); + launcher.addView(launcherBorder); + + TextView titleView = new TextView(this); + titleView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + titleView.setText("Command-line arguments"); + titleView.setTextAppearance(this, android.R.attr.textAppearanceLarge); + + cmdArgs = new EditText(this); + cmdArgs.setLayoutParams(buttonparams); + cmdArgs.setSingleLine(true); + if(sdk < 21) + { + cmdArgs.setBackgroundColor(0xFF353535); + cmdArgs.setTextColor(0xFFFFFFFF); + cmdArgs.setPadding(5,5,5,5); + } + Button startButton = new Button(this); + + // Set launch button title here + startButton.setText(styleButtonString("Launch " + "TFC15-Client" + "!")); + LayoutParams buttonParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); + buttonParams.gravity = 5; + startButton.setLayoutParams(buttonParams); + if(sdk < 21) + { + startButton.getBackground().setAlpha(96); + startButton.getBackground().invalidateSelf(); + startButton.setTextColor(0xFFFFFFFF); + startButton.setTextAppearance(this, android.R.attr.textAppearanceLarge); + startButton.setTextSize(20); + } + startButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startXash(v); + } + }); + launcherBody.addView(titleView); + launcherBody.addView(cmdArgs); + + // Add other options here + + launcher.addView(startButton); + setContentView(launcher); + mPref = getSharedPreferences("mod", 0); + cmdArgs.setText(mPref.getString("argv","-dev 3 -log")); + + // Uncomment this if you have pak file + // ExtractAssets.extractPAK(this, false); + } + + private Intent prepareIntent(Intent i) + { + String argv = cmdArgs.getText().toString(); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + SharedPreferences.Editor editor = mPref.edit(); + + editor.putString("argv", argv); + editor.commit(); + + // Command-line arguments + // if not passed, uses arguments from xash3d package + // Uncoment this if you are using client from other package + /* + String libserver = getFilesDir().getAbsolutePath().replace("/files","/lib/libserver_hardfp.so"); + if( !(new File(libserver).exists()) ) + libserver = getFilesDir().getAbsolutePath().replace("/files","/lib/libserver.so"); + argv = "-dll "+ libserver + " " + argv; + */ + if(argv.length() != 0) + i.putExtra("argv", argv); + + // default gamedir + // may be overriden by -game command-line option + // Uncomment to set gamedir here + i.putExtra("gamedir", "tfc" ); + + // default library package + // if you are using client from other package (not from half-life), + // replace following line by: + /*i.putExtra("gamelibdir", "/data/data//lib");*/ + i.putExtra("gamelibdir", getFilesDir().getAbsolutePath().replace("/files","/lib")); + + // if you are using pak file, uncomment this: + // i.putExtra("pakfile", getFilesDir().getAbsolutePath() + "/extras.pak"); + + // you may pass extra enviroment variables to game + // it is availiable from game code with getenv() function + /* + String envp[] = + { + "VAR1", "value1", + "VAR2", "value2" + }; + i.putExtra("env", envp); + */ + + return i; + } + + public void startXash(View view) + { + try + { + Intent intent = new Intent(); + intent.setAction("in.celest.xash3d.START"); + intent = prepareIntent(intent); + startActivity(intent); + return; + } + catch(Exception e){} + // some samsung devices have + // completely broken intent resolver + // so try specify exact component here + try + { + Intent intent = new Intent(); + intent.setComponent(new ComponentName("in.celest.xash3d.hl.test", "in.celest.xash3d.XashActivity")); + intent = prepareIntent(intent); + startActivity(intent); + return; + } + catch(Exception e){} + try + { + Intent intent = new Intent(); + intent.setComponent(new ComponentName("in.celest.xash3d.hl", "in.celest.xash3d.XashActivity")); + intent = prepareIntent(intent); + startActivity(intent); + return; + } + catch(Exception e){} + new AlertDialog.Builder(this) + .setTitle("Error") + .setMessage("Failed to start Xash3D FWGS engine\nIs it installed?") + .setCancelable(false) + .setPositiveButton("Ok", new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface i, int w){ + LauncherActivity.this.finish(); + } + }).show(); + } +} diff --git a/cl_dll/Android.mk b/cl_dll/Android.mk index df6130ed..3f1bf805 100755 --- a/cl_dll/Android.mk +++ b/cl_dll/Android.mk @@ -24,25 +24,26 @@ LOCAL_CFLAGS += -DCLIENT_DLL=1 SRCS= SRCS_C= -SRCS+=../dlls/crossbow.cpp -SRCS+=../dlls/crowbar.cpp -SRCS+=../dlls/egon.cpp -SRCS+=./ev_hldm.cpp -SRCS+=../dlls/gauss.cpp -SRCS+=../dlls/handgrenade.cpp +SRCS+=./tfc/ev_tfc.cpp SRCS+=./hl/hl_baseentity.cpp -SRCS+=./hl/hl_events.cpp +SRCS+=./tfc/tfc_events.cpp SRCS+=./hl/hl_objects.cpp -SRCS+=./hl/hl_weapons.cpp -SRCS+=../dlls/hornetgun.cpp -SRCS+=../dlls/mp5.cpp -SRCS+=../dlls/python.cpp -SRCS+=../dlls/rpg.cpp -SRCS+=../dlls/satchel.cpp -SRCS+=../dlls/shotgun.cpp -SRCS+=../dlls/squeakgrenade.cpp -SRCS+=../dlls/tripmine.cpp -SRCS+=../dlls/glock.cpp +SRCS+=./tfc/tfc_weapons.cpp +SRCS+=../dlls/crowbar.cpp +SRCS+=../dlls/tfc/assaultcannon.cpp +SRCS+=../dlls/tfc/axe.cpp +SRCS+=../dlls/tfc/flamethrower.cpp +SRCS+=../dlls/tfc/grenadelauncher.cpp +SRCS+=../dlls/tfc/incendiarycannon.cpp +SRCS+=../dlls/tfc/nailgun.cpp +SRCS+=../dlls/tfc/pipebomblauncher.cpp +SRCS+=../dlls/tfc/railgun.cpp +SRCS+=../dlls/tfc/rpg.cpp +SRCS+=../dlls/tfc/shotgun.cpp +SRCS+=../dlls/tfc/sniperrifle.cpp +SRCS+=../dlls/tfc/spanner.cpp +SRCS+=../dlls/tfc/supernailgun.cpp +SRCS+=../dlls/tfc/supershotgun.cpp #SRCS+=../game_shared/voice_banmgr.cpp #SRCS+=../game_shared/voice_status.cpp SRCS+=./ammo.cpp @@ -100,6 +101,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/. \ $(LOCAL_PATH)/../game_shared \ $(LOCAL_PATH)/../dlls \ $(LOCAL_PATH)/../pm_shared \ + $(LOCAL_PATH)/../dlls/tfc \ $(LOCAL_PATH)/../utils/false_vgui/include LOCAL_CFLAGS += $(DEFINES) $(INCLUDES) diff --git a/cl_dll/hl/hl_objects.cpp b/cl_dll/hl/hl_objects.cpp index 55822dcb..89bc2b8c 100644 --- a/cl_dll/hl/hl_objects.cpp +++ b/cl_dll/hl/hl_objects.cpp @@ -29,7 +29,7 @@ extern BEAM *pBeam; extern BEAM *pBeam2; -extern TEMPENTITY *pFlare; // Vit_amiN: egon's energy flare +//extern TEMPENTITY *pFlare; // Vit_amiN: egon's energy flare void HUD_GetLastOrg( float *org ); void UpdateBeams( void ) @@ -76,7 +76,7 @@ void UpdateBeams( void ) pBeam2->target = tr.endpos; pBeam2->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case. } - +/* if( pFlare ) // Vit_amiN: beam flare { pFlare->entity.origin = tr.endpos; @@ -98,6 +98,7 @@ void UpdateBeams( void ) } } } +*/ } /* @@ -109,6 +110,8 @@ Add game specific, client-side objects here */ void Game_AddObjects( void ) { + /* if( pBeam || pBeam2 || pFlare ) // Vit_amiN: egon flare added UpdateBeams(); + */ } diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index 62c32b41..7af2b738 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -28,6 +28,9 @@ #include "demo.h" #include "demo_api.h" +#define MENU_TEAM 2 +#define MENU_CLASS 3 + cvar_t *hud_textmode; float g_hud_text_color[3]; @@ -123,7 +126,7 @@ int __MsgFunc_Detpack( const char *pszName, int iSize, void *pbuf ) int __MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ) { - return 0; + return gHUD.MsgFunc_VGUIMenu( pszName, iSize, pbuf ); } int __MsgFunc_BuildSt( const char *pszName, int iSize, void *pbuf ) @@ -148,7 +151,7 @@ int __MsgFunc_Spectator( const char *pszName, int iSize, void *pbuf ) int __MsgFunc_AllowSpec( const char *pszName, int iSize, void *pbuf ) { - return 0; + return gHUD.MsgFunc_AllowSpec( pszName, iSize, pbuf ); } // This is called every time the DLL is loaded @@ -587,3 +590,42 @@ float CHud::GetSensitivity( void ) { return m_flMouseSensitivity; } + +int CHud::MsgFunc_AllowSpec( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_bAllowSpec = (bool)READ_BYTE(); + + return 1; +} + +int CHud::MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int menuType = READ_BYTE(); + //m_bitsValidSlots = READ_SHORT(); // is ignored + + ShowVGUIMenu(menuType); + return 1; +} + +void CHud::ShowVGUIMenu( int menuType ) +{ + char *szCmd; + + switch(menuType) + { + case MENU_TEAM: + szCmd = "exec touch/chooseteam.cfg"; + break; + default: + szCmd = "touch_removebutton _menu_*"; // back to the default touch page + //m_fMenuDisplayed = 0; + break; + } + //Velaron: Touch Menus + //m_fMenuDisplayed = 1; + ClientCmd(szCmd); +} diff --git a/cl_dll/hud.h b/cl_dll/hud.h index f3e1ed85..8ad0f98a 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -420,6 +420,7 @@ private: wrect_t *m_prc1; wrect_t *m_prc2; int m_iBat; + int m_iBatMax; float m_fFade; int m_iHeight; // width of the battery innards }; @@ -597,6 +598,8 @@ public: int DrawHudStringLen( const char *szIt ); void DrawDarkRectangle( int x, int y, int wide, int tall ); + bool m_bAllowSpec; + private: // the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded. // freed in ~CHud() @@ -655,6 +658,9 @@ public: int _cdecl MsgFunc_SetFOV( const char *pszName, int iSize, void *pbuf ); int _cdecl MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf ); + int _cdecl MsgFunc_AllowSpec( const char *pszName, int iSize, void *pbuf ); + int _cdecl MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ); + // Screen information SCREENINFO m_scrinfo; @@ -670,6 +676,8 @@ public: void AddHudElem( CHudBase *p ); float GetSensitivity(); + + void ShowVGUIMenu( int menuType ); }; extern CHud gHUD; diff --git a/cl_dll/hud_msg.cpp b/cl_dll/hud_msg.cpp index 7cc2fbad..930f3dc6 100644 --- a/cl_dll/hud_msg.cpp +++ b/cl_dll/hud_msg.cpp @@ -25,7 +25,7 @@ extern BEAM *pBeam; extern BEAM *pBeam2; -extern TEMPENTITY *pFlare; // Vit_amiN +//extern TEMPENTITY *pFlare; // Vit_amiN extern float g_lastFOV; // Vit_amiN @@ -79,7 +79,7 @@ void CHud::MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf ) //Probably not a good place to put this. pBeam = pBeam2 = NULL; - pFlare = NULL; // Vit_amiN: clear egon's beam flare + //pFlare = NULL; // Vit_amiN: clear egon's beam flare } int CHud::MsgFunc_GameMode( const char *pszName, int iSize, void *pbuf ) diff --git a/cl_dll/tfc/ev_tfc.cpp b/cl_dll/tfc/ev_tfc.cpp new file mode 100644 index 00000000..161b2fae --- /dev/null +++ b/cl_dll/tfc/ev_tfc.cpp @@ -0,0 +1,2225 @@ +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "entity_types.h" +#include "usercmd.h" +#include "pm_defs.h" +#include "pm_materials.h" + +#include "eventscripts.h" +#include "ev_tfc.h" + +#include "r_efx.h" +#include "event_api.h" +#include "event_args.h" +#include "in_defs.h" + +#include + +#include "r_studioint.h" +#include "com_model.h" + +extern engine_studio_api_t IEngineStudio; + +static int tracerCount[32]; + +extern "C" char PM_FindTextureType( char *name ); + +void V_PunchAxis( int axis, float punch ); +void VectorAngles( const float *forward, float *angles ); + +extern cvar_t *cl_lw; + + +BEAM *pBeam; +BEAM *pBeam2; + +extern "C" float anglemod( float a ); + +struct eventnode_s +{ + event_args_t *data; + eventnode_s *prev; + eventnode_s *next; +}; +typedef eventnode_s eventnode_t; + +pmtrace_t *gp_tr_decal[32]; +float g_flSpinDownTime[32]; +int g_bACSpinning[32]; +float g_flSpinUpTime[32]; + +extern "C" +{ +void EV_TFC_Axe( struct event_args_s *args ); +void EV_FireTFCShotgun( struct event_args_s *args ); +void EV_FireTFCSuperShotgun( struct event_args_s *args ); +void EV_ReloadTFCShotgun( struct event_args_s *args ); +void EV_PumpTFCShotgun( struct event_args_s *args ); +void EV_FireTFCNailgun( struct event_args_s *args ); +void EV_FireTFCSuperNailgun( struct event_args_s *args ); +void EV_FireTFCAutoRifle( struct event_args_s *args ); +void EV_TFC_Gas( struct event_args_s *args ); +void EV_TFC_DoorGoUp( struct event_args_s *args ); +void EV_TFC_DoorGoDown( struct event_args_s *args ); +void EV_TFC_DoorHitTop( struct event_args_s *args ); +void EV_TFC_DoorHitBottom( struct event_args_s *args ); +void EV_TFC_Explosion( struct event_args_s *args ); +void EV_TFC_Grenade( struct event_args_s *args ); +void EV_TFC_NormalGrenade( struct event_args_s *args ); +void EV_TFC_FireRPG( struct event_args_s *args ); +void EV_FireTFCSniper( struct event_args_s *args ); +void EV_TFC_SniperHit( struct event_args_s *args ); +void EV_TFC_FireIC( struct event_args_s *args ); +void EV_TFC_NailgrenadeNail( struct event_args_s *args ); +void EV_TFC_GrenadeLauncher( struct event_args_s *args ); +void EV_TFC_PipeLauncher( struct event_args_s *args ); +void EV_TFC_NormalShot( struct event_args_s *args ); +void EV_TFC_SuperShot( struct event_args_s *args ); +void EV_TFC_SteamShot( struct event_args_s *args ); +void EV_TFC_EngineerGrenade( struct event_args_s *args ); +void EV_TFC_Concussion( struct event_args_s *args ); +void EV_TFC_Assault_WindUp( struct event_args_s *args ); +void EV_TFC_Assault_WindDown( struct event_args_s *args ); +void EV_TFC_Assault_Start( struct event_args_s *args ); +void EV_TFC_Assault_Fire( struct event_args_s *args ); +void EV_TFC_Assault_Spin( struct event_args_s *args ); +void EV_TFC_Assault_StartSpin( struct event_args_s *args ); +void EV_TFC_AxeDecal( struct event_args_s *args ); +void EV_TFC_NapalmFire( struct event_args_s *args ); +void EV_TFC_MirvGrenadeMain( struct event_args_s *args ); +void EV_TFC_MirvGrenade( struct event_args_s *args ); +void EV_TFC_NapalmBurn( struct event_args_s *args ); +void EV_TFC_EMP( struct event_args_s *args ); +void EV_TFC_Flame_Fire( struct event_args_s *args ); +void EV_TFC_Railgun( struct event_args_s *args ); +void EV_TFC_Tranquilizer( struct event_args_s *args ); +void EV_TFC_NailGrenade( struct event_args_s *args ); + +void EV_TrainPitchAdjust( struct event_args_s *args ); +} + +#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 ) +#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 ) +#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 ) +#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 ) +#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 ) +#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 ) +#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 ) +#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 ) +#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 ) +#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 ) +#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 ) +#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 ) + +// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the +// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture. +// returns volume of strike instrument (crowbar) to play +float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType ) +{ + // hit the world, try to play sound based on texture material type + char chTextureType = CHAR_TEX_CONCRETE; + float fvol; + float fvolbar; + char *rgsz[4]; + int cnt; + float fattn = ATTN_NORM; + int entity; + char *pTextureName; + char texname[64]; + char szbuffer[64]; + + entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr ); + + // FIXME check if playtexture sounds movevar is set + // + chTextureType = 0; + + // Player + if( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) + { + // hit body + chTextureType = CHAR_TEX_FLESH; + } + else if( entity == 0 ) + { + // get texture from entity or world (world is ent(0)) + pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); + + if ( pTextureName ) + { + strcpy( texname, pTextureName ); + pTextureName = texname; + + // strip leading '-0' or '+0~' or '{' or '!' + if( *pTextureName == '-' || *pTextureName == '+' ) + { + pTextureName += 2; + } + + if( *pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ' ) + { + pTextureName++; + } + + // '}}' + strcpy( szbuffer, pTextureName ); + szbuffer[CBTEXTURENAMEMAX - 1] = 0; + + // get texture type + chTextureType = PM_FindTextureType( szbuffer ); + } + } + + switch (chTextureType) + { + default: + case CHAR_TEX_CONCRETE: + fvol = 0.9; + fvolbar = 0.6; + rgsz[0] = "player/pl_step1.wav"; + rgsz[1] = "player/pl_step2.wav"; + cnt = 2; + break; + case CHAR_TEX_METAL: + fvol = 0.9; + fvolbar = 0.3; + rgsz[0] = "player/pl_metal1.wav"; + rgsz[1] = "player/pl_metal2.wav"; + cnt = 2; + break; + case CHAR_TEX_DIRT: + fvol = 0.9; + fvolbar = 0.1; + rgsz[0] = "player/pl_dirt1.wav"; + rgsz[1] = "player/pl_dirt2.wav"; + rgsz[2] = "player/pl_dirt3.wav"; + cnt = 3; + break; + case CHAR_TEX_VENT: + fvol = 0.5; + fvolbar = 0.3; + rgsz[0] = "player/pl_duct1.wav"; + rgsz[1] = "player/pl_duct1.wav"; + cnt = 2; + break; + case CHAR_TEX_GRATE: + fvol = 0.9; + fvolbar = 0.5; + rgsz[0] = "player/pl_grate1.wav"; + rgsz[1] = "player/pl_grate4.wav"; + cnt = 2; + break; + case CHAR_TEX_TILE: + fvol = 0.8; + fvolbar = 0.2; + rgsz[0] = "player/pl_tile1.wav"; + rgsz[1] = "player/pl_tile3.wav"; + rgsz[2] = "player/pl_tile2.wav"; + rgsz[3] = "player/pl_tile4.wav"; + cnt = 4; + break; + case CHAR_TEX_SLOSH: + fvol = 0.9; + fvolbar = 0.0; + rgsz[0] = "player/pl_slosh1.wav"; + rgsz[1] = "player/pl_slosh3.wav"; + rgsz[2] = "player/pl_slosh2.wav"; + rgsz[3] = "player/pl_slosh4.wav"; + cnt = 4; + break; + case CHAR_TEX_WOOD: + fvol = 0.9; + fvolbar = 0.2; + rgsz[0] = "debris/wood1.wav"; + rgsz[1] = "debris/wood2.wav"; + rgsz[2] = "debris/wood3.wav"; + cnt = 3; + break; + case CHAR_TEX_GLASS: + case CHAR_TEX_COMPUTER: + fvol = 0.8; + fvolbar = 0.2; + rgsz[0] = "debris/glass1.wav"; + rgsz[1] = "debris/glass2.wav"; + rgsz[2] = "debris/glass3.wav"; + cnt = 3; + break; + case CHAR_TEX_FLESH: + if( iBulletType == BULLET_PLAYER_CROWBAR ) + return 0.0; // crowbar already makes this sound + fvol = 1.0; + fvolbar = 0.2; + rgsz[0] = "weapons/bullet_hit1.wav"; + rgsz[1] = "weapons/bullet_hit2.wav"; + fattn = 1.0; + cnt = 2; + break; + } + + // play material hit sound + gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong( 0, cnt - 1 )], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + return fvolbar; +} + +char *EV_HLDM_DamageDecal( physent_t *pe ) +{ + static char decalname[32]; + int idx; + + if( pe->classnumber == 1 ) + { + idx = gEngfuncs.pfnRandomLong( 0, 2 ); + sprintf( decalname, "{break%i", idx + 1 ); + } + else if( pe->rendermode != kRenderNormal ) + { + sprintf( decalname, "{bproof1" ); + } + else + { + idx = gEngfuncs.pfnRandomLong( 0, 4 ); + sprintf( decalname, "{shot%i", idx + 1 ); + } + return decalname; +} + +void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName ) +{ + int iRand; + physent_t *pe; + + gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos ); + + iRand = gEngfuncs.pfnRandomLong( 0, 0x7FFF ); + if( iRand < ( 0x7fff / 2 ) )// not every bullet makes a sound. + { + switch( iRand % 5 ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); + break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); + break; + case 2: + gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); + break; + case 3: + gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); + break; + case 4: + gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); + break; + } + } + + pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); + + // Only decal brush models such as the world etc. + if( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) ) + { + if( CVAR_GET_FLOAT( "r_decals" ) ) + { + gEngfuncs.pEfxAPI->R_DecalShoot( + gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ), + gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 ); + } + } +} + +void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType ) +{ + physent_t *pe; + + pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); + + if( pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) ) + { + switch( iBulletType ) + { + case BULLET_PLAYER_9MM: + case BULLET_MONSTER_9MM: + case BULLET_PLAYER_MP5: + case BULLET_MONSTER_MP5: + case BULLET_PLAYER_BUCKSHOT: + case BULLET_PLAYER_357: + default: + // smoke and decal + EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) ); + break; + } + } +} + +int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount ) +{ + int tracer = 0; + int i; + qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false; + + if( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq ) == 0 ) + { + vec3_t vecTracerSrc; + + if( player ) + { + vec3_t offset( 0, 0, -4 ); + + // adjust tracer position for player + for( i = 0; i < 3; i++ ) + { + vecTracerSrc[i] = vecSrc[i] + offset[i] + right[i] * 2 + forward[i] * 16; + } + } + else + { + VectorCopy( vecSrc, vecTracerSrc ); + } + + if( iTracerFreq != 1 ) // guns that always trace also always decal + tracer = 1; + + switch( iBulletType ) + { + case BULLET_PLAYER_MP5: + case BULLET_MONSTER_MP5: + case BULLET_MONSTER_9MM: + case BULLET_MONSTER_12MM: + default: + EV_CreateTracer( vecTracerSrc, end ); + break; + } + } + + return tracer; +} + +/* +================ +FireBullets + +Go to the trouble of combining multiple pellets into a single damage call. +================ +*/ +void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY ) +{ + int i; + pmtrace_t tr; + int iShot; + int tracer; + + for( iShot = 1; iShot <= cShots; iShot++ ) + { + vec3_t vecDir, vecEnd; + float x, y, z; + + //We randomize for the Shotgun. + if( iBulletType == BULLET_PLAYER_BUCKSHOT ) + { + do{ + x = gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) + gEngfuncs.pfnRandomFloat( -0.5, 0.5 ); + y = gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) + gEngfuncs.pfnRandomFloat( -0.5, 0.5 ); + z = x * x + y * y; + }while( z > 1 ); + + for( i = 0 ; i < 3; i++ ) + { + vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[i] + y * flSpreadY * up [i]; + vecEnd[i] = vecSrc[i] + flDistance * vecDir[i]; + } + }//But other guns already have their spread randomized in the synched spread. + else + { + for( i = 0 ; i < 3; i++ ) + { + vecDir[i] = vecDirShooting[i] + flSpreadX * right[i] + flSpreadY * up [i]; + vecEnd[i] = vecSrc[i] + flDistance * vecDir[i]; + } + } + + gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true ); + + // Store off the old count + gEngfuncs.pEventAPI->EV_PushPMStates(); + + // Now add in all of the players. + gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 ); + + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + + tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); + + // do damage, paint decals + if( tr.fraction != 1.0 ) + { + switch( iBulletType ) + { + default: + case BULLET_PLAYER_9MM: + EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); + EV_HLDM_DecalGunshot( &tr, iBulletType ); + break; + case BULLET_PLAYER_MP5: + if( !tracer ) + { + EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); + EV_HLDM_DecalGunshot( &tr, iBulletType ); + } + break; + case BULLET_PLAYER_BUCKSHOT: + EV_HLDM_DecalGunshot( &tr, iBulletType ); + break; + case BULLET_PLAYER_357: + EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); + EV_HLDM_DecalGunshot( &tr, iBulletType ); + break; + } + } + + gEngfuncs.pEventAPI->EV_PopPMStates(); + } +} + +#define SND_CHANGE_PITCH (1 << 7) + +void EV_TrainPitchAdjust( event_args_t *args ) +{ + int idx; + vec3_t origin; + + unsigned short us_params; + int noise; + float m_flVolume; + int pitch; + int stop; + + char sz[256]; + + idx = args->entindex; + + VectorCopy( args->origin, origin ); + + us_params = (unsigned short)args->iparam1; + stop = args->bparam1; + + m_flVolume = (float)( us_params & 0x003f ) / 40.0; + noise = (int)( ( ( us_params ) >> 12 ) & 0x0007 ); + pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) ); + + switch( noise ) + { + case 1: + strcpy( sz, "plats/ttrain1.wav" ); + break; + case 2: + strcpy( sz, "plats/ttrain2.wav" ); + break; + case 3: + strcpy( sz, "plats/ttrain3.wav" ); + break; + case 4: + strcpy( sz, "plats/ttrain4.wav"); + break; + case 5: + strcpy( sz, "plats/ttrain6.wav"); + break; + case 6: + strcpy( sz, "plats/ttrain7.wav"); + break; + default: + // no sound + strcpy( sz, "" ); + return; + } + + if( stop ) + { + gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz ); + } + else + { + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch ); + } +} + +int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 ) +{ + return 0; +} + +enum tfc_axe_e +{ + AXE_IDLE1 = 0, + AXE_DRAW, + AXE_HOLSTER, + AXE_ATTACK1, + AXE_ATTACK1MISS, + AXE_ATTACK2, + AXE_ATTACK2HIT, + AXE_ATTACK3, + AXE_ATTACK3HIT, + AXE_IDLE2, + AXE_IDLE3 +}; + +int m_iSwing; + +void EV_TFC_Axe(event_args_t *args) +{ + int idx; + float fSoundData; + float *vecc; + signed int classid; + int ent; + pmtrace_t tr; + pmtrace_t tr2; + vec3_t vecSrc, vecEnd; + vec3_t right, forward, up; + vec3_t origin, angles; + + idx = args->entindex; + classid = args->iparam1; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + AngleVectors(angles, forward, right, up); + EV_GetGunPosition(args, vecSrc, origin); + VectorMA(vecSrc, 32.0, forward, vecEnd); + gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction(0, 1); + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetSolidPlayers(idx - 1); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr); + if (tr.fraction >= 1.0) + { + gEngfuncs.pEventAPI->EV_SetTraceHull(1); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr2); + if(tr2.fraction < 1.0) + tr = tr2; + } + gEngfuncs.pEventAPI->EV_PopPMStates(); + if(tr.fraction >= 1.0) + { + switch(classid) + { + default: + { + switch((m_iSwing++) % 3) + { + case 1: + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation( AXE_ATTACK1, 2 ); + break; + case 2: + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation( AXE_ATTACK2, 2 ); + break; + default: + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation( AXE_ATTACK3, 2 ); + break; + } + if (EV_IsLocal(idx)) + EV_TFC_PlayAxeSound(idx, classid, origin, 0, 1.0); + } + break; + case 2: + case 0: + { + if (EV_IsLocal(idx)) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation( 2, 2 ); + EV_TFC_PlayAxeSound(idx, classid, origin, 0, 1.0); + } + } + break; + case 1: + { + if (EV_IsLocal(idx)) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation( 1, 2 ); + EV_TFC_PlayAxeSound(idx, classid, origin, 0, 1.0); + } + } + break; + } + } + else + { + ent = gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr); + switch(classid) + { + default: + { + if(!EV_TFC_IsAlly(idx, ent)) + { + if(gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, forward, &tr, 20.0); + } + if(EV_IsPlayer(ent)) + EV_TFC_PlayAxeSound(idx, classid, origin, 1, 1.0); + else + EV_TFC_PlayAxeSound(idx, classid, origin, 2, 1.0); + switch((m_iSwing++) % 2) + { + case 1: + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation( AXE_ATTACK2HIT, 2 ); + break; + default: + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation( AXE_ATTACK3HIT, 2 ); + break; + } + } + break; + case 0: + { + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(2, 2); + EV_TFC_AxeHit(idx, origin, forward, right, ent, forward, &tr); + if (EV_IsLocal(idx)) + if(EV_IsPlayer(ent)) + EV_TFC_PlayAxeSound(idx, classid, origin, 1, 1.0); + else + EV_TFC_PlayAxeSound(idx, classid, origin, 2, 1.0); + } + break; + case 2: + { + EV_TFC_Medkit(idx, origin, forward, right, ent, forward, &tr); + if (EV_IsLocal(idx)) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2); + if(EV_IsPlayer(ent)) + EV_TFC_PlayAxeSound(idx, classid, origin, 1, 1.0); + else + EV_TFC_PlayAxeSound(idx, classid, origin, 2, 1.0); + } + } + break; + case 1: + { + EV_TFC_AxeHit(idx, origin, forward, right, ent, forward, &tr); + if (EV_IsLocal(idx)) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2); + if(EV_IsPlayer(ent)) + EV_TFC_PlayAxeSound(idx, classid, origin, 1, 1.0); + else + EV_TFC_PlayAxeSound(idx, classid, origin, 2, 1.0); + } + } + break; + } + } +} + +enum tfc_shotgun_e +{ + TFCSHOTGUN_IDLE = 0, + TFCSHOTGUN_SHOOT, + TFCSHOTGUN_SHOOT_BIG, + TFCSHOTGUN_RELOAD, + TFCSHOTGUN_PUMP, + TFCSHOTGUN_STARTRELOAD, + TFCSHOTGUN_DRAW, + TFCSHOTGUN_REHOLSTER, + TFCSHOTGUN_IDLE4, + TFCSHOTGUN_DEEPIDLE +}; + +void EV_FireTFCShotgun(event_args_t *args) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + vec3_t up, right, forward; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + VectorCopy(args->velocity, velocity); + + AngleVectors(angles, forward, right, up); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/shotgunshell.mdl"); + + EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4); + + if(EV_IsLocal(idx)) + { + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFCSHOTGUN_SHOOT, 2); + V_PunchAxis(0, -2.0); + } + + EV_EjectBrass(ShellOrigin, ShellVelocity, angles.y, shell, TE_BOUNCE_SHELL); + + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/sbarrel1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), 0.8, 0, gEngfuncs.pfnRandomLong(0, 31) + 93); + EV_GetGunPosition(args, vecSrc, origin); + VectorCopy(forward, vecAiming); + + EV_HLDM_FireBullets(idx, forward, right, up, 6, vecSrc, vecAiming, 2048.0, BULLET_PLAYER_BUCKSHOT, 0, tracerCount + idx, 0.04, 0.04); +} + +void EV_ReloadTFCShotgun(event_args_t *args) +{ + int idx; + vec3_t origin; + const char* sound; + + idx = args->entindex; + VectorCopy(args->origin, origin); + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFCSHOTGUN_RELOAD, 2); + if(gEngfuncs.pfnRandomLong(0, 1)) + sound = "weapons/reload3.wav"; + + else + sound = "weapons/reload1.wav"; + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, sound, 1.0, 0.8, 0, gEngfuncs.pfnRandomLong(0, 31) + 85); +} + +void EV_PumpTFCShotgun(event_args_t *args) +{ + int full; + int idx; + vec3_t origin; + + full = args->bparam1; + idx = args->entindex; + VectorCopy(args->origin, origin); + if(full && EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFCSHOTGUN_PUMP, 2); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/scock1.wav", 1.0, 0.8, 0, gEngfuncs.pfnRandomLong(0, 31) + 95); +} + +enum tfc_nailgun_e +{ + NAILGUN_LONGIDLE = 0, + NAILGUN_IDLE1, + NAILGUN_GRENADE, + NAILGUN_RELOAD, + NAILGUN_DEPLOY, + NAILGUN_SHOOT1, + NAILGUN_SHOOT2, + NAILGUN_SHOOT3 +}; + +void EV_FireTFCNailgun(event_args_t *args) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + vec3_t up, right, forward; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + VectorCopy(args->velocity, velocity); + + AngleVectors(angles, forward, right, up); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/nail.mdl"); + + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(NAILGUN_SHOOT1, 2); + EV_GetGunPosition(args, ShellOrigin, origin); + VectorMA(ShellOrigin, -4.0, up, ShellOrigin); + VectorMA(ShellOrigin, 2.0, right, ShellOrigin); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/airgun_1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), 0.8, 0, gEngfuncs.pfnRandomLong(0, 31) + 93); + VectorScale(forward, 1000.0, velocity); + gEngfuncs.pEfxAPI->R_Projectile(ShellOrigin, velocity, shell, 6, idx, EV_TFC_NailTouch); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -1.0); +} + +void EV_TFC_NailTouch(struct tempent_s *ent, pmtrace_t *ptr) +{ + physent_t *pe; + char name; + + pe = gEngfuncs.pEventAPI->EV_GetPhysent(ptr->ent); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + { + sprintf(&name, "{shot%i", gEngfuncs.pfnRandomLong(0, 4) + 1); + if(name) + { + if (ptr->fraction != 1.0) + EV_HLDM_GunshotDecalTrace(ptr, &name); + } + } +} + +void EV_FireTFCSuperNailgun(event_args_t *args) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + vec3_t up, right, forward; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + VectorCopy(args->velocity, velocity); + + AngleVectors(angles, forward, right, up); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/nail.mdl"); + + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(NAILGUN_SHOOT1, 2); + EV_GetGunPosition(args, ShellOrigin, origin); + VectorMA(ShellOrigin, -4.0, up, ShellOrigin); + VectorMA(ShellOrigin, 2.0, right, ShellOrigin); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/spike2.wav", 1.0, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + VectorScale(forward, 1000.0, velocity); + gEngfuncs.pEfxAPI->R_Projectile(ShellOrigin, velocity, shell, 6, idx, EV_TFC_NailTouch); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -1.0); +} + +void EV_FireTFCSuperShotgun(event_args_t *args) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + vec3_t up, right, forward; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + VectorCopy(args->velocity, velocity); + + AngleVectors(angles, forward, right, up); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/shotgunshell.mdl"); + + EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4); + + if(EV_IsLocal(idx)) + { + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFCSHOTGUN_SHOOT, 2); + V_PunchAxis(0, -4.0); + } + + EV_EjectBrass(ShellOrigin, ShellVelocity, angles.y, shell, TE_BOUNCE_SHELL); + + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/shotgn2.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), 0.8, 0, gEngfuncs.pfnRandomLong(0, 31) + 93); + EV_GetGunPosition(args, vecSrc, origin); + VectorCopy(forward, vecAiming); + + EV_HLDM_FireBullets(idx, forward, right, up, 14, vecSrc, vecAiming, 2048.0, BULLET_PLAYER_BUCKSHOT, 0, tracerCount + idx, 0.04, 0.04); +} + +enum tfc_sniper_e +{ + SNIPER_IDLE = 0, + SNIPER_AIM, + SNIPER_FIRE, + SNIPER_DRAW, + SNIPER_HOLSTER, + SNIPER_AUTOIDLE, + SNIPER_AUTOFIRE, + SNIPER_AUTODRAW, + SBIPER_AUTOHOLSTER +}; + +void EV_FireTFCAutoRifle(event_args_t *args) +{ + int idx; + physent_s *pe; + pmtrace_t tr; + + vec3_t origin; + vec3_t angles; + vec3_t up, right, forward; + + vec3_t vecSrc, vecAiming, vecEnd; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + AngleVectors(angles, forward, right, up); + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(SNIPER_AUTOFIRE, 2); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/sniper.wav", 0.9, 0.8, 0, 100); + EV_GetGunPosition(args, vecSrc, origin); + vecAiming = forward; + VectorMA(vecSrc, 8192.0, vecAiming, vecEnd); + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetSolidPlayers(idx - 1); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr); + + if ( tr.fraction != 1.0 ) + { + if(gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, vecAiming, &tr, 8.0); + EV_HLDM_PlayTextureSound(idx, &tr, vecSrc, vecEnd, BULLET_PLAYER_357); + pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + EV_HLDM_DecalGunshot(&tr, BULLET_PLAYER_357); + } + gEngfuncs.pEventAPI->EV_PopPMStates(); +} + +void EV_TFC_TraceAttack(int idx, float *vecDir, pmtrace_t *ptr, float flDamage) +{ + int index; + signed int iPlayer1; + signed int iPlayer2; + vec3_t dir; + vec3_t vecOrigin; + + VectorScale(vecDir, -4.0, dir); + vecOrigin.x = (int)ptr + 20 - dir.x; + vecOrigin.y = (int)ptr + 24 - dir.y; + vecOrigin.z = (int)ptr + 28 - dir.z; + index = gEngfuncs.pEventAPI->EV_IndexFromTrace(ptr); + if(index > 0 && index <= gEngfuncs.GetMaxClients()) + { + iPlayer2 = -1; + if(GetEntity(index)) + iPlayer2 = GetEntity(index)->curstate.team; + } + if(idx > 0 && idx <= gEngfuncs.GetMaxClients()) + { + iPlayer1 = -1; + if(GetEntity(idx)) + iPlayer1 = GetEntity(idx)->curstate.team; + } + if ( iPlayer1 != iPlayer2 ) + EV_TFC_BloodDrips(vecOrigin, (signed int)flDamage, vecOrigin.z); +} + +void EV_TFC_BloodDrips(float *vecOrigin, signed int iDamage, long double height) +{ + int modelIndex; + int modelIndex2; + float scale; + + if (gEngfuncs.pfnGetCvarFloat("violence_hblood") != 0.0 && iDamage > 0) + { + if (gEngfuncs.GetMaxClients() > 2) + iDamage *= 2; + if (iDamage > 255) + { + modelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/bloodspray.spr"); + scale = 16.0; + modelIndex2 = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/blood.spr"); + } + else + { + modelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/bloodspray.spr"); + modelIndex2 = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/blood.spr"); + if ( iDamage > 159 ) + scale = 16.0; + else + { + scale = 3.0; + if ( iDamage > 29 ) + scale = iDamage / 10; + } + } + gEngfuncs.pEfxAPI->R_BloodSprite(vecOrigin, 47, modelIndex, modelIndex2, scale); + } +} + +enum tfc_assault_e +{ + ASSAULT_IDLE = 0, + ASSAULT_IDLE2, + ASSAULT_SPINUP, + ASSAULT_SPINDOWN, + ASSAULT_FIRE, + ASSAULT_DRAW, + ASSAULT_HOLSTER +}; + +void EV_TFC_Assault_WindUp(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + g_flSpinDownTime[idx - 1] = 0; + gEngfuncs.GetClientTime(); + g_flSpinUpTime[idx - 1] = 0.0 + 3.5; + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(ASSAULT_SPINUP, 2); + g_bACSpinning[idx - 1] = 0; + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan2.wav"); + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan4.wav"); + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_WEAPON, "weapons/asscan3.wav"); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/asscan1.wav", 0.98, 0.8, 0, 125); +} + +void EV_TFC_Assault_WindDown(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + if(g_flSpinUpTime[idx - 1] == 0.0) + { + gEngfuncs.GetClientTime(); + g_flSpinDownTime[idx - 1] = 0.0 + 3.0; + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(ASSAULT_SPINDOWN, 2); + } + else if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(ASSAULT_SPINDOWN, 2); + + g_bACSpinning[idx - 1] = 0; + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan2.wav"); + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan4.wav"); + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_WEAPON, "weapons/asscan1.wav"); + if(!args->bparam1) + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/asscan3.wav", 0.98, 0.8, 0, 125); +} + +void EV_TFC_Assault_Start(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + g_flSpinDownTime[idx - 1] = 0; + g_flSpinUpTime[idx - 1] = 0; + g_bACSpinning[idx - 1] = 0; + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan2.wav"); + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan4.wav"); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_STATIC, "weapons/asscan3.wav", 0.98, 0.8, 0, 125); +} + +void EV_TFC_Assault_Fire(event_args_t *args) +{ + int idx; + int oddammo; + int shell; + vec3_t ShellOrigin, ShellVelocity; + vec3_t up, right, forward; + vec3_t vecSrc, vecAiming; + vec3_t origin, angles, velocity; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + VectorCopy(args->velocity, velocity); + oddammo = args->bparam1; + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/shell.mdl"); + gEngfuncs.pfnAngleVectors(angles, forward, right, up); + if(EV_IsLocal(idx)) + { + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation(ASSAULT_FIRE, 2); + } + g_bACSpinning[idx - 1] = 0; + if(oddammo) + { + EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 15.0, -25.0, 6.0); + EV_EjectBrass(ShellOrigin, ShellVelocity, angles.y, shell, TE_BOUNCE_SHELL); + } + EV_GetGunPosition(args, vecSrc, origin); + vecAiming = forward; + vecSrc.x = right.x + right.x + up.x * -4.0 + vecSrc.x; + vecSrc.y = right.y + right.y + up.y * -4.0 + vecSrc.y; + vecSrc.z = right.z + right.z + -4.0 * up.z + vecSrc.z; + EV_HLDM_FireBullets(idx, forward, right, up, 5, vecSrc, vecAiming, 0.1, 8192.0, BULLET_MONSTER_MP5, &tracerCount[idx - 1], 1.0, 8.0); +} + +void EV_TFC_Assault_Spin(event_args_t *args) +{ + int idx; + + idx = args->entindex; + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(ASSAULT_FIRE, 2); + g_bACSpinning[idx - 1] = 1; +} + +void EV_TFC_Assault_StartSpin(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + g_bACSpinning[idx - 1] = 1; + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan2.wav"); + gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_STATIC, "weapons/asscan4.wav"); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_STATIC, "weapons/asscan4.wav", 0.98, 0.8, 0, 125); +} + +void EV_TFC_Gas(event_args_t *args) +{ + vec3_t origin; + VectorCopy(args->origin, origin); + gEngfuncs.pEfxAPI->R_ParticleBurst(origin, 240, 195, 2.0); +} + +void EV_TFC_DoorGoUp(event_args_t *args) +{ + int index; + char sound[255]; + char num; + + index = args->iparam1; + num = (char)index; + + sprintf(sound,"doors/doormove%d.wav", num); + gEngfuncs.pEventAPI->EV_StopSound(-1, CHAN_STATIC, sound); + gEngfuncs.pEventAPI->EV_PlaySound(-1, args->origin, CHAN_STATIC, sound, 1.0, 1.0, 0, 100); +} + +void EV_TFC_DoorGoDown(event_args_t *args) +{ + int index; + char sound[255]; + char num; + + index = args->iparam1; + num = (char)index; + + sprintf(sound,"doors/doormove%d.wav", num); + gEngfuncs.pEventAPI->EV_StopSound(-1, CHAN_STATIC, sound); + gEngfuncs.pEventAPI->EV_PlaySound(-1, args->origin, CHAN_STATIC, sound, 1.0, 1.0, 0, 100); +} + +void EV_TFC_DoorHitTop(event_args_t *args) +{ + int index; + char sound[255]; + char num; + + index = args->iparam1; + num = (char)index; + + sprintf(sound,"doors/doormove%d.wav", num); + gEngfuncs.pEventAPI->EV_StopSound(-1, CHAN_STATIC, sound); + sound[255]; + sprintf(sound,"doors/doorstop%d.wav", num); + gEngfuncs.pEventAPI->EV_PlaySound(-1, args->origin, CHAN_STATIC, sound, 1.0, 1.0, 0, 100); +} + +void EV_TFC_DoorHitBottom(event_args_t *args) +{ + int index; + char sound[255]; + char num; + + index = args->iparam1; + num = (char)index; + + sprintf(sound,"doors/doormove%d.wav", num); + gEngfuncs.pEventAPI->EV_StopSound(-1, CHAN_STATIC, sound); + sound[255]; + sprintf(sound,"doors/doorstop%d.wav", num); + gEngfuncs.pEventAPI->EV_PlaySound(-1, args->origin, CHAN_STATIC, sound, 1.0, 1.0, 0, 100); +} + +void EV_TFC_Explode(float *org, int dmg, pmtrace_t *pTrace, qboolean bDontSpark) +{ + int pc; + bool outside; + int explosion; + float exp_scale; + float veca, vecb; + int fireball; + int decalindex; + physent_s *pe; + const char *vecc; + int explosion_outside; + int damage; + vec3_t origin; + float fExplosionScale; + + VectorCopy(org, origin); + + if(pTrace->fraction != 1.0) + { + if(dmg <= 23) + damage = dmg; + else + damage = dmg - 24; + fireball = (float)damage * 0.6; + VectorMA(pTrace->endpos, fireball, pTrace->plane.normal, origin); + } + pc = gEngfuncs.PM_PointContents(origin, 0); + if (pc != CONTENTS_SOLID) + { + outside = pc != -3; + explosion_outside = 0; + } + else + { + outside = 1; + explosion_outside = 1; + } + fExplosionScale = (float)(dmg - 50) * 0.6; + explosion = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/explode01.spr"); + exp_scale = 0.1 * fExplosionScale; + vecb = exp_scale; + gEngfuncs.pEfxAPI->R_Explosion(origin, explosion, vecb, 15, 3); + if ( !explosion_outside ) + { + veca = pTrace->ent; + if(gEngfuncs.pfnRandomFloat(0, 1.0) >= 0.5) + { + pe = gEngfuncs.pEventAPI->EV_GetPhysent((int)veca); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + if(gEngfuncs.pfnGetCvarFloat("r_decals") != 0.0) + decalindex = gEngfuncs.pEfxAPI->Draw_DecalIndexFromName("{scorch2"); + } + else + { + pe = gEngfuncs.pEventAPI->EV_GetPhysent((int)veca); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + if ( exp_scale != 0.0 ) + decalindex = gEngfuncs.pEfxAPI->Draw_DecalIndexFromName("{scorch1"); + } + gEngfuncs.pEfxAPI->R_DecalShoot(gEngfuncs.pEfxAPI->Draw_DecalIndex(decalindex), gEngfuncs.pEventAPI->EV_IndexFromTrace(pTrace), 0, pTrace->endpos, 0); + } + long rand = gEngfuncs.pfnRandomLong(0, 2); + if(rand == 1) + vecc = "weapons/debris2.wav"; + if(rand == 2) + vecc = "weapons/debris3.wav"; + if(!rand) + vecc = "weapons/debris1.wav"; + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_VOICE, vecc, 0.55, 0.8, 0, 100); + + if ( outside && !bDontSpark ) + { + long rand2 = gEngfuncs.pfnRandomLong(0, 3); + if ( rand2 > 0 ) + for(int x = 0; x < rand2; x++) + gEngfuncs.pEfxAPI->R_SparkShower(origin); + } +} + +void EV_TFC_Explosion(event_args_t *args) +{ + pmtrace_t tr; + vec3_t vecEnd; + vec3_t vecSpot; + vec3_t origin; + + VectorCopy(args->origin, origin); + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + EV_TFC_Explode(origin, 120, &tr, 0.0); +} + +void EV_TFC_Grenade(event_args_t *args) +{ + pmtrace_t tr; + vec3_t vecEnd; + vec3_t vecSpot; + vec3_t origin; + + VectorCopy(args->origin, origin); + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + EV_TFC_Explode(origin, 120, &tr, 0.0); +} + +void EV_TFC_NormalGrenade(event_args_t *args) +{ + pmtrace_t tr; + vec3_t vecEnd; + vec3_t vecSpot; + vec3_t origin; + + VectorCopy(args->origin, origin); + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + EV_TFC_Explode(origin, 180, &tr, 0.0); +} + +enum tfc_tfcrpg_e +{ + TFCRPG_IDLE = 0, + TFCRPG_FIDGET, + TFCRPG_FIRE, + TFCRPG_HOLSTER1, + TFCRPG_DRAW1, + TFCRPG_HOLSTER2, + TFCRPG_DRAW2, + TFCRPG_RELSTART, + TFCRPG_RELCYCLE, + TFCRPG_RELEND, + TFCRPG_IDLE2, + TFCRPG_FIDGET2 +}; + +void EV_TFC_FireRPG(event_args_t *args) +{ + int idx; + vec_t v2; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFCRPG_FIRE, 2); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, 0.8, 0, 100); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/glauncher.wav", 0.7, 0.8, 0, 100); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -5.0); +} + +void EV_FireTFCSniper(event_args_t *args) +{ + int idx; + physent_s *pe; + pmtrace_t tr; + int iDamage; + + vec3_t origin; + vec3_t angles; + vec3_t up, right, forward; + + vec3_t vecSrc, vecDir, vecEnd; + + idx = args->entindex; + iDamage = args->iparam1; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + AngleVectors(angles, forward, right, up); + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(SNIPER_FIRE, 2); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "ambience/rifle1.wav", 0.9, 0.8, 0, 100); + EV_GetGunPosition(args, vecSrc, origin); + vecDir = forward; + VectorMA(vecSrc, 2.0, up, vecSrc); + VectorMA(vecSrc, 8192.0, vecDir, vecEnd); + gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction(false, true); + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetSolidPlayers(idx - 1); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSrc, vecEnd, PM_STUDIO_BOX, -1, (pmtrace_s*)&up); + gEngfuncs.pEventAPI->EV_PopPMStates(); + + if ( tr.fraction != 1.0 ) + { + if(gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, vecDir, &tr, iDamage); + EV_HLDM_PlayTextureSound(idx, &tr, vecSrc, vecEnd, BULLET_PLAYER_357); + pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + EV_HLDM_DecalGunshot(&tr, BULLET_PLAYER_357); + } +} + + +void EV_TFC_SniperHit(event_args_s *args) +{ + int idx; + float volume; + char *sound; + vec3_t origin; + + VectorCopy(args->origin, origin); + idx = args->entindex; + volume = (float)args->iparam1 / 100.0; + if (args->bparam2) + { + sound = "common/bodysplat.wav"; + volume = 1.0; + } + else if (args->bparam1) + sound = "weapons/bullet_hit2.wav"; + else + sound = "weapons/bullet_hit1.wav"; + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_STATIC, sound, volume, 0.8, 0, 100); +} + +void EV_TFC_FireIC(event_args_t *args) +{ + int idx; + vec_t v2; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/sgun1.wav", 0.9, 0.8, 0, 100); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -5.0); +} + +void EV_TFC_NailgrenadeNail(event_args_t *args) +{ + int nail; + vec3_t origin, angles, forward, velocity, org; + + angles.x = 0; + angles.z = 0; + angles.y = (float)(args->iparam1 & 2047) * 0.25; + VectorCopy(args->origin, org); + nail = gEngfuncs.pEventAPI->EV_FindModelIndex("models/nail.mdl"); + angles.y = anglemod(args->fparam1 + angles.y); + gEngfuncs.pfnAngleVectors(angles, forward, 0, 0); + VectorMA(org, 12.0, forward, origin); + VectorScale(forward, 1000.0, velocity); + gEngfuncs.pEfxAPI->R_Projectile(origin, velocity, nail, 6, (args->iparam1 >> 11) & 31, EV_TFC_NailTouch); + if(!gEngfuncs.pfnRandomLong(0, 5)) + { + if (gEngfuncs.pfnRandomLong(0, 1) == 0) + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/airgun_1.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + else + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/spike2.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + } + angles.y = anglemod(args->fparam1 + angles.y); + gEngfuncs.pfnAngleVectors(angles, forward, 0, 0); + VectorMA(org, 12.0, forward, origin); + VectorScale(forward, 1000.0, velocity); + gEngfuncs.pEfxAPI->R_Projectile(origin, velocity, nail, 6, (args->iparam1 >> 11) & 31, EV_TFC_NailTouch); + if(!gEngfuncs.pfnRandomLong(0, 5)) + { + if (gEngfuncs.pfnRandomLong(0, 1) == 0) + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/airgun_1.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + else + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/spike2.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + } + angles.y = anglemod(args->fparam1 + angles.y); + gEngfuncs.pfnAngleVectors(angles, forward, 0, 0); + VectorMA(org, 12.0, forward, origin); + VectorScale(forward, 1000.0, velocity); + gEngfuncs.pEfxAPI->R_Projectile(origin, velocity, nail, 6, (args->iparam1 >> 11) & 31, EV_TFC_NailTouch); + if(!gEngfuncs.pfnRandomLong(0, 5)) + { + if (gEngfuncs.pfnRandomLong(0, 1) == 0) + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/airgun_1.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + else + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/spike2.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + } + angles.y = anglemod(args->fparam1 + angles.y); + gEngfuncs.pfnAngleVectors(angles, forward, 0, 0); + VectorMA(org, 12.0, forward, origin); + VectorScale(forward, 1000.0, velocity); + gEngfuncs.pEfxAPI->R_Projectile(origin, velocity, nail, 6, (args->iparam1 >> 11) & 31, EV_TFC_NailTouch); + if(!gEngfuncs.pfnRandomLong(0, 5)) + { + if (gEngfuncs.pfnRandomLong(0, 1) == 0) + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/airgun_1.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + else + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/spike2.wav", 1, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + } +} + +enum tfc_grenadelauncher_e +{ + TFGL_IDLE = 0, + TFPL_IDLE, + TFGL_FIRE, + TFPL_FIRE, + TFGL_RELOAD1, + TFGL_RELOAD2, + TFPL_RELOAD1, + TFPL_RELOAD2, + TFGL_DRAW, + TFPL_DRAW, + TFGL_HOLSTER, + TFPL_HOLSTER +}; + +void EV_TFC_GrenadeLauncher(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFGL_FIRE, 2); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/glauncher.wav", 0.7, 0.8, 0, 100); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -2.0); +} + +void EV_TFC_PipeLauncher(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(TFPL_FIRE, 2); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_WEAPON, "weapons/glauncher.wav", 0.7, 0.8, 0, 100); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -2.0); +} + +void EV_TFC_NormalShot(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_ITEM, "items/medshot4.wav", 1, 0.8, 0, 100); +} + + +void EV_TFC_SuperShot(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_ITEM, "items/medshot5.wav", 1, 0.8, 0, 100); +} + +void EV_TFC_SteamShot(event_args_t *args) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy(args->origin, origin); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_ITEM, "ambience/steamburst1.wav", 1, 0.8, 0, 100); +} + +void EV_TFC_AxeDecal(event_args_t *args) +{ + int idx; + pmtrace_t *tr; + physent_s *pe; + + idx = args->entindex; + tr = gp_tr_decal[idx-1]; + if (tr) + { + pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr->ent); + if ( pe && (pe->solid == 4 || pe->movetype == 13) ) + EV_HLDM_DecalGunshot(tr, BULLET_PLAYER_CROWBAR); + tr = 0; + } +} + +void EV_TFC_EngineerGrenade(event_args_t *args) +{ + pmtrace_t tr; + vec3_t vecEnd; + vec3_t vecSpot; + vec3_t origin; + + VectorCopy(args->origin, origin); + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + EV_TFC_Explode(origin, 180, &tr, 1.0); +} + +void EV_TFC_Concussion(event_args_t *args) +{ + int wave; + long rand; + const char *sound; + pmtrace_t tr; + vec3_t vecEnd, vecSpot, origin; + + VectorCopy(args->origin, origin) + wave = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/shockwave.spr"); + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + rand = gEngfuncs.pfnRandomLong(0, 2); + if(rand == 1) + sound = "weapons/concgren_blast2.wav"; + if(rand == 2) + sound = "weapons/concgren_blast3.wav"; + if (rand = 0) + sound = "weapons/concgren_blast1.wav"; + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_VOICE, sound, 1, 0.8, 0, 100); + vecSpot.z = origin.z + 16.0; + vecEnd.z = origin.z + 16.0 + 600.0; + gEngfuncs.pEfxAPI->R_BeamCirclePoints(21, vecSpot, vecEnd, wave, 0.2, 70, 0, 1.0, 0, 0, 0, 1.0, 1.0, 1.0); +} + +void EV_TFC_MirvGrenadeMain(event_args_t *args) +{ + EV_TFC_NormalGrenade(args); +} + +void EV_TFC_MirvGrenade(event_args_t *args) +{ + EV_TFC_NormalGrenade(args); +} + +void EV_TFC_NapalmFire(event_args_t *args) +{ + int explosion; + physent_s *pe; + int decalindex; + int decal; + const char *sound; + pmtrace_t tr; + vec3_t origin, vecSpot, vecEnd; + vec3_t org; + + VectorCopy(args->origin, origin) + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + if(tr.fraction != 1.0) + VectorMA(tr.endpos, 12.0, tr.plane.normal, org); + if(gEngfuncs.PM_PointContents(org, 0) == CONTENTS_SOLID && gEngfuncs.PM_PointContents(origin, 0) == CONTENTS_SOLID) + return; + explosion = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/explode01.spr"); + gEngfuncs.pEfxAPI->R_Explosion(org, explosion, 3, 15, 3); + if(gEngfuncs.pfnRandomFloat(0, 1.0) < 0.5) + { + pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + if(gEngfuncs.pfnGetCvarFloat("r_decals") != 0.0) + decalindex = gEngfuncs.pEfxAPI->Draw_DecalIndexFromName("{scorch1"); + } + else + { + pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + if(gEngfuncs.pfnGetCvarFloat("r_decals") != 0.0) + decalindex = gEngfuncs.pEfxAPI->Draw_DecalIndexFromName("{scorch2"); + } + if(decalindex != 0) + { + decal = gEngfuncs.pEfxAPI->Draw_DecalIndex(decalindex); + gEngfuncs.pEfxAPI->R_DecalShoot(decal, gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr), 0, tr.endpos, 0); + } + + switch(gEngfuncs.pfnRandomLong(0, 2)) + { + case 0: + sound = "weapons/debris1.wav"; + break; + case 1: + sound = "weapons/debris2.wav"; + break; + case 2: + sound = "weapons/debris3.wav"; + break; + } + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_VOICE, sound, 0.55, 0.8, 0, 100); +} + +void EV_TFC_NapalmBurn(event_args_t *args) +{ + int sprite; + vec3_t origin; + + VectorCopy(args->origin, origin); + sprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/playerflame.spr"); + gEngfuncs.pEfxAPI->R_FireField(origin, 100, sprite, 12, 18, 0.8); +} + +void EV_TFC_EMP(event_args_t *args) +{ + int sprite; + pmtrace_t tr; + vec3_t origin, vecSpot, vecEnd; + + sprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/shockwave.spr"); + VectorCopy(args->origin, origin) + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + gEngfuncs.pEventAPI->EV_PlaySound(-1, origin, CHAN_VOICE, "weapons/emp_1.wav", 1.0, 0.8, 0, 100); + vecSpot.z = origin.z + 16.0; + vecEnd.z = origin.z + 16.0 + 600.0; + gEngfuncs.pEfxAPI->R_BeamCirclePoints(21, vecSpot, vecEnd, sprite, 0.2, 70, 0, 1.0, 0, 0, 0, 1.0, 1.0, 0.0); +} + +void EV_TFC_Flame_Fire(event_args_t *args) +{ + int idx; + float height; + long double height2; + int underwater; + int shell; + int bubble; + vec3_t ShellOrigin, BubbleSpot, up, right, forward, vecVelocity, origin, angles; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + underwater = args->bparam1; + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/fthrow.spr"); + bubble = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/bubble.spr"); + gEngfuncs.pfnAngleVectors(angles, forward, right, up); + if(EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(5, 2); + EV_GetGunPosition(args, ShellOrigin, origin); + VectorMA(ShellOrigin, -8.0, up, ShellOrigin); + VectorMA(ShellOrigin, 8.0, right, ShellOrigin); + VectorMA(ShellOrigin, 16.0, forward, ShellOrigin); + if (!underwater) + { + VectorScale(forward, 600.0, vecVelocity); + gEngfuncs.pEfxAPI->R_Projectile(ShellOrigin, vecVelocity, shell, 1, idx, 0); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/flmfire2.wav", 0.9, 0.8, 0, 100); + return; + } + VectorMA(ShellOrigin, 128.0, forward, BubbleSpot); + height = EV_TFC_WaterLevel(ShellOrigin, ShellOrigin.z, ShellOrigin.z + 256.0); + if(height >= 8.0) + { + gEngfuncs.pEfxAPI->R_BubbleTrail(ShellOrigin, BubbleSpot, EV_TFC_WaterLevel(ShellOrigin, ShellOrigin.z, ShellOrigin.z + 256.0) - ShellOrigin.z, bubble, 4, 8.0); + return; + } + height2 = EV_TFC_WaterLevel(BubbleSpot, BubbleSpot.z, BubbleSpot.z + 256.0) - BubbleSpot.z; + if (height2 >= 8.0) + { + height = height2 + BubbleSpot.z - ShellOrigin.z; + gEngfuncs.pEfxAPI->R_BubbleTrail(ShellOrigin, BubbleSpot, EV_TFC_WaterLevel(ShellOrigin, ShellOrigin.z, ShellOrigin.z + 256.0) - ShellOrigin.z, bubble, 4, 8.0); + return; + } +} + +long double EV_TFC_WaterLevel(float *position, float minz, float maxz) +{ + long double result; + long double dif; + long double dif2; + float diff; + float minz_1; + + minz_1 = minz; + result = minz; + if(gEngfuncs.PM_PointContents(position, 0) == -3 ) + { + minz_1 = maxz; + if(gEngfuncs.PM_PointContents(position, 0) == -3 ) + result = maxz; + } + else + { + diff = minz; + dif = maxz - minz; + if(dif > 1.0) + { + while(1) + { + minz_1 = dif * 0.5 + diff; + if(gEngfuncs.PM_PointContents(position, 0) == -3) + { + result = minz_1; + diff = minz_1; + } + else + { + result = minz_1; + maxz = minz_1; + } + dif2 = maxz - diff; + if (dif2 <= 1.0) + break; + dif = dif2; + } + } + else + result = minz_1; + } + return result; +} + +void EV_TFC_Railgun(event_args_t *args) +{ + int idx; + pmtrace_t tr; + vec3_t ShellOrigin, vecSrc, vecEnd, tracerVelocity, right, up, forward, delta, origin, angles; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + gEngfuncs.pfnAngleVectors(angles, forward, right, up); + gEngfuncs.pEventAPI->EV_FindModelIndex("models/nail.mdl"); + if(EV_IsLocal(idx)) + { + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation(1, 2); + } + EV_GetGunPosition(args, ShellOrigin, origin); + VectorMA(ShellOrigin, -4.0, up, ShellOrigin); + VectorMA(ShellOrigin, 2.0, right, ShellOrigin); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/railgun.wav", 0.9, 0.8, 0, 100); + vecSrc = ShellOrigin; + VectorMA(vecSrc, 4096.0, forward, vecEnd); + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetSolidPlayers(idx - 1); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr); + delta.x = tr.endpos.x - vecSrc.x; + delta.y = tr.endpos.y - vecSrc.y; + delta.z = tr.endpos.z - vecSrc.z; + VectorScale(forward, 1500.0, tracerVelocity); + gEngfuncs.pEfxAPI->R_UserTracerParticle(ShellOrigin, tracerVelocity, Length(delta) / 1500.0, 2, 1.0, idx, EV_TFC_RailDie); + gEngfuncs.pEventAPI->EV_PopPMStates(); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -2.0); +} + +void EV_TFC_RailDie(particle_s *particle) +{ + physent_s *pe; + int idx2; + pmtrace_t tr; + char decalname[32]; + vec3_t forward, back, vecSrc, vecEnd; + + if (particle) + { + forward.x = particle->vel.x; + forward.y = particle->vel.y; + forward.z = particle->vel.z; + VectorNormalize(forward); + back = forward; + VectorInverse(back); + VectorMA(particle->org, 128.0, back, vecSrc); + VectorMA(vecSrc, 256.0, forward, vecEnd); + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetSolidPlayers(particle->context - 1); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr); + if(tr.ent != -1) + { + pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent); + idx2 = gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr); + if(!EV_IsPlayer(idx2) || EV_TFC_IsAlly(gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr), particle->context)) + { + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + { + decalname[0] = 0; + sprintf(decalname, "{shot%i", gEngfuncs.pfnRandomLong(0, 4) + 1); + if(decalname[0]) + { + if(tr.fraction != 1.0) + EV_HLDM_GunshotDecalTrace(&tr, decalname); + } + } + } + else if (gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + { + EV_TFC_BloodDrips(tr.endpos, 25, 0.0); + } + } + gEngfuncs.pEventAPI->EV_PopPMStates(); + } +} + +int EV_TFC_IsAlly(int idx1, int idx2) +{ + bool err; + signed int iPlayer1; + signed int iPlayer2; + int result; + long v10; + if (idx1 > 0 && idx1 <= gEngfuncs.GetMaxClients() && GetEntity(idx1) != 0 ) + { + iPlayer1 = GetEntity(idx1)->curstate.team; + err = iPlayer1 == -1; + } + else + { + err = 1; + iPlayer1 = -1; + } + if (idx1 < 0 || idx1 > gEngfuncs.GetMaxClients() || GetEntity(idx1) == 0 ) + return 0; + iPlayer2 = GetEntity(idx2)->curstate.team; + if(iPlayer2 == -1 || err || !iPlayer2 || !iPlayer1) + return 0; + result = 0; + if (!gEngfuncs.GetLocalPlayer()) + return result; + if(iPlayer2 > 4 || iPlayer2 > 4) + return 0; + v10 = strtol(gEngfuncs.PhysInfo_ValueForKey("ta"), 0, 10); + result = 1; + if (!(((v10 & 0x1F) + iPlayer1) >> (iPlayer2 - 1) & 1)); + result = iPlayer1 == iPlayer2; + return result; +} + +void EV_TFC_Tranquilizer(event_args_t *args) +{ + int idx; + int shell; + vec3_t ShellOrigin, vecVelocity, right, up, forward, origin, angles; + + idx = args->entindex; + VectorCopy(args->origin, origin); + VectorCopy(args->angles, angles); + gEngfuncs.pfnAngleVectors(angles, forward, right, up); + shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/nail.mdl"); + if(EV_IsLocal(idx)) + { + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 1); + } + EV_GetGunPosition(args, ShellOrigin, origin); + VectorMA(ShellOrigin, -4.0, up, ShellOrigin); + VectorMA(ShellOrigin, 2.0, right, ShellOrigin); + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/dartgun.wav", 0.9, 0.8, 0, 100); + VectorScale(forward, 1500.0, vecVelocity); + gEngfuncs.pEfxAPI->R_Projectile(ShellOrigin, vecVelocity, shell, 6, idx, EV_TFC_TranqNailTouch); + if(EV_IsLocal(idx)) + V_PunchAxis(0, -2.0); +} + +void EV_TFC_TranqNailTouch(tempent_s *ent, pmtrace_t *ptr) +{ + physent_s *pe; + char decalname[32]; + + if(gEngfuncs.pEventAPI->EV_IndexFromTrace(ptr) > 0 && gEngfuncs.pEventAPI->EV_IndexFromTrace(ptr) <= gEngfuncs.GetMaxClients() ) + { + decalname[0] = 0; + sprintf(decalname, "{shot%i", gEngfuncs.pfnRandomLong(0, 4) + 1); + } + else + { + decalname[0] = 0; + sprintf(decalname, "{shot%i", gEngfuncs.pfnRandomLong(0, 4) + 1); + pe = gEngfuncs.pEventAPI->EV_GetPhysent(ptr->ent); + if(pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)) + { + if (decalname[0]) + { + if(ptr->fraction != 1.0) + EV_HLDM_GunshotDecalTrace(ptr, decalname); + } + } + } +} + + +void EV_TFC_NailGrenade(event_args_t *args) +{ + pmtrace_t tr; + vec3_t vecEnd, vecSpot, origin; + + VectorCopy(args->origin, origin) + vecSpot.x = origin.x; + vecSpot.y = origin.y; + vecSpot.z = origin.z + 8.0; + vecEnd.x = origin.x; + vecEnd.y = origin.y; + vecEnd.z = origin.z + 8.0 - 40.0; + gEngfuncs.pEventAPI->EV_PushPMStates(); + gEngfuncs.pEventAPI->EV_SetTraceHull(2); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecSpot, vecEnd, PM_STUDIO_BOX, -1, &tr); + gEngfuncs.pEventAPI->EV_PopPMStates(); + EV_TFC_Explode(origin, 180, &tr, 78); +} + +void EV_TFC_Gibs(event_args_t *args) +{ + int idx; + int multiplier; + vec3_t origin, attackdir; + + idx = args->entindex; + VectorCopy(args->origin, origin) + VectorCopy(args->angles, attackdir) + multiplier = args->iparam1; + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "common/bodysplat.wav", 1.0, 0.8, 0, 100); +// for(int x = 0; x < 6; x++) +// EV_TFC_CreateGib(origin, attackdir, multiplier, 0); +// EV_TFC_CreateGib(origin, attackdir, multiplier, 1); +} + +void EV_TFC_PlayAxeSound(int idx, int classid, float *origin, int iSoundType, float fSoundData) +{ + if(classid == 2) + return; + + switch(iSoundType) + { + case 1: + { + switch(gEngfuncs.pfnRandomLong(0, 2)) + { + case 1: + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/cbar_hitbod2.wav", 1.0, 0.8, 0, 100); + case 2: + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/cbar_hitbod3.wav", 1.0, 0.8, 0, 100); + default: + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/cbar_hitbod1.wav", 1.0, 0.8, 0, 100); + } + } + break; + case 2: + { + switch(gEngfuncs.pfnRandomLong(0, 1)) + { + case 1: + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/cbar_hit2", fSoundData, 0.8, 0, gEngfuncs.pfnRandomLong(0, 3) + 98); + default: + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/cbar_hit1", fSoundData, 0.8, 0, gEngfuncs.pfnRandomLong(0, 3) + 98); + } + } + break; + default: + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1.0, 0.8, 0, gEngfuncs.pfnRandomLong(0, 15) + 94); + break; + } +} + +int EV_TFC_AxeHit(int idx, float *origin, float *forward, float *right, int entity, float *vecDir, pmtrace_t *ptr) +{ + cl_entity_s *ent; + Vector tf_0, tu, tr; + + if(entity > 0 && entity <= gEngfuncs.GetMaxClients()) + ent = GetEntity(entity - 1); + + if (entity > 0 + && entity <= gEngfuncs.GetMaxClients() + && ent != 0) + { + AngleVectors(ent->curstate.angles, tf_0, tu, tr); + if (tr.x * forward[1] - *forward * tr.y <= 0.0) + { + if (gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, vecDir, ptr, 40.0); + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(2, 2); + } + else + { + if (gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, vecDir, ptr, 120.0); + if (EV_IsLocal(idx)) + gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2); + } + } + else if (gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, vecDir, ptr, 20.0); + return 1; +} + +int EV_TFC_Medkit(int idx, float *origin, float *forward, float *right, int entity, float *vecDir, pmtrace_t *ptr) +{ + cl_entity_s *ent; + + if (entity > 0 && entity <= gEngfuncs.GetMaxClients()) + { + ent = GetEntity(entity - 1); + if (!EV_TFC_IsAlly(idx, entity)) + { + if (gEngfuncs.pfnGetCvarFloat("cl_localblood") != 0.0) + EV_TFC_TraceAttack(idx, vecDir, ptr, 10.0); + if (ent->curstate.playerclass != 5) + gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, 2, "player/death2.wav", 1.0, 0.8, 0, 100); + } + } + return 1; +} diff --git a/cl_dll/tfc/ev_tfc.h b/cl_dll/tfc/ev_tfc.h new file mode 100644 index 00000000..4e41617e --- /dev/null +++ b/cl_dll/tfc/ev_tfc.h @@ -0,0 +1,42 @@ +//========= Copyright 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#if !defined ( EV_HLDMH ) +#define EV_HLDMH + +// bullet types +typedef enum +{ + BULLET_NONE = 0, + BULLET_PLAYER_9MM, // glock + BULLET_PLAYER_MP5, // mp5 + BULLET_PLAYER_357, // python + BULLET_PLAYER_BUCKSHOT, // shotgun + BULLET_PLAYER_CROWBAR, // crowbar swipe + + BULLET_MONSTER_9MM, + BULLET_MONSTER_MP5, + BULLET_MONSTER_12MM +}Bullet; + +void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName ); +void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType ); +int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount ); +void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY ); +void EV_TFC_NailTouch( struct tempent_s *ent, pmtrace_t *ptr ); +void EV_TFC_Explode( float *org, int dmg, pmtrace_t *pTrace, qboolean bDontSpark ); +void EV_TFC_BloodDrips( float *vecOrigin, signed int iDamage, long double height ); +void EV_TFC_TraceAttack( int idx, float *vecDir, pmtrace_t *ptr, float flDamage ); +long double EV_TFC_WaterLevel( float *position, float minz, float maxz ); +void EV_TFC_RailDie( struct particle_s *particle ); +int EV_TFC_IsAlly( int idx1, int idx2 ); +void EV_TFC_TranqNailTouch( tempent_s *ent, pmtrace_t *ptr ); +void EV_TFC_PlayAxeSound( int idx, int classid, float *origin, int iSoundType, float fSoundData ); +int EV_TFC_AxeHit(int idx, float *origin, float *forward, float *right, int entity, float *vecDir, pmtrace_t *ptr); +int EV_TFC_Medkit(int idx, float *origin, float *forward, float *right, int entity, float *vecDir, pmtrace_t *ptr); +//tempent_s EV_TFC_CreateGib(float *origin, float *attackdir, int multiplier, int ishead); +#endif // EV_HLDMH diff --git a/cl_dll/tfc/tfc_events.cpp b/cl_dll/tfc/tfc_events.cpp new file mode 100644 index 00000000..b80b524e --- /dev/null +++ b/cl_dll/tfc/tfc_events.cpp @@ -0,0 +1,129 @@ +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "../hud.h" +#include "../cl_util.h" +#include "event_api.h" + +extern "C" +{ +void EV_TFC_Axe( struct event_args_s *args ); +void EV_FireTFCShotgun( struct event_args_s *args ); +void EV_FireTFCSuperShotgun( struct event_args_s *args ); +void EV_ReloadTFCShotgun( struct event_args_s *args ); +void EV_PumpTFCShotgun( struct event_args_s *args ); +void EV_FireTFCNailgun( struct event_args_s *args ); +void EV_FireTFCSuperNailgun( struct event_args_s *args ); +void EV_FireTFCAutoRifle( struct event_args_s *args ); +void EV_TFC_Gas( struct event_args_s *args ); +void EV_TFC_DoorGoUp( struct event_args_s *args ); +void EV_TFC_DoorGoDown( struct event_args_s *args ); +void EV_TFC_DoorHitTop( struct event_args_s *args ); +void EV_TFC_DoorHitBottom( struct event_args_s *args ); +void EV_TFC_Explosion( struct event_args_s *args ); +void EV_TFC_Grenade( struct event_args_s *args ); +void EV_TFC_NormalGrenade( struct event_args_s *args ); +void EV_TFC_FireRPG( struct event_args_s *args ); +void EV_FireTFCSniper( struct event_args_s *args ); +void EV_TFC_SniperHit( struct event_args_s *args ); +void EV_TFC_FireIC( struct event_args_s *args ); +void EV_TFC_NailgrenadeNail( struct event_args_s *args ); +void EV_TFC_GrenadeLauncher( struct event_args_s *args ); +void EV_TFC_PipeLauncher( struct event_args_s *args ); +void EV_TFC_NormalShot( struct event_args_s *args ); +void EV_TFC_SuperShot( struct event_args_s *args ); +void EV_TFC_SteamShot( struct event_args_s *args ); +void EV_TFC_EngineerGrenade( struct event_args_s *args ); +void EV_TFC_Concussion( struct event_args_s *args ); +void EV_TFC_Assault_WindUp( struct event_args_s *args ); +void EV_TFC_Assault_WindDown( struct event_args_s *args ); +void EV_TFC_Assault_Start( struct event_args_s *args ); +void EV_TFC_Assault_Fire( struct event_args_s *args ); +void EV_TFC_Assault_Spin( struct event_args_s *args ); +void EV_TFC_Assault_StartSpin( struct event_args_s *args ); +void EV_TFC_AxeDecal( struct event_args_s *args ); +void EV_TFC_NapalmFire( struct event_args_s *args ); +void EV_TFC_MirvGrenadeMain( struct event_args_s *args ); +void EV_TFC_MirvGrenade( struct event_args_s *args ); +void EV_TFC_NapalmBurn( struct event_args_s *args ); +void EV_TFC_EMP( struct event_args_s *args ); +void EV_TFC_Flame_Fire( struct event_args_s *args ); +void EV_TFC_Railgun( struct event_args_s *args ); +void EV_TFC_Tranquilizer( struct event_args_s *args ); +void EV_TFC_NailGrenade( struct event_args_s *args ); + +void EV_TrainPitchAdjust( struct event_args_s *args ); +} + +/* +====================== +Game_HookEvents + +Associate script file name with callback functions. Callback's must be extern "C" so + the engine doesn't get confused about name mangling stuff. Note that the format is + always the same. Of course, a clever mod team could actually embed parameters, behavior + into the actual .sc files and create a .sc file parser and hook their functionality through + that.. i.e., a scripting system. + +That was what we were going to do, but we ran out of time...oh well. +====================== +*/ +void Game_HookEvents( void ) +{ + gEngfuncs.pfnHookEvent("events/wpn/tf_axe.sc", EV_TFC_Axe); + gEngfuncs.pfnHookEvent("events/wpn/tf_sg.sc", EV_FireTFCShotgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_sgreload.sc", EV_ReloadTFCShotgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_sgpump.sc", EV_PumpTFCShotgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_nail.sc", EV_FireTFCNailgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_snail.sc", EV_FireTFCSuperNailgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_ssg.sc", EV_FireTFCSuperShotgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_ar.sc", EV_FireTFCAutoRifle); + gEngfuncs.pfnHookEvent("events/explode/tf_gas.sc", EV_TFC_Gas); + gEngfuncs.pfnHookEvent("events/door/doorgoup.sc", EV_TFC_DoorGoUp); + gEngfuncs.pfnHookEvent("events/door/doorgodown.sc", EV_TFC_DoorGoDown); + gEngfuncs.pfnHookEvent("events/door/doorhittop.sc", EV_TFC_DoorHitTop); + gEngfuncs.pfnHookEvent("events/door/doorhitbottom.sc", EV_TFC_DoorHitBottom); + gEngfuncs.pfnHookEvent("events/explode/tf_pipe.sc", EV_TFC_Explosion); + gEngfuncs.pfnHookEvent("events/explode/tf_gren.sc", EV_TFC_Grenade); + gEngfuncs.pfnHookEvent("events/explode/tf_normalgren.sc", EV_TFC_NormalGrenade); + gEngfuncs.pfnHookEvent("events/wpn/tf_rpg.sc", EV_TFC_FireRPG); + gEngfuncs.pfnHookEvent("events/wpn/tf_sniper.sc", EV_FireTFCSniper); + gEngfuncs.pfnHookEvent("events/wpn/tf_sniperhit.sc", EV_TFC_SniperHit); + gEngfuncs.pfnHookEvent("events/wpn/tf_ic.sc", EV_TFC_FireIC); + gEngfuncs.pfnHookEvent("events/explode/tf_nailgren.sc", EV_TFC_NailgrenadeNail); + gEngfuncs.pfnHookEvent("events/wpn/tf_gl.sc", EV_TFC_GrenadeLauncher); + gEngfuncs.pfnHookEvent("events/wpn/tf_pipel.sc", EV_TFC_PipeLauncher); + gEngfuncs.pfnHookEvent("events/wpn/tf_mednormal.sc", EV_TFC_NormalShot); + gEngfuncs.pfnHookEvent("events/wpn/tf_medsuper.sc", EV_TFC_SuperShot); + gEngfuncs.pfnHookEvent("events/wpn/tf_medsteam.sc", EV_TFC_SteamShot); + gEngfuncs.pfnHookEvent("events/explode/tf_engrgren.sc", EV_TFC_EngineerGrenade); + gEngfuncs.pfnHookEvent("events/explode/tf_concuss.sc", EV_TFC_Concussion); + gEngfuncs.pfnHookEvent("events/wpn/tf_acwu.sc", EV_TFC_Assault_WindUp); + gEngfuncs.pfnHookEvent("events/wpn/tf_acwd.sc", EV_TFC_Assault_WindDown); + gEngfuncs.pfnHookEvent("events/wpn/tf_acstart.sc", EV_TFC_Assault_Start); + gEngfuncs.pfnHookEvent("events/wpn/tf_acfire.sc", EV_TFC_Assault_Fire); + gEngfuncs.pfnHookEvent("events/wpn/tf_acspin.sc", EV_TFC_Assault_Spin); + gEngfuncs.pfnHookEvent("events/wpn/tf_acsspin.sc", EV_TFC_Assault_StartSpin); + gEngfuncs.pfnHookEvent("events/wpn/tf_axedecal.sc", EV_TFC_AxeDecal); + gEngfuncs.pfnHookEvent("events/explode/tf_mirvmain.sc", EV_TFC_MirvGrenadeMain); + gEngfuncs.pfnHookEvent("events/explode/tf_mirv.sc", EV_TFC_MirvGrenade); + gEngfuncs.pfnHookEvent("events/explode/tf_fire.sc", EV_TFC_NapalmFire); + gEngfuncs.pfnHookEvent("events/explode/tf_burn.sc", EV_TFC_NapalmBurn); + gEngfuncs.pfnHookEvent("events/explode/tf_emp.sc", EV_TFC_EMP); + gEngfuncs.pfnHookEvent("events/wpn/tf_flame.sc", EV_TFC_Flame_Fire); + gEngfuncs.pfnHookEvent("events/wpn/tf_rail.sc", EV_TFC_Railgun); + gEngfuncs.pfnHookEvent("events/wpn/tf_tranq.sc", EV_TFC_Tranquilizer); + gEngfuncs.pfnHookEvent("events/explode/tf_ng.sc", EV_TFC_NailGrenade); +} diff --git a/cl_dll/hl/hl_weapons.cpp b/cl_dll/tfc/tfc_weapons.cpp similarity index 91% rename from cl_dll/hl/hl_weapons.cpp rename to cl_dll/tfc/tfc_weapons.cpp index 75161a9e..0c945ba9 100644 --- a/cl_dll/hl/hl_weapons.cpp +++ b/cl_dll/tfc/tfc_weapons.cpp @@ -21,6 +21,8 @@ #include "nodes.h" #include "player.h" +#include "tf_defs.h" + #include "usercmd.h" #include "entity_state.h" #include "demo_api.h" @@ -52,21 +54,21 @@ int g_irunninggausspred = 0; vec3_t previousorigin; -// HLDM Weapon placeholder entities. -CGlock g_Glock; -CCrowbar g_Crowbar; -CPython g_Python; -CMP5 g_Mp5; -CCrossbow g_Crossbow; -CShotgun g_Shotgun; -CRpg g_Rpg; -CGauss g_Gauss; -CEgon g_Egon; -CHgun g_HGun; -CHandGrenade g_HandGren; -CSatchel g_Satchel; -CTripmine g_Tripmine; -CSqueak g_Snark; +// TFC Weapons +CTFShotgun g_TFShotgun; +CTFSuperShotgun g_TFSuperShotgun; +CTFNailgun g_TFNailgun; +CTFSuperNailgun g_TFSuperNailgun; +CTFSniperRifle g_TFSniperRifle; +CTFRpg g_TFRpg; +CTFIncendiaryC g_TFIncediaryC; +CTFFlamethrower g_TFFlamethrower; +CTFAxe g_TFAxe; +CTFSpanner g_TFSpanner; +CTFRailgun g_TFRailgun; +CTFGrenadeLauncher g_TFGrenadeLauncher; +CTFAssaultC g_TFAssaultC; +CTFPipebombLauncher g_TFPipebombLauncher; /* ====================== @@ -602,20 +604,20 @@ void HUD_InitClientWeapons( void ) HUD_PrepEntity( &player, NULL ); // Allocate slot(s) for each weapon that we are going to be predicting - HUD_PrepEntity( &g_Glock, &player ); - HUD_PrepEntity( &g_Crowbar, &player ); - HUD_PrepEntity( &g_Python, &player ); - HUD_PrepEntity( &g_Mp5, &player ); - HUD_PrepEntity( &g_Crossbow, &player ); - HUD_PrepEntity( &g_Shotgun, &player ); - HUD_PrepEntity( &g_Rpg, &player ); - HUD_PrepEntity( &g_Gauss, &player ); - HUD_PrepEntity( &g_Egon, &player ); - HUD_PrepEntity( &g_HGun, &player ); - HUD_PrepEntity( &g_HandGren, &player ); - HUD_PrepEntity( &g_Satchel, &player ); - HUD_PrepEntity( &g_Tripmine, &player ); - HUD_PrepEntity( &g_Snark, &player ); + HUD_PrepEntity( &g_TFShotgun, &player ); + HUD_PrepEntity( &g_TFSuperShotgun, &player ); + HUD_PrepEntity( &g_TFNailgun, &player ); + HUD_PrepEntity( &g_TFSuperNailgun, &player ); + HUD_PrepEntity( &g_TFSniperRifle, &player ); + HUD_PrepEntity( &g_TFRpg, &player ); + HUD_PrepEntity( &g_TFIncediaryC, &player ); + HUD_PrepEntity( &g_TFFlamethrower, &player ); + HUD_PrepEntity( &g_TFAxe, &player ); + HUD_PrepEntity( &g_TFSpanner, &player ); + HUD_PrepEntity( &g_TFRailgun, &player ); + HUD_PrepEntity( &g_TFGrenadeLauncher, &player ); + HUD_PrepEntity( &g_TFAssaultC, &player ); + HUD_PrepEntity( &g_TFPipebombLauncher, &player ); } /* @@ -679,47 +681,71 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm // FIXME, make this a method in each weapon? where you pass in an entity_state_t *? switch( from->client.m_iId ) { - case WEAPON_CROWBAR: - pWeapon = &g_Crowbar; + case WEAPON_HOOK: + //pWeapon = &; break; - case WEAPON_GLOCK: - pWeapon = &g_Glock; + case WEAPON_BIOWEAPON: + //pWeapon = &; break; - case WEAPON_PYTHON: - pWeapon = &g_Python; + case WEAPON_SPANNER: + pWeapon = &g_TFSpanner; break; - case WEAPON_MP5: - pWeapon = &g_Mp5; + case WEAPON_AXE: + pWeapon = &g_TFAxe; break; - case WEAPON_CROSSBOW: - pWeapon = &g_Crossbow; + case WEAPON_SNIPER_RIFLE: + pWeapon = &g_TFSniperRifle; break; - case WEAPON_SHOTGUN: - pWeapon = &g_Shotgun; + case WEAPON_AUTO_RIFLE: + //pWeapon = &; break; - case WEAPON_RPG: - pWeapon = &g_Rpg; + case WEAPON_TF_SHOTGUN: + pWeapon = &g_TFShotgun; break; - case WEAPON_GAUSS: - pWeapon = &g_Gauss; + case WEAPON_SUPER_SHOTGUN: + pWeapon = &g_TFSuperShotgun; break; - case WEAPON_EGON: - pWeapon = &g_Egon; + case WEAPON_NAILGUN: + pWeapon = &g_TFNailgun; break; - case WEAPON_HORNETGUN: - pWeapon = &g_HGun; + case WEAPON_SUPER_NAILGUN: + pWeapon = &g_TFSuperNailgun; break; - case WEAPON_HANDGRENADE: - pWeapon = &g_HandGren; + case WEAPON_GRENADE_LAUNCHER: + pWeapon = &g_TFGrenadeLauncher; break; - case WEAPON_SATCHEL: - pWeapon = &g_Satchel; + case WEAPON_FLAMETHROWER: + pWeapon = &g_TFFlamethrower; break; - case WEAPON_TRIPMINE: - pWeapon = &g_Tripmine; + case WEAPON_ROCKET_LAUNCHER: + pWeapon = &g_TFRpg; break; - case WEAPON_SNARK: - pWeapon = &g_Snark; + case WEAPON_INCENDIARY: + pWeapon = &g_TFIncediaryC; + break; + case WEAPON_ASSAULT_CANNON: + pWeapon = &g_TFAssaultC; + break; + case WEAPON_LIGHTNING: + //pWeapon = &; + break; + case WEAPON_DETPACK: + //pWeapon = &; + break; + case WEAPON_TRANQ: + //pWeapon = &; + break; + case WEAPON_LASER: + pWeapon = &g_TFRailgun; + break; + case WEAPON_PIPEBOMB_LAUNCHER: + pWeapon = &g_TFPipebombLauncher; + break; + case WEAPON_KNIFE: + //pWeapon = &; + break; + case WEAPON_BENCHMARK: + //pWeapon = &; break; } @@ -824,13 +850,13 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm { player.m_pActiveItem = g_pWpns[from->client.m_iId]; } - +/* if( player.m_pActiveItem->m_iId == WEAPON_RPG ) { ( (CRpg *)player.m_pActiveItem )->m_fSpotActive = (int)from->client.vuser2[1]; ( (CRpg *)player.m_pActiveItem )->m_cActiveRockets = (int)from->client.vuser2[2]; } - +*/ // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed if( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && @@ -892,7 +918,7 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm to->client.ammo_cells = player.ammo_uranium; to->client.vuser2[0] = player.ammo_hornets; to->client.ammo_rockets = player.ammo_rockets; - +/* if( player.m_pActiveItem->m_iId == WEAPON_RPG ) { from->client.vuser2[1] = ( (CRpg *)player.m_pActiveItem)->m_fSpotActive; @@ -916,7 +942,7 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, body, 1 ); } - +*/ for( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[i]; diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index daecc3af..96f8d219 100644 --- a/cl_dll/view.cpp +++ b/cl_dll/view.cpp @@ -1313,21 +1313,21 @@ int V_FindViewModelByWeaponModel( int weaponindex ) { static const char *modelmap[][2] = { - { "models/p_crossbow.mdl", "models/v_crossbow.mdl" }, - { "models/p_crowbar.mdl", "models/v_crowbar.mdl" }, - { "models/p_egon.mdl", "models/v_egon.mdl" }, - { "models/p_gauss.mdl", "models/v_gauss.mdl" }, - { "models/p_9mmhandgun.mdl", "models/v_9mmhandgun.mdl" }, - { "models/p_grenade.mdl", "models/v_grenade.mdl" }, - { "models/p_hgun.mdl", "models/v_hgun.mdl" }, - { "models/p_9mmAR.mdl", "models/v_9mmAR.mdl" }, - { "models/p_357.mdl", "models/v_357.mdl" }, - { "models/p_rpg.mdl", "models/v_rpg.mdl" }, - { "models/p_shotgun.mdl", "models/v_shotgun.mdl" }, - { "models/p_squeak.mdl", "models/v_squeak.mdl" }, - { "models/p_tripmine.mdl", "models/v_tripmine.mdl" }, - { "models/p_satchel_radio.mdl", "models/v_satchel_radio.mdl" }, - { "models/p_satchel.mdl", "models/v_satchel.mdl" }, + { "models/p_mini.mdl", "models/v_tfac.mdl" }, + { "models/p_sniper.mdl", "models/v_tfc_sniper.mdl" }, + { "models/p_umbrella.mdl", "models/v_umbrella.mdl" }, + { "models/p_crowbar.mdl", "models/v_tfc_crowbar.mdl" }, + { "models/p_spanner.mdl", "models/v_tfc_spanner.mdl" }, + { "models/p_knife.mdl", "models/v_tfc_knife.mdl" }, + { "models/p_medkit.mdl", "models/v_tfc_medkit.mdl" }, + { "models/p_egon.mdl", "models/v_flame.mdl" }, + { "models/p_glauncher.mdl", "models/v_tfgl.mdl" }, + { "models/p_rpg.mdl", "models/v_tfc_rpg.mdl" }, + { "models/p_nailgun.mdl", "models/v_tfc_nailgun.mdl" }, + { "models/p_snailgun.mdl", "models/v_tfc_supernailgun.mdl" }, + { "models/p_9mmhandgun.mdl", "models/v_tfc_railgun.mdl" }, + { "models/p_srpg.mdl", "models/v_tfc_rpg.mdl" }, + { "models/p_smallshotgun.mdl", "models/v_tfc_12gauge.mdl" }, { NULL, NULL } }; diff --git a/dlls/tfc/assaultcannon.cpp b/dlls/tfc/assaultcannon.cpp new file mode 100644 index 00000000..e6631758 --- /dev/null +++ b/dlls/tfc/assaultcannon.cpp @@ -0,0 +1,188 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_ac, CTFAssaultC ) + +void CTFAssaultC::Spawn() +{ + Precache(); + + m_iId = 17; + m_iDefaultAmmo = 25; + m_iWeaponState = 0; + pev->solid = SOLID_TRIGGER; +} + +int CTFAssaultC::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "buckshot"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 200; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 4; + p->iPosition = 3; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 17; + p->iWeight = 15; + return 1; +} + +void CTFAssaultC::Holster() +{ + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usWindDown, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 1, 0); + m_iWeaponState = 0; + //tfstate + //setspeed + m_fInReload = 0; + m_flTimeWeaponIdle = 2; + m_pPlayer->m_flNextAttack = 0.1; + SendWeaponAnim(ASSAULT_HOLSTER, 1); +} + +void CTFAssaultC::Precache() +{ + PRECACHE_MODEL("models/v_tfac.mdl"); + PRECACHE_MODEL("models/p_mini.mdl"); + PRECACHE_MODEL("models/p_mini2.mdl"); + m_iShell = PRECACHE_MODEL("models/shell.mdl"); + PRECACHE_SOUND("weapons/357_cock1.wav"); + PRECACHE_SOUND("weapons/asscan1.wav"); + PRECACHE_SOUND("weapons/asscan2.wav"); + PRECACHE_SOUND("weapons/asscan3.wav"); + PRECACHE_SOUND("weapons/asscan4.wav"); + m_usWindUp = PRECACHE_EVENT(1, "events/wpn/tf_acwu.sc"); + m_usWindDown = PRECACHE_EVENT(1, "events/wpn/tf_acwd.sc"); + m_usFire = PRECACHE_EVENT(1, "events/wpn/tf_acfire.sc"); + m_usStartSpin = PRECACHE_EVENT(1, "events/wpn/tf_acsspin.sc"); + m_usSpin = PRECACHE_EVENT(1, "events/wpn/tf_acspin.sc"); + m_usACStart = PRECACHE_EVENT(1, "events/wpn/tf_acstart.sc"); +} + +void CTFAssaultC::WeaponIdle( void ) +{ + ResetEmptySound(); + + if(m_flTimeWeaponIdle <= 0.0) + { + if(m_iWeaponState) + { + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usWindDown, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_iWeaponState = 0; + //tfstate + //setspeed + m_flTimeWeaponIdle = 2; + } + else + { + SendWeaponAnim(RANDOM_LONG(0, 1), 1); + m_flTimeWeaponIdle = 12.5; + } + } +} + +BOOL CTFAssaultC::Deploy() +{ + //Velaron: "ac" deploy + return DefaultDeploy( "models/v_tfac.mdl", "models/p_mini.mdl", ASSAULT_DRAW, "mp5", 1 ); +} + +int CTFAssaultC::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFAssaultC::PrimaryAttack() +{ + if(m_iWeaponState == 2) + { + if(m_pPlayer->ammo_buckshot <= 0) + { + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usStartSpin, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_iWeaponState = 3; + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + pev->effects &= ~EF_MUZZLEFLASH; + } + else + Fire(); + + m_flTimeWeaponIdle = 0.1; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; + return; + } + if(m_iWeaponState == 3) + { + if(m_pPlayer->ammo_buckshot <= 0) + { + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usSpin, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + } + else + { + m_iWeaponState = 1; + } + m_flTimeWeaponIdle = 0.1; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; + return; + } + if(m_iWeaponState == 1) + { + if(m_flNextPrimaryAttack > 0.0) + return; + + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usACStart, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_iWeaponState = 2; + m_flTimeWeaponIdle = 0.1; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; + return; + } + + if(m_pPlayer->pev->button & 1) + { + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usWindUp, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_iWeaponState = 1; + //tfstate + //setspeed + } + + m_flTimeWeaponIdle = 0.6; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; +} + +void CTFAssaultC::Fire() +{ + vec3_t p_vecSrc, vecAiming, vecSpread; + + if(m_flNextPrimaryAttack > 0) + return; + + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usWindUp, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, m_pPlayer->ammo_buckshot & 1, 0); + m_pPlayer->m_iWeaponVolume = 600; + m_pPlayer->m_iWeaponFlash = 256; + m_pPlayer->pev->effects |= EF_MUZZLEFLASH; + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + UTIL_MakeVectors(m_pPlayer->pev->v_angle); + p_vecSrc.x = gpGlobals->v_up.x * -4.0 + gpGlobals->v_right.x + gpGlobals->v_right.x + m_pPlayer->pev->origin.x + m_pPlayer->pev->view_ofs.x; + p_vecSrc.y = gpGlobals->v_up.y * -4.0 + gpGlobals->v_right.y + gpGlobals->v_right.y + m_pPlayer->pev->origin.y + m_pPlayer->pev->view_ofs.y; + p_vecSrc.z = gpGlobals->v_up.z * -4.0 + gpGlobals->v_right.z + gpGlobals->v_right.z + m_pPlayer->pev->origin.z + m_pPlayer->pev->view_ofs.z; + vecAiming = m_pPlayer->GetAutoaimVector(0.087155744); + vecSpread.x = 0.1; + vecSpread.y = 0.1; + vecSpread.z = 0.0; + FireBullets(5, p_vecSrc, vecAiming, vecSpread, 8192.0, 7, 8, 7, 0); + m_pPlayer->ammo_buckshot--; +} \ No newline at end of file diff --git a/dlls/tfc/axe.cpp b/dlls/tfc/axe.cpp new file mode 100644 index 00000000..f6505a0c --- /dev/null +++ b/dlls/tfc/axe.cpp @@ -0,0 +1,93 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_axe, CTFAxe ) + +void CTFAxe::Spawn() +{ + Precache(); + + m_iId = 5; + m_iClip = -1; + pev->solid = SOLID_TRIGGER; +} + +int CTFAxe::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = 0; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = -1; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 0; + p->iPosition = 3; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 5; + p->iWeight = 0; + return 1; +} + +void CTFAxe::Holster() +{ + SendWeaponAnim(AXE_HOLSTER, 1); + m_pPlayer->m_flNextAttack = 0.5; +} + +void CTFAxe::Precache() +{ + PRECACHE_MODEL("models/v_umbrella.mdl"); + PRECACHE_MODEL("models/p_umbrella.mdl"); + PRECACHE_MODEL("models/v_tfc_crowbar.mdl"); + PRECACHE_MODEL("models/p_crowbar.mdl"); + PRECACHE_MODEL("models/p_crowbar2.mdl"); + PRECACHE_SOUND("weapons/cbar_hit1.wav"); + PRECACHE_SOUND("weapons/cbar_hit2.wav"); + PRECACHE_SOUND("weapons/cbar_hitbod1.wav"); + PRECACHE_SOUND("weapons/cbar_hitbod2.wav"); + PRECACHE_SOUND("weapons/cbar_hitbod3.wav"); + PRECACHE_SOUND("weapons/cbar_miss1.wav"); + classid = 3; + m_usAxe = PRECACHE_EVENT(1, "events/wpn/tf_axe.sc"); + m_usAxeDecal = PRECACHE_EVENT(1, "events/wpn/tf_axedecal.sc"); +} + +BOOL CTFAxe::Deploy() +{ + if(m_pPlayer->pev->playerclass == 11) + return DefaultDeploy( "models/v_umbrella.mdl", "models/p_umbrella.mdl", AXE_DRAW, "crowbar", 1 ); + else + return DefaultDeploy( "models/v_tfc_crowbar.mdl", "models/p_crowbar.mdl", AXE_DRAW, "crowbar", 1 ); +} +//Velaron: finish this? +void CTFAxe::PrimaryAttack() +{ + vec3_t vecSrc, vecEnd; + TraceResult tr; + + m_bHullHit = 0; + UTIL_MakeVectors(m_pPlayer->pev->v_angle); + vecSrc = m_pPlayer->GetGunPosition(); + vecEnd.x = gpGlobals->v_forward.x * 32.0 + vecSrc.x; + vecEnd.y = gpGlobals->v_forward.y * 32.0 + vecSrc.y; + vecEnd.z = gpGlobals->v_forward.z * 32.0 + vecSrc.z; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usAxe, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, classid, 0, 0, 0); + if ( tr.flFraction >= 1.0 ) + { + m_bHullHit = 1; + //m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.4; + m_flNextPrimaryAttack = 1.0; + m_flTimeWeaponIdle = 5; + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + return; + } + m_flNextPrimaryAttack = 1.0; + m_flTimeWeaponIdle = 5; + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); +} \ No newline at end of file diff --git a/dlls/tfc/flamethrower.cpp b/dlls/tfc/flamethrower.cpp new file mode 100644 index 00000000..5ab5ab31 --- /dev/null +++ b/dlls/tfc/flamethrower.cpp @@ -0,0 +1,120 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_flamethrower, CTFFlamethrower ) + +void CTFFlamethrower::Spawn() +{ + Precache(); + + m_iId = 13; + SET_MODEL(ENT(pev), "models/w_egon.mdl"); + m_iDefaultAmmo = 50; + pev->solid = SOLID_TRIGGER; +} + +int CTFFlamethrower::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "uranium"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 200; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 3; + p->iPosition = 2; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 13; + p->iWeight = 20; + return 1; +} + +void CTFFlamethrower::Holster() +{ + m_fInReload = 0; + SendWeaponAnim(10, 1); + m_pPlayer->m_flNextAttack = 0.5; +} + +void CTFFlamethrower::Precache() +{ + PRECACHE_MODEL("models/w_egon.mdl"); + PRECACHE_MODEL("models/v_flame.mdl"); + PRECACHE_MODEL("models/p_egon.mdl"); + PRECACHE_MODEL("models/p_egon2.mdl"); + PRECACHE_MODEL("models/w_9mmclip.mdl"); + PRECACHE_SOUND("weapons/9mmclip1.wav"); + UTIL_PrecacheOther("tf_flamethrower_burst"); + PRECACHE_SOUND("weapons/flmfire2.wav"); + m_usFireFlame = PRECACHE_EVENT(1, "events/wpn/tf_flame.sc"); +} + +void CTFFlamethrower::WeaponIdle( void ) +{ + ResetEmptySound(); + + if(m_flTimeWeaponIdle <= 0.0) + { + if(UTIL_SharedRandomLong(m_pPlayer->random_seed, 0, 4)) + { + m_flTimeWeaponIdle = 12.5; + SendWeaponAnim(0, 1); + } + else + { + m_flTimeWeaponIdle = 3; + SendWeaponAnim(1, 1); + } + } +} + +BOOL CTFFlamethrower::Deploy() +{ + return DefaultDeploy( "models/v_flame.mdl", "models/p_egon.mdl", 5, "egon", 1 ); +} + +int CTFFlamethrower::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFFlamethrower::PrimaryAttack() +{ + BOOL bUnderwater; + + if(m_pPlayer->ammo_uranium <= 0) + { + PlayEmptySound(); + return; + } + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + bUnderwater = m_pPlayer->pev->waterlevel > 2; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireFlame, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, bUnderwater, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + if(bUnderwater) + { + m_flTimeWeaponIdle = 1; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1; + } + else + { + m_flTimeWeaponIdle = 0.15; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15; + } + m_pPlayer->ammo_uranium--; +} \ No newline at end of file diff --git a/dlls/tfc/grenadelauncher.cpp b/dlls/tfc/grenadelauncher.cpp new file mode 100644 index 00000000..28786dcf --- /dev/null +++ b/dlls/tfc/grenadelauncher.cpp @@ -0,0 +1,174 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_gl, CTFGrenadeLauncher ) + +void CTFGrenadeLauncher::Spawn() +{ + Precache(); + + SET_MODEL( ENT( pev ), "models/w_gauss.mdl" ); + m_iId = 12; + m_iDefaultAmmo = 50; + m_fReloadTime = 0.666667; + pev->solid = SOLID_TRIGGER; +} + +void CTFGrenadeLauncher::Precache() +{ + PRECACHE_MODEL("models/v_tfgl.mdl"); + PRECACHE_MODEL("models/p_glauncher.mdl"); + PRECACHE_MODEL("models/p_p_glauncher2rpg.mdl"); + PRECACHE_MODEL("models/pipebomb.mdl"); + PRECACHE_SOUND("weapons/9mmclip1.wav"); + PRECACHE_SOUND("items/clipinsert1.wav"); + PRECACHE_SOUND("items/cliprelease1.wav"); + PRECACHE_SOUND("weapons/hks1.wav"); + PRECACHE_SOUND("weapons/hks2.wav"); + PRECACHE_SOUND("weapons/hks3.wav"); + PRECACHE_SOUND("weapons/glauncher.wav"); + PRECACHE_SOUND("weapons/glauncher2.wav"); + PRECACHE_SOUND("weapons/357_cock1.wav"); + m_usFireGL = PRECACHE_EVENT(1, "events/wpn/tf_gl.sc"); +} + +int CTFGrenadeLauncher::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "rockets"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 50; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 3; + p->iPosition = 3; + p->iFlags = 0; + p->iMaxClip = 6; + p->iId = 12; + p->iWeight = 15; + return 1; +} + +void CTFGrenadeLauncher::Holster() +{ + //m_pPlayer->m_iGLClip = m_iClip; + //tfstate? + m_fInSpecialReload = 0; + SendWeaponAnim(10, 1); + m_flTimeWeaponIdle = 1000; + m_pPlayer->m_flNextAttack = 0.5; +} + +BOOL CTFGrenadeLauncher::Deploy() +{ + return DefaultDeploy( "models/v_tfgl.mdl", "models/p_glauncher.mdl", 8, "mp5", 1 ); +} + +void CTFGrenadeLauncher::Reload() +{ + if ( m_pPlayer->ammo_rockets > 0 ) + { + if ( m_iClip != 6 && m_flNextReload <= 0.0 && m_flNextPrimaryAttack <= 0.0 ) + { + if (m_fInSpecialReload) + { + if ( m_fInSpecialReload == 1 ) + { + if ( m_flTimeWeaponIdle <= 0.0 ) + { + m_fInSpecialReload = 2; + m_flNextReload = m_fReloadTime; + m_flTimeWeaponIdle = m_fReloadTime; + } + } + else + { + m_iClip++; + m_pPlayer->ammo_rockets--; + m_fInSpecialReload = 1; + //m_pPlayer->tfstate &= 2; + } + } + else + { + SendWeaponAnim(4, 1); + //m_pPlayer->tfstate |= 2; + m_fInSpecialReload = 1; + m_pPlayer->m_flNextAttack = 0.1; + m_flTimeWeaponIdle = 0.1; + m_flNextSecondaryAttack = 0.1; + m_flNextPrimaryAttack = 0.0; + } + } + } +} + +int CTFGrenadeLauncher::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFGrenadeLauncher::WeaponIdle( void ) +{ + ResetEmptySound(); + + if(m_flTimeWeaponIdle > 0.0) + return; + + if(m_iClip > 0) + { + if(m_fInSpecialReload) + { + if(m_iClip == 6) + { + SendWeaponAnim(5, 1); + m_fInSpecialReload = 0; + m_flTimeWeaponIdle = 1.5; + return; + } + if(m_pPlayer->ammo_rockets > 0) + { + Reload(); + return; + } + } + } + m_flTimeWeaponIdle = 3; + SendWeaponAnim(0, 1); +} + +void CTFGrenadeLauncher::PrimaryAttack() +{ + if(m_pPlayer->ammo_rockets <= 0) + { + m_flNextPrimaryAttack = 1; + SendWeaponAnim(0, 1); + PlayEmptySound(); + m_fInSpecialReload = 0; + //tfstate + return; + } + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireGL, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_fInSpecialReload = 0; + //tfstate + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_iClip--; + m_flTimeWeaponIdle = 0.6; + m_flNextPrimaryAttack = 0.6; + m_flNextSecondaryAttack = 0.6; +} diff --git a/dlls/tfc/incendiarycannon.cpp b/dlls/tfc/incendiarycannon.cpp new file mode 100644 index 00000000..eafa6f7f --- /dev/null +++ b/dlls/tfc/incendiarycannon.cpp @@ -0,0 +1,107 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_ic, CTFIncendiaryC ) + +void CTFIncendiaryC::Spawn() +{ + Precache(); + + m_iId = 15; + SET_MODEL(ENT(pev), "models/w_rpg.mdl"); + m_iDefaultAmmo = 50; + pev->solid = SOLID_TRIGGER; +} + +int CTFIncendiaryC::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "rockets"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 20; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 4; + p->iPosition = 2; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 15; + p->iWeight = 20; + return 1; +} + +void CTFIncendiaryC::Holster() +{ + m_fInReload = 0; + SendWeaponAnim(4, 1); + m_pPlayer->m_flNextAttack = 0.5; +} + +void CTFIncendiaryC::Precache() +{ + PRECACHE_MODEL("models/w_rpg.mdl"); + PRECACHE_MODEL("models/v_rpg.mdl"); + PRECACHE_MODEL("models/p_rpg.mdl"); + PRECACHE_MODEL("models/p_rpg2.mdl"); + PRECACHE_SOUND("weapons/9mmclip1.wav"); + UTIL_PrecacheOther("tf_ic_rocket"); + PRECACHE_SOUND("weapons/rocketfire1.wav"); + PRECACHE_SOUND("weapons/glauncher.wav"); + m_usFireIC = PRECACHE_EVENT(1, "events/wpn/tf_ic.sc"); +} + +void CTFIncendiaryC::WeaponIdle( void ) +{ + if(m_flTimeWeaponIdle <= 0.0) + { + if(m_pPlayer->ammo_rockets <= 0) + m_flTimeWeaponIdle = 1; + else + { + m_flTimeWeaponIdle = 3; + SendWeaponAnim(1, 1); + } + } +} + +BOOL CTFIncendiaryC::Deploy() +{ + if(m_iClip >= 0) + return DefaultDeploy( "models/v_rpg.mdl", "models/p_rpg.mdl", 5, "rpg", 1 ); + else + return DefaultDeploy( "models/v_tfc_rpg.mdl", "models/p_rpg.mdl", 7, "rpg", 1 ); +} + +int CTFIncendiaryC::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFIncendiaryC::PrimaryAttack() +{ + if(m_pPlayer->ammo_rockets <= 0) + { + PlayEmptySound(); + return; + } + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireIC, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_pPlayer->ammo_rockets--; + m_flTimeWeaponIdle = 1.2; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.2; +} diff --git a/dlls/tfc/nailgun.cpp b/dlls/tfc/nailgun.cpp new file mode 100644 index 00000000..e37fbeac --- /dev/null +++ b/dlls/tfc/nailgun.cpp @@ -0,0 +1,95 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_ng, CTFNailgun ) + +void CTFNailgun::Spawn() +{ + Precache(); + + m_iId = 4; + m_iDefaultAmmo = 50; + pev->solid = SOLID_TRIGGER; +} + +void CTFNailgun::Precache( void ) +{ + PRECACHE_MODEL("models/v_tfc_nailgun.mdl"); + PRECACHE_MODEL("models/v_tfc_supernailgun.mdl"); + PRECACHE_MODEL("models/p_nailgun.mdl"); + PRECACHE_MODEL("models/p_nailgun2.mdl"); + PRECACHE_MODEL("models/p_snailgun.mdl"); + PRECACHE_MODEL("models/p_snailgun2.mdl"); + PRECACHE_SOUND("items/9mmclip1.wav"); + PRECACHE_SOUND("items/clipinsert1.wav"); + PRECACHE_SOUND("items/cliprelease1.wav"); + PRECACHE_SOUND("weapons/airgun_1.wav"); + PRECACHE_SOUND("weapons/spike2.wav"); + PRECACHE_SOUND("weapons/357_cock1.wav"); + m_usFireNailGun = PRECACHE_EVENT(1, "events/wpn/tf_nail.sc"); +} + +int CTFNailgun::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = ""; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 200; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 3; + p->iPosition = 4; + p->iFlags = 0; + p->iMaxClip = 0; + p->iId = 10; + p->iWeight = 15; + return 1; +} + +BOOL CTFNailgun::Deploy() +{ + return DefaultDeploy( "models/v_tfc_nailgun.mdl", "models/p_nailgun.mdl", NAILGUN_DEPLOY, "mp5", 1 ); +} + +void CTFNailgun::WeaponIdle( void ) +{ + if(m_flTimeWeaponIdle < 0.0) + { + m_flTimeWeaponIdle = 15; + SendWeaponAnim(NAILGUN_IDLE1, 1); + } +} + +int CTFNailgun::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFNailgun::PrimaryAttack() +{ + if(m_pPlayer->ammo_bolts <= 0) + { + PlayEmptySound(); + return; + } + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireNailGun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_pPlayer->ammo_bolts--; + m_flTimeWeaponIdle = 10; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; +} \ No newline at end of file diff --git a/dlls/tfc/pipebomblauncher.cpp b/dlls/tfc/pipebomblauncher.cpp new file mode 100644 index 00000000..9c450610 --- /dev/null +++ b/dlls/tfc/pipebomblauncher.cpp @@ -0,0 +1,62 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_pl, CTFPipebombLauncher ) + +void CTFPipebombLauncher::Spawn() +{ + Precache(); + + SET_MODEL( ENT( pev ), "models/w_gauss.mdl" ); + m_iId = 22; + m_iDefaultAmmo = 50; + m_fReloadTime = 0.666667; + pev->solid = SOLID_TRIGGER; + m_usFireGL = PRECACHE_EVENT(1, "events/wpn/tf_gl.sc"); +} + +int CTFPipebombLauncher::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "rockets"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 50; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 4; + p->iPosition = 4; + p->iFlags = 0; + p->iMaxClip = 6; + p->iId = 22; + p->iWeight = 15; + return 1; +} + +void CTFPipebombLauncher::PrimaryAttack() +{ + if(m_pPlayer->ammo_rockets <= 0) + { + m_flNextPrimaryAttack = 1; + SendWeaponAnim(0, 1); + PlayEmptySound(); + m_fInSpecialReload = 0; + //tfstate + return; + } + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireGL, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_fInSpecialReload = 0; + //tfstate + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_iClip--; + m_flTimeWeaponIdle = 0.6; + m_flNextPrimaryAttack = 0.6; + m_flNextSecondaryAttack = 0.6; +} diff --git a/dlls/tfc/railgun.cpp b/dlls/tfc/railgun.cpp new file mode 100644 index 00000000..feeb7f30 --- /dev/null +++ b/dlls/tfc/railgun.cpp @@ -0,0 +1,82 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_railgun, CTFRailgun ) + +void CTFRailgun::Spawn() +{ + Precache(); + + //pev->classname = STRING("tf_weapon_railgun"); + SET_MODEL( ENT( pev ), "models/w_gauss.mdl" ); + m_iId = 21; + m_iDefaultAmmo = 17; + pev->solid = SOLID_TRIGGER; +} + +int CTFRailgun::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = ""; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 50; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 1; + p->iPosition = 2; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 21; + p->iWeight = 10; + return 1; +} + +void CTFRailgun::Precache() +{ + PRECACHE_MODEL("models/v_tfc_railgun.mdl"); + PRECACHE_MODEL("models/w_gauss.mdl"); + PRECACHE_MODEL("models/p_9mmhandgun.mdl"); + PRECACHE_MODEL("models/p_9mmhandgun2.mdl"); + PRECACHE_SOUND("weapons/railgun.wav"); + m_usFireRail = PRECACHE_EVENT(1, "events/wpn/tf_rail.sc"); +} + +BOOL CTFRailgun::Deploy() +{ + return DefaultDeploy( "models/v_tfc_railgun.mdl", "models/p_9mmhandgun.mdl", 2, "onehanded", 1 ); +} + +void CTFRailgun::PrimaryAttack() +{ + if(m_pPlayer->ammo_bolts <= 0) + { + PlayEmptySound(); + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2; + return; + } + + m_pPlayer->m_iWeaponVolume = 600; + m_pPlayer->m_iWeaponFlash = 256; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireRail, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->pev->effects |= EF_MUZZLEFLASH; + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + m_pPlayer->ammo_bolts--; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.4; + m_flTimeWeaponIdle = 12.5; +} + +void CTFRailgun::WeaponIdle( void ) +{ + ResetEmptySound(); + + if(m_flTimeWeaponIdle <= 0.0) + { + m_flTimeWeaponIdle = 12.5; + SendWeaponAnim(0, 1); + } +} diff --git a/dlls/tfc/rpg.cpp b/dlls/tfc/rpg.cpp new file mode 100644 index 00000000..ffb1bc64 --- /dev/null +++ b/dlls/tfc/rpg.cpp @@ -0,0 +1,193 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_rpg, CTFRpg ) + +void CTFRpg::Spawn() +{ + Precache(); + + m_iId = 14; + SET_MODEL(ENT(pev), "models/w_rpg.mdl"); + m_iDefaultAmmo = 50; + m_fReloadTime = 1.25; + pev->solid = SOLID_TRIGGER; +} + +int CTFRpg::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "rockets"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 50; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 4; + p->iPosition = 1; + p->iFlags = 0; + p->iMaxClip = 4; + p->iId = 14; + p->iWeight = 20; + return 1; +} + +void CTFRpg::Holster() +{ + //тф стейт чот там + m_fInSpecialReload = 0; + m_pPlayer->m_flNextAttack = 0.5; +} + +void CTFRpg::Precache() +{ + PRECACHE_MODEL("models/v_tfc_rpg.mdl"); + PRECACHE_MODEL("models/p_srpg.mdl"); + PRECACHE_MODEL("models/p_shotgun2.mdl"); + PRECACHE_MODEL("models/p_rpg2.mdl"); + PRECACHE_SOUND("weapons/9mmclip1.wav"); + UTIL_PrecacheOther("tf_rpg_rocket"); + PRECACHE_SOUND("weapons/rocketfire1.wav"); + PRECACHE_SOUND("weapons/glauncher.wav"); + m_usFireRPG = PRECACHE_EVENT(1, "events/wpn/tf_rpg.sc"); +} + +void CTFRpg::Reload( void ) +{ + if ( m_pPlayer->ammo_rockets == 0 || m_iClip == 4 || m_flNextReload > 0.0 || m_flNextPrimaryAttack > 0.0) + return; + + if ( m_fInSpecialReload ) + { + if ( m_fInSpecialReload == 1 ) + { + if ( m_flTimeWeaponIdle <= gpGlobals->time ) + { + m_fInSpecialReload = 2; + SendWeaponAnim(TFCRPG_RELCYCLE, 1); + m_flNextReload = UTIL_WeaponTimeBase() + m_fReloadTime; + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + m_fReloadTime; + } + } + else + { + m_iClip += 1; + m_pPlayer->ammo_rockets -= 1; + m_fInSpecialReload = 1; + //m_pPlayer->tfstate &= 2; + } + } + else + { + SendWeaponAnim(TFCRPG_RELSTART, 1); + //m_pPlayer->tfstate |= 2; + m_fInSpecialReload = 1; + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.1; + m_flTimeWeaponIdle = 0.1; + m_flNextSecondaryAttack = 0.1; + m_flNextPrimaryAttack = 0.0; + } +} + +void CTFRpg::WeaponIdle( void ) +{ + ResetEmptySound(); + if (m_flTimeWeaponIdle > 0.0) + return; + + if(m_iClip > 0) + { + if (!m_fInSpecialReload) + { + if (m_pPlayer->ammo_rockets > 0) + { + if(m_iClip == 0) + SendWeaponAnim(TFCRPG_FIDGET2, 1); + else + SendWeaponAnim(TFCRPG_IDLE, 1); + m_flTimeWeaponIdle = 3; + } + else + m_flTimeWeaponIdle = 1; + return; + } + if (m_iClip == 4) + { + SendWeaponAnim(TFCRPG_RELEND, 1); + m_fInSpecialReload = 0; + m_flTimeWeaponIdle = 1.5; + return; + } + } + else if (!m_fInSpecialReload) + { + if (m_pPlayer->ammo_rockets > 0) + { + Reload(); + return; + } + + if (m_pPlayer->ammo_rockets > 0) + { + if(m_iClip == 0) + SendWeaponAnim(TFCRPG_FIDGET2, 1); + else + SendWeaponAnim(TFCRPG_IDLE, 1); + m_flTimeWeaponIdle = 3; + } + else + m_flTimeWeaponIdle = 1; + return; + } + + if (m_pPlayer->ammo_rockets > 0) + { + Reload(); + return; + } + + SendWeaponAnim(TFCRPG_RELEND, 1); + m_fInSpecialReload = 0; + m_flTimeWeaponIdle = 1.5; + return; +} + +BOOL CTFRpg::Deploy() +{ + if(m_iClip >= 0) + return DefaultDeploy( "models/v_tfc_rpg.mdl", "models/p_srpg.mdl", TFCRPG_DRAW1, "rpg", 1 ); + else + return DefaultDeploy( "models/v_tfc_rpg.mdl", "models/p_srpg.mdl", TFCRPG_DRAW2, "rpg", 1 ); +} + +int CTFRpg::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFRpg::PrimaryAttack() +{ + if(m_iClip <= 0) + return; + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireRPG, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_fInSpecialReload = 0; + //tfstatatata + m_iClip--; + m_flTimeWeaponIdle = 0.8; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.8; +} \ No newline at end of file diff --git a/dlls/tfc/shotgun.cpp b/dlls/tfc/shotgun.cpp new file mode 100644 index 00000000..f7def98d --- /dev/null +++ b/dlls/tfc/shotgun.cpp @@ -0,0 +1,204 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_shotgun, CTFShotgun ) + +void CTFShotgun::Spawn() +{ + Precache(); + + m_iId = 8; + m_iDefaultAmmo = 8; + m_iMaxClipSize = 8; + m_iShellsReloaded = 1; + m_fReloadTime = 0.25; + m_flPumpTime = 1000; + pev->solid = SOLID_TRIGGER; +} + +void CTFShotgun::Precache( void ) +{ + PRECACHE_MODEL("models/v_tfc_12gauge.mdl"); + PRECACHE_MODEL("models/p_smallshotgun.mdl"); + PRECACHE_MODEL("models/p_shotgun2.mdl"); + m_iShell = PRECACHE_MODEL("models/shotgunshell.mdl"); + PRECACHE_SOUND("weapons/dbarrel1.wav"); + PRECACHE_SOUND("weapons/sbarrel1.wav"); + PRECACHE_SOUND("weapons/reload1.wav"); + PRECACHE_SOUND("weapons/reload3.wav"); + PRECACHE_SOUND("weapons/357_cock1.wav"); + PRECACHE_SOUND("weapons/scock1.wav"); + PRECACHE_SOUND("weapons/shotgn2.wav"); + m_usFireShotgun = PRECACHE_EVENT(1, "events/wpn/tf_sg.sc"); + m_usReloadShotgun = PRECACHE_EVENT(1, "events/wpn/tf_sgreload.sc"); + m_usPumpShotgun = PRECACHE_EVENT(1, "events/wpn/tf_sgpump.sc"); +} + +int CTFShotgun::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +int CTFShotgun::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "buckshot"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 200; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 1; + p->iPosition = 3; + p->iFlags = 0; + p->iMaxClip = m_iMaxClipSize; + p->iId = 8; + p->iWeight = 15; + return 1; +} + +BOOL CTFShotgun::Deploy() +{ + return DefaultDeploy( "models/v_tfc_12gauge.mdl", "models/p_smallshotgun.mdl", TFCSHOTGUN_DRAW, "shotgun", 1 ); +} + +void CTFShotgun::PrimaryAttack() +{ + float flDelta; + vec3_t *p_vecDirShooting; + vec3_t vecSrc, vecAiming; + vec3_t spread; + + if ( m_iClip <= 0 ) + { + Reload(); + if( m_iClip == 0 ) + PlayEmptySound(); + } + else + { + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 256; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireShotgun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + vecSrc = m_pPlayer->GetGunPosition(); + vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); + spread.x = 0.04; + spread.y = 0.04; + spread.z = 0; + m_pPlayer->FireBullets(6, vecSrc, vecAiming, spread, 2048.0, 6, 0, 4, 0); + if ( !m_iClip && m_pPlayer->ammo_buckshot <= 0 ) + { + p_vecDirShooting = 0; + flDelta = 0.0; + } + m_iClip--; + pev->effects |= EF_MUZZLEFLASH; + m_fInSpecialReload = 0; + m_flTimeWeaponIdle = 5; + //m_pPlayer->tfstate &= 2; + if ( m_iClip ) + m_flPumpTime = 0.5; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; + } +} + +void CTFShotgun::Reload( void ) +{ + if ( m_pPlayer->ammo_buckshot >= m_iShellsReloaded ) + { + if ( m_iClip != m_iMaxClipSize && m_flNextReload <= 0.0 && m_flNextPrimaryAttack <= 0.0 ) + { + if (m_fInSpecialReload) + { + if ( m_fInSpecialReload == 1 ) + { + if ( m_flTimeWeaponIdle <= 0.0 ) + { + m_fInSpecialReload = 2; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usReloadShotgun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0); + m_flNextReload = m_fReloadTime; + m_flTimeWeaponIdle = m_fReloadTime; + } + } + else + { + m_iClip = m_iShellsReloaded + m_iClip; + m_pPlayer->ammo_buckshot -= m_iShellsReloaded; + m_fInSpecialReload = 1; + //m_pPlayer->tfstate &= 2; + } + } + else + { + SendWeaponAnim(TFCSHOTGUN_STARTRELOAD, 1); + //m_pPlayer->tfstate |= 2; + m_fInSpecialReload = 1; + m_pPlayer->m_flNextAttack = 0.1; + m_flTimeWeaponIdle = 0.1; + m_flNextSecondaryAttack = 0.1; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; + } + } + } +} + +void CTFShotgun::WeaponIdle( void ) +{ + int iAnim; + + ResetEmptySound(); + if ( m_flPumpTime != 1000.0 && m_flPumpTime < 0.0 ) + { + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usPumpShotgun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0); + m_flPumpTime = 1000; + } + + if (m_flTimeWeaponIdle < 0.0 ) + { + if ( m_fInSpecialReload ) + { + if ( m_iClip == m_iMaxClipSize || m_pPlayer->ammo_buckshot < m_iShellsReloaded ) + { + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usPumpShotgun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 1, 0); + m_fInSpecialReload = 0; + m_flTimeWeaponIdle = 1.5; + return; + } + Reload(); + return; + } + + int i = UTIL_SharedRandomLong(m_pPlayer->random_seed, 0, 20); + if ( i == 5 * (i / 5) ) + { + if ( i == 20 * (i / 20) ) + { + m_flTimeWeaponIdle = 2.22222; + iAnim = TFCSHOTGUN_IDLE; + } + else + { + m_flTimeWeaponIdle = 2.10526; + iAnim = TFCSHOTGUN_IDLE4; + } + } + else + { + m_flTimeWeaponIdle = 5; + iAnim = TFCSHOTGUN_DEEPIDLE; + } + SendWeaponAnim(iAnim, 1); + } +} \ No newline at end of file diff --git a/dlls/tfc/sniperrifle.cpp b/dlls/tfc/sniperrifle.cpp new file mode 100644 index 00000000..c14e5639 --- /dev/null +++ b/dlls/tfc/sniperrifle.cpp @@ -0,0 +1,228 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( laser_spot, CLaserSpot ) +LINK_ENTITY_TO_CLASS( tf_weapon_sniperrifle, CTFSniperRifle ) + +CLaserSpot *CLaserSpot::CreateSpot( void ) +{ + CLaserSpot *pSpot = GetClassPtr( (CLaserSpot *)NULL ); + pSpot->Spawn(); + pSpot->pev->classname = MAKE_STRING( "laser_spot" ); + return pSpot; +} + +void CLaserSpot::Spawn( void ) +{ + Precache(); + pev->movetype = MOVETYPE_NONE; + pev->solid = SOLID_NOT; + pev->rendermode = kRenderGlow; + pev->renderfx = kRenderFxNoDissipation; + pev->renderamt = 255; + SET_MODEL( ENT( pev ), "sprites/laserdot.spr" ); + UTIL_SetOrigin( pev, pev->origin ); +} + +void CLaserSpot::Suspend( float flSuspendTime ) +{ + pev->effects |= EF_NODRAW; + SetThink( &CLaserSpot::Revive ); + pev->nextthink = gpGlobals->time + flSuspendTime; +} + +void CLaserSpot::Revive() +{ + pev->effects &= ~EF_NODRAW; + SetThink( NULL ); +} + +void CLaserSpot::Precache() +{ + PRECACHE_MODEL( "sprites/laserdot.spr" ); +} + +void CTFSniperRifle::Spawn() +{ + Precache(); + + m_iId = 6; + m_iDefaultAmmo = 5; + m_fAimedDamage = 0; + m_fNextAimBonus = -1; + pev->solid = SOLID_TRIGGER; +} + +void CTFSniperRifle::Precache() +{ + PRECACHE_MODEL("models/v_tfc_sniper.mdl"); + PRECACHE_MODEL("models/p_sniper.mdl"); + PRECACHE_MODEL("models/p_sniper2.mdl"); + PRECACHE_SOUND("ambience/rifle1.wav"); + m_usFireSniper = PRECACHE_EVENT(1, "events/wpn/tf_sniper.sc"); + m_usSniperHit = PRECACHE_EVENT(1, "events/wpn/tf_sniperhit.sc"); +} + +int CTFSniperRifle::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "buckshot"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 75; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 1; + p->iPosition = 1; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 6; + p->iWeight = 10; + return 1; +} + +void CTFSniperRifle::SecondaryAttack() +{ + if(m_fInZoom) + { + m_pPlayer->m_iFOV = 0; + pev->fov = 0; + m_fInZoom = 0; + } + else + { + m_pPlayer->m_iFOV = 20; + pev->fov = 20; + m_fInZoom = 1; + } + + pev->nextthink = gpGlobals->time + 0.1; + m_flNextSecondaryAttack = 0.3; +} + +void CTFSniperRifle::Holster() +{ + m_fInReload = 0; + if(m_fInZoom) + SecondaryAttack(); + + //m_pPlayer->tfstate &= 2; + //тф сет спид + + if(m_pSpot) + m_pSpot->Killed(0, 0); + + m_fAimedDamage = 0; + m_pPlayer->m_flNextAttack = 0.5; + SendWeaponAnim(SNIPER_HOLSTER, 1); +} + +BOOL CTFSniperRifle::Deploy() +{ + m_pSpot = 0; + m_flTimeWeaponIdle = 0.5; + m_fAimedDamage = 0; + m_iSpotActive = 0; + + //Velaron: "autosniper" draw animation + return DefaultDeploy( "models/v_tfc_sniper.mdl", "models/p_sniper.mdl", SNIPER_DRAW, "mp5", 1 ); +} + +int CTFSniperRifle::AddToPlayer( CBasePlayer *pPlayer ) +{ + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; +} + +void CTFSniperRifle::UpdateSpot() +{ + vec3_t vecSrc, vecEnd; + TraceResult tr; + + if(!m_iSpotActive) + return; + + if(!m_pSpot) + { + m_pSpot = CLaserSpot::CreateSpot(); + //Velaron: effect 256 + //m_pSpot->pev->effects |= 256; + m_pSpot->pev->owner = ENT(m_pPlayer->pev); + } + + UTIL_MakeVectors(m_pPlayer->pev->v_angle); + vecSrc = m_pPlayer->GetGunPosition(); + vecEnd.x = gpGlobals->v_forward.x * 8192.0 + vecSrc.x; + vecEnd.y = gpGlobals->v_forward.y * 8192.0 + vecSrc.y; + vecEnd.z = gpGlobals->v_forward.z * 8192.0 + vecSrc.z; + UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); + UTIL_SetOrigin(m_pSpot->pev, tr.vecEndPos); + m_pSpot->pev->renderamt = 0.25 * m_fAimedDamage + 150.0; +} + +void CTFSniperRifle::WeaponIdle( void ) +{ + if(m_iSpotActive) + UpdateSpot(); + + if(m_flTimeWeaponIdle < 0.0) + { + m_flTimeWeaponIdle = 12.5; + SendWeaponAnim(SNIPER_IDLE, 1); + } +} + +//Velaron: finish this nightmare +void CTFSniperRifle::PrimaryAttack() +{ + vec3_t anglesAim; + vec3_t vecAim; + vec3_t vecSrc, vecEnd; + TraceResult tr; + + if(m_pPlayer->ammo_buckshot <= 0) + { + PlayEmptySound(); + return; + } + + m_pPlayer->m_iWeaponVolume = 200; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireSniper, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_fAimedDamage, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_flTimeWeaponIdle = 0.5; + anglesAim.x = m_pPlayer->pev->v_angle.x + m_pPlayer->pev->punchangle.x; + anglesAim.y = m_pPlayer->pev->v_angle.y + m_pPlayer->pev->punchangle.y; + anglesAim.z = m_pPlayer->pev->v_angle.z + m_pPlayer->pev->punchangle.z; + UTIL_MakeVectors(anglesAim); + vecAim = m_pPlayer->GetGunPosition(); + UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); + + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usSniperHit, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + + m_pPlayer->ammo_buckshot--; +} + +void CTFSniperRifle::ItemPostFrame() +{ +/* + if(!m_pPlayer->pev->button & 8 || m_flNextSecondaryAttack > 0.0) + { + if(m_pPlayer->m_afButtonReleased & 1 && m_flNextPrimaryAttack <= 0.0) + { + if(tfstate & 8) + {} + } + } +*/ +} \ No newline at end of file diff --git a/dlls/tfc/spanner.cpp b/dlls/tfc/spanner.cpp new file mode 100644 index 00000000..f232812f --- /dev/null +++ b/dlls/tfc/spanner.cpp @@ -0,0 +1,68 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_spanner, CTFSpanner ) + +void CTFSpanner::Spawn() +{ + Precache(); + + m_iId = 4; + SET_MODEL(ENT(pev), "models/w_egon.mdl"); + m_iDefaultAmmo = 50; + pev->solid = SOLID_TRIGGER; + classid = 1; +} + +void CTFSpanner::Precache() +{ + PRECACHE_MODEL("models/v_tfc_spanner.mdl"); + PRECACHE_MODEL("models/p_spanner.mdl"); + PRECACHE_MODEL("models/p_spanner2.mdl"); + m_usAxe = PRECACHE_EVENT(1, "events/wpn/tf_axe.sc"); + m_usAxeDecal = PRECACHE_EVENT(1, "events/wpn/tf_axedecal.sc"); +} + +void CTFSpanner::Holster() +{ + SendWeaponAnim(5, 1); + m_pPlayer->m_flNextAttack = 0.5; +} + +int CTFSpanner::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "uranium"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = -1; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 0; + p->iPosition = 2; + p->iFlags = 0; + p->iMaxClip = -1; + p->iId = 4; + p->iWeight = 0; + return 1; +} + +BOOL CTFSpanner::Deploy() +{ + return DefaultDeploy( "models/v_tfc_spanner.mdl", "models/p_spanner.mdl", 4, "crowbar", 1 ); +} + +void CTFSpanner::WeaponIdle( void ) +{ + ResetEmptySound(); + + if(m_flTimeWeaponIdle <= 0.0) + { + m_flTimeWeaponIdle = 12.5; + SendWeaponAnim(0, 1); + } +} \ No newline at end of file diff --git a/dlls/tfc/supernailgun.cpp b/dlls/tfc/supernailgun.cpp new file mode 100644 index 00000000..fb19abc4 --- /dev/null +++ b/dlls/tfc/supernailgun.cpp @@ -0,0 +1,56 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_superng, CTFSuperNailgun ) + +void CTFSuperNailgun::Precache() +{ + CTFNailgun::Precache(); + m_usFireSuperNailGun = PRECACHE_EVENT(1, "events/wpn/tf_snail.sc"); +} + +int CTFSuperNailgun::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = ""; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 150; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 3; + p->iPosition = 1; + p->iFlags = 0; + p->iMaxClip = 0; + p->iId = 11; + p->iWeight = 15; + return 1; +} + +BOOL CTFSuperNailgun::Deploy() +{ + return DefaultDeploy( "models/v_tfc_supernailgun.mdl", "models/p_snailgun.mdl", NAILGUN_DEPLOY, "mp5", 1 ); +} + +void CTFSuperNailgun::PrimaryAttack() +{ + if(m_pPlayer->ammo_bolts <= 0) + { + PlayEmptySound(); + return; + } + + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 512; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireSuperNailGun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_pPlayer->ammo_bolts -= 2; + if(m_pPlayer->ammo_bolts < 0) + m_pPlayer->ammo_bolts = 0; + m_flTimeWeaponIdle = 10; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; +} \ No newline at end of file diff --git a/dlls/tfc/supershotgun.cpp b/dlls/tfc/supershotgun.cpp new file mode 100644 index 00000000..5c2bd1b2 --- /dev/null +++ b/dlls/tfc/supershotgun.cpp @@ -0,0 +1,109 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "gamerules.h" + +LINK_ENTITY_TO_CLASS( tf_weapon_supershotgun, CTFSuperShotgun ) + +void CTFSuperShotgun::Spawn() +{ + Precache(); + + m_iId = 9; + m_iDefaultAmmo = 16; + m_iMaxClipSize = 16; + m_iShellsReloaded = 2; + m_fReloadTime = 0.375; + m_flPumpTime = 1000; + pev->solid = SOLID_TRIGGER; +} + +void CTFSuperShotgun::Precache( void ) +{ + PRECACHE_MODEL("models/v_tfc_shotgun.mdl"); + PRECACHE_MODEL("models/p_shotgun.mdl"); + PRECACHE_MODEL("models/p_shotgun2.mdl"); + m_iShell = PRECACHE_MODEL("models/shotgunshell.mdl"); + PRECACHE_SOUND("weapons/dbarrel1.wav"); + PRECACHE_SOUND("weapons/sbarrel1.wav"); + PRECACHE_SOUND("weapons/reload1.wav"); + PRECACHE_SOUND("weapons/reload3.wav"); + PRECACHE_SOUND("weapons/357_cock1.wav"); + PRECACHE_SOUND("weapons/scock1.wav"); + PRECACHE_SOUND("weapons/shotgn2.wav"); + m_usFireSuperShotgun = PRECACHE_EVENT(1, "events/wpn/tf_ssg.sc"); + m_usReloadShotgun = PRECACHE_EVENT(1, "events/wpn/tf_sgreload.sc"); + m_usPumpShotgun = PRECACHE_EVENT(1, "events/wpn/tf_sgpump.sc"); +} + +int CTFSuperShotgun::GetItemInfo( ItemInfo *p ) +{ + p->pszAmmo1 = "buckshot"; + p->pszName = STRING( pev->classname ); + p->iMaxAmmo1 = 200; + p->pszAmmo2 = 0; + p->iMaxAmmo2 = -1; + p->iSlot = 2; + p->iPosition = 2; + p->iFlags = 0; + p->iMaxClip = m_iMaxClipSize; + p->iId = 9; + p->iWeight = 15; + return 1; +} + +BOOL CTFSuperShotgun::Deploy() +{ + return DefaultDeploy( "models/v_tfc_shotgun.mdl", "models/p_shotgun.mdl", 6, "shotgun", 1 ); +} + +void CTFSuperShotgun::PrimaryAttack() +{ + float flDelta; + vec3_t *p_vecDirShooting; + vec3_t vecSrc, vecAiming; + vec3_t spread; + + if ( m_iClip == 1 ) + { + CTFShotgun::PrimaryAttack(); + return; + } + + if ( m_iClip <= 0 ) + { + Reload(); + if( m_iClip == 0 ) + PlayEmptySound(); + } + else + { + m_pPlayer->m_iWeaponVolume = 1000; + m_pPlayer->m_iWeaponFlash = 256; + PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usFireSuperShotgun, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0, 0, 0); + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + vecSrc = m_pPlayer->GetGunPosition(); + vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); + spread.x = 0.04; + spread.y = 0.04; + spread.z = 0; + m_pPlayer->FireBullets(14, vecSrc, vecAiming, spread, 2048.0, 6, 4, 4, 0); + if ( !m_iClip && m_pPlayer->ammo_buckshot <= 0 ) + { + p_vecDirShooting = 0; + flDelta = 0.0; + } + m_iClip -= 2; + pev->effects |= EF_MUZZLEFLASH; + m_fInSpecialReload = 0; + m_flTimeWeaponIdle = 5; + //m_pPlayer->tfstate &= 2; + if ( m_iClip ) + m_flPumpTime = 0.7; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; + } +} \ No newline at end of file diff --git a/dlls/weapons.h b/dlls/tfc/weapons.h similarity index 59% rename from dlls/weapons.h rename to dlls/tfc/weapons.h index 312f5531..67b4ecd3 100644 --- a/dlls/weapons.h +++ b/dlls/tfc/weapons.h @@ -1,9 +1,9 @@ /*** * * Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting @@ -12,7 +12,6 @@ * without written permission from Valve LLC. * ****/ -#pragma once #ifndef WEAPONS_H #define WEAPONS_H @@ -21,63 +20,13 @@ class CBasePlayer; extern int gmsgWeapPickup; -void DeactivateSatchels( CBasePlayer *pOwner ); - -// Contact Grenade / Timed grenade / Satchel Charge -class CGrenade : public CBaseMonster -{ -public: - void Spawn( void ); - - typedef enum { SATCHEL_DETONATE = 0, SATCHEL_RELEASE } SATCHELCODE; - - static CGrenade *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time ); - static CGrenade *ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ); - static CGrenade *ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ); - static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code ); - - void Explode( Vector vecSrc, Vector vecAim ); - void Explode( TraceResult *pTrace, int bitsDamageType ); - void EXPORT Smoke( void ); - - void EXPORT BounceTouch( CBaseEntity *pOther ); - void EXPORT SlideTouch( CBaseEntity *pOther ); - void EXPORT ExplodeTouch( CBaseEntity *pOther ); - void EXPORT DangerSoundThink( void ); - void EXPORT PreDetonate( void ); - void EXPORT Detonate( void ); - void EXPORT DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void EXPORT TumbleThink( void ); - - virtual void BounceSound( void ); - virtual int BloodColor( void ) { return DONT_BLEED; } - virtual void Killed( entvars_t *pevAttacker, int iGib ); - - BOOL m_fRegisteredSound;// whether or not this grenade has issued its DANGER sound to the world sound list yet. -}; - // constant items #define ITEM_HEALTHKIT 1 #define ITEM_ANTIDOTE 2 #define ITEM_SECURITY 3 #define ITEM_BATTERY 4 -#define WEAPON_NONE 0 -#define WEAPON_CROWBAR 1 -#define WEAPON_GLOCK 2 -#define WEAPON_PYTHON 3 -#define WEAPON_MP5 4 -#define WEAPON_CHAINGUN 5 -#define WEAPON_CROSSBOW 6 -#define WEAPON_SHOTGUN 7 -#define WEAPON_RPG 8 -#define WEAPON_GAUSS 9 -#define WEAPON_EGON 10 -#define WEAPON_HORNETGUN 11 -#define WEAPON_HANDGRENADE 12 -#define WEAPON_TRIPMINE 13 -#define WEAPON_SATCHEL 14 -#define WEAPON_SNARK 15 +#define WEAPON_CROWBAR 1 #define WEAPON_ALLWEAPONS (~(1<absmin = pev->origin + Vector(-16, -16, -5); - pev->absmax = pev->origin + Vector(16, 16, 28); - } - - void PrimaryAttack( void ); - BOOL Deploy( void ); - void Holster( int skiplocal = 0 ); - void WeaponIdle( void ); - - virtual BOOL UseDecrement( void ) - { -#if defined( CLIENT_WEAPONS ) - return TRUE; -#else - return FALSE; -#endif - } - -private: - unsigned short m_usTripFire; -}; - -class CSqueak : public CBasePlayerWeapon -{ -public: - void Spawn( void ); - void Precache( void ); - int iItemSlot( void ) { return 5; } - int GetItemInfo(ItemInfo *p); - - void PrimaryAttack( void ); - void SecondaryAttack( void ); - BOOL Deploy( void ); - void Holster( int skiplocal = 0 ); - void WeaponIdle( void ); - int m_fJustThrown; + int m_fInReload; + float m_flNextReload; + int m_iShell; + int m_iMaxClipSize; + int m_iShellsReloaded; + int m_fReloadTime; virtual BOOL UseDecrement( void ) { -#if defined( CLIENT_WEAPONS ) - return TRUE; -#else - return FALSE; -#endif + return true; } + unsigned short m_usReloadShotgun; + unsigned short m_usPumpShotgun; + private: - unsigned short m_usSnarkFire; + unsigned short m_usFireShotgun; }; + +class CTFSuperShotgun : public CTFShotgun +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + void PrimaryAttack(void); + BOOL Deploy(); + +private: + unsigned short m_usFireSuperShotgun; +}; + +enum tfc_nailgun_e +{ + NAILGUN_LONGIDLE = 0, + NAILGUN_IDLE1, + NAILGUN_GRENADE, + NAILGUN_RELOAD, + NAILGUN_DEPLOY, + NAILGUN_SHOOT1, + NAILGUN_SHOOT2, + NAILGUN_SHOOT3 +}; + +class CTFNailgun : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + int AddToPlayer(CBasePlayer *pPlayer); + void PrimaryAttack(void); + BOOL Deploy(); + void WeaponIdle(void); + + virtual BOOL UseDecrement( void ) + { + return true; + } + + unsigned short m_usFireNailGun; +}; + +class CTFSuperNailgun : public CTFNailgun +{ +public: + void Precache(void); + int GetItemInfo(ItemInfo *p); + void PrimaryAttack(void); + BOOL Deploy(); + +private: + unsigned short m_usFireSuperNailGun; +}; + +class CTFGrenadeLauncher : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + void Holster(void); + void WeaponIdle(void); + BOOL Deploy(void); + void Reload(void); + int AddToPlayer(CBasePlayer *pPlayer); + void PrimaryAttack(void); + +private: + unsigned short m_usFireGL; + float m_fReloadTime; + float m_flNextReload; +}; + +class CTFPipebombLauncher : public CTFGrenadeLauncher +{ +public: + void Spawn(void); + int GetItemInfo(ItemInfo *p); + void PrimaryAttack(void); + +private: + unsigned short m_usFireGL; + float m_fReloadTime; + float m_flNextReload; +}; + +class CTFFlamethrower : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + BOOL CanHolster(void) {return 1;}; + void Holster(void); + void WeaponIdle(void); + BOOL Deploy(void); + int AddToPlayer(CBasePlayer *pPlayer); + void PrimaryAttack(void); + +private: + unsigned short m_usFireFlame; +}; + +enum tfc_tfcrpg_e +{ + TFCRPG_IDLE = 0, + TFCRPG_FIDGET, + TFCRPG_FIRE, + TFCRPG_HOLSTER1, + TFCRPG_DRAW1, + TFCRPG_HOLSTER2, + TFCRPG_DRAW2, + TFCRPG_RELSTART, + TFCRPG_RELCYCLE, + TFCRPG_RELEND, + TFCRPG_IDLE2, + TFCRPG_FIDGET2 +}; + +class CTFRpg : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + BOOL CanHolster(void) {return 1;}; + void Holster(void); + void WeaponIdle(void); + void Reload(void); + BOOL Deploy(void); + int AddToPlayer(CBasePlayer *pPlayer); + void PrimaryAttack(void); + +private: + unsigned short m_usFireRPG; + float m_fReloadTime; + float m_flNextReload; +}; + +class CTFIncendiaryC : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + BOOL CanHolster(void) {return 1;}; + void Holster(void); + void WeaponIdle(void); + BOOL Deploy(void); + int AddToPlayer(CBasePlayer *pPlayer); + void PrimaryAttack(void); + +private: + unsigned short m_usFireIC; +}; + +enum tfc_assault_e +{ + ASSAULT_IDLE = 0, + ASSAULT_IDLE2, + ASSAULT_SPINUP, + ASSAULT_SPINDOWN, + ASSAULT_FIRE, + ASSAULT_DRAW, + ASSAULT_HOLSTER +}; + +class CTFAssaultC : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + void Holster(void); + void WeaponIdle(void); + BOOL Deploy(void); + BOOL ShouldWeaponIdle() {return 1;}; + int AddToPlayer(CBasePlayer *pPlayer); + void PrimaryAttack(void); + void Fire(void); + +private: + int m_iWeaponState; + int m_iShell; + unsigned short m_usWindUp; + unsigned short m_usWindDown; + unsigned short m_usFire; + unsigned short m_usStartSpin; + unsigned short m_usSpin; + unsigned short m_usACStart; +}; + +class CTFRailgun : public CBasePlayerWeapon +{ +public: + void Spawn(void); + void Precache(void); + int GetItemInfo(ItemInfo *p); + void WeaponIdle(void); + BOOL Deploy(void); + void PrimaryAttack(void); + +private: + unsigned short m_usFireRail; +}; + #endif // WEAPONS_H