Serious-Engine/Sources/EntitiesMP/PlayerWeapons.es
2019-07-31 17:53:47 -07:00

5644 lines
215 KiB
C++
Executable File

/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
402
%{
#include "EntitiesMP/StdH/StdH.h"
#include "GameMP/SEColors.h"
#include <Engine/Build.h>
#include "EntitiesMP/Player.h"
#include "EntitiesMP/Bullet.h"
#include "Models/Weapons/Knife/Knife.h"
#include "Models/Weapons/Knife/KnifeItem.h"
#include "Models/Weapons/Colt/colt.h"
#include "Models/Weapons/Colt/ColtMain.h"
#include "Models/Weapons/SingleShotgun/SingleShotGun.h"
#include "Models/Weapons/SingleShotgun/Barrels.h"
#include "Models/Weapons/DoubleShotgun/DoubleShotgun.h"
#include "Models/Weapons/DoubleShotgun/Dshotgunbarrels.h"
#include "Models/Weapons/DoubleShotgun/HandWithAmmo.h"
#include "Models/Weapons/TommyGun/TommyGun.h"
#include "Models/Weapons/TommyGun/Body.h"
#include "Models/Weapons/MiniGun/minigun.h"
#include "Models/Weapons/MiniGun/Body.h"
#include "Models/Weapons/GrenadeLauncher/GrenadeLauncher.h"
#include "Models/Weapons/RocketLauncher/RocketLauncher.h"
#include "Models/Weapons/Laser/Laser.h"
#include "Models/Weapons/Laser/Barrel.h"
#include "Models/Weapons/Cannon/Cannon.h"
#include "Models/Weapons/Cannon/Body.h"
// Mission Pack weapons
#include "ModelsMP/Weapons/Sniper/Sniper.h"
#include "ModelsMP/Weapons/Sniper/Body.h"
#include "ModelsMP/Weapons/Flamer/Flamer.h"
#include "ModelsMP/Weapons/Flamer/Body.h"
#include "ModelsMP/Weapons/Flamer/FuelReservoir.h"
#include "ModelsMP/Weapons/Flamer/Flame.h"
#include "ModelsMP/Weapons/ChainSaw/ChainSaw.h"
#include "ModelsMP/Weapons/ChainSaw/ChainsawForPlayer.h"
#include "ModelsMP/Weapons/ChainSaw/Body.h"
#include "ModelsMP/Weapons/ChainSaw/Blade.h"
#include "ModelsMP/Weapons/ChainSaw/Teeth.h"
// Mission Pack player body instead of the old one
#include "ModelsMP/Player/SeriousSam/Body.h"
#include "ModelsMP/Player/SeriousSam/Player.h"
#include "EntitiesMP/Switch.h"
#include "EntitiesMP/PlayerView.h"
#include "EntitiesMP/PlayerAnimator.h"
#include "EntitiesMP/MovingBrush.h"
#include "EntitiesMP/MessageHolder.h"
#include "EntitiesMP/EnemyBase.h"
extern INDEX hud_bShowWeapon;
extern const INDEX aiWeaponsRemap[19] = { 0, 1, 10, 2, 3, 4, 5, 6, 7,
8, 9, 11, 13, 12, 14, 15, 16, 17, 18 };
%}
uses "EntitiesMP/Player";
uses "EntitiesMP/PlayerWeaponsEffects";
uses "EntitiesMP/Projectile";
uses "EntitiesMP/Bullet";
uses "EntitiesMP/BasicEffects";
uses "EntitiesMP/WeaponItem";
uses "EntitiesMP/AmmoItem";
uses "EntitiesMP/AmmoPack";
uses "EntitiesMP/ModelHolder2";
//uses "EntitiesMP/Pipebomb";
//uses "EntitiesMP/GhostBusterRay";
uses "EntitiesMP/CannonBall";
// input parameter for weapons
event EWeaponsInit {
CEntityPointer penOwner, // who owns it
};
// select weapon
event ESelectWeapon {
INDEX iWeapon, // weapon to select
};
// boring weapon animations
event EBoringWeapon {};
// fire weapon
event EFireWeapon {};
// release weapon
event EReleaseWeapon {};
// reload weapon
event EReloadWeapon {};
// weapon changed - used to notify other entities
event EWeaponChanged {};
// weapons (do not change order! - needed by HUD.cpp)
enum WeaponType {
0 WEAPON_NONE "", // don't consider this in WEAPONS_ALLAVAILABLEMASK
1 WEAPON_KNIFE "",
2 WEAPON_COLT "",
3 WEAPON_DOUBLECOLT "",
4 WEAPON_SINGLESHOTGUN "",
5 WEAPON_DOUBLESHOTGUN "",
6 WEAPON_TOMMYGUN "",
7 WEAPON_MINIGUN "",
8 WEAPON_ROCKETLAUNCHER "",
9 WEAPON_GRENADELAUNCHER "",
10 WEAPON_CHAINSAW "",
11 WEAPON_FLAMER "",
12 WEAPON_LASER "",
13 WEAPON_SNIPER "",
14 WEAPON_IRONCANNON "",
15 WEAPON_LAST "",
}; // see 'WEAPONS_ALLAVAILABLEMASK' -> (11111111111111 == 0x3FFF)
%{
// AVAILABLE WEAPON MASK
#define WEAPONS_ALLAVAILABLEMASK 0x3FFF
/*
#if BUILD_TEST
#define WEAPONS_DISABLEDMASK (\
(1<<(WEAPON_TOMMYGUN -1))|\
(1<<(WEAPON_GRENADELAUNCHER-1))|\
(1<<(WEAPON_PIPEBOMB -1))|\
(1<<(WEAPON_FLAMER -1))|\
(1<<(WEAPON_LASER -1))|\
(1<<(WEAPON_GHOSTBUSTER -1))|\
(1<<(WEAPON_IRONCANNON -1))|\
(1<<(WEAPON_NUKECANNON -1)))
#else
#define WEAPONS_DISABLEDMASK (0)
#endif
*/
#define MAX_WEAPONS 30
// MiniGun specific
#define MINIGUN_STATIC 0
#define MINIGUN_FIRE 1
#define MINIGUN_SPINUP 2
#define MINIGUN_SPINDOWN 3
#define MINIGUN_SPINUPTIME 0.5f
#define MINIGUN_SPINDNTIME 3.0f
#define MINIGUN_SPINUPSOUND 0.5f
#define MINIGUN_SPINDNSOUND 1.5f
#define MINIGUN_FULLSPEED 500.0f
#define MINIGUN_SPINUPACC (MINIGUN_FULLSPEED/MINIGUN_SPINUPTIME)
#define MINIGUN_SPINDNACC (MINIGUN_FULLSPEED/MINIGUN_SPINDNTIME)
#define MINIGUN_TICKTIME (_pTimer->TickQuantum)
// chainsaw specific
#define CHAINSAW_UPDATETIME 0.05f
// fire flare specific
#define FLARE_REMOVE 1
#define FLARE_ADD 2
// animation light specific
#define LIGHT_ANIM_MINIGUN 2
#define LIGHT_ANIM_TOMMYGUN 3
#define LIGHT_ANIM_COLT_SHOTGUN 4
#define LIGHT_ANIM_NONE 5
// mana for ammo adjustment (multiplier)
#define MANA_AMMO (0.1f)
// position of weapon model -- weapon 0 is never used
static FLOAT wpn_fH[MAX_WEAPONS+1];
static FLOAT wpn_fP[MAX_WEAPONS+1];
static FLOAT wpn_fB[MAX_WEAPONS+1];
static FLOAT wpn_fX[MAX_WEAPONS+1];
static FLOAT wpn_fY[MAX_WEAPONS+1];
static FLOAT wpn_fZ[MAX_WEAPONS+1];
static FLOAT wpn_fFOV[MAX_WEAPONS+1];
static FLOAT wpn_fClip[MAX_WEAPONS+1];
static FLOAT wpn_fFX[MAX_WEAPONS+1]; // firing source
static FLOAT wpn_fFY[MAX_WEAPONS+1];
//static FLOAT wpn_fFZ[MAX_WEAPONS+1];
static INDEX wpn_iCurrent;
extern FLOAT hud_tmWeaponsOnScreen;
extern FLOAT wpn_fRecoilSpeed[17];
extern FLOAT wpn_fRecoilLimit[17];
extern FLOAT wpn_fRecoilDampUp[17];
extern FLOAT wpn_fRecoilDampDn[17];
extern FLOAT wpn_fRecoilOffset[17];
extern FLOAT wpn_fRecoilFactorP[17];
extern FLOAT wpn_fRecoilFactorZ[17];
// bullet positions
static FLOAT afSingleShotgunPellets[] =
{ -0.3f,+0.1f, +0.0f,+0.1f, +0.3f,+0.1f,
-0.4f,-0.1f, -0.1f,-0.1f, +0.1f,-0.1f, +0.4f,-0.1f
};
static FLOAT afDoubleShotgunPellets[] =
{
-0.3f,+0.15f, +0.0f,+0.15f, +0.3f,+0.15f,
-0.4f,+0.05f, -0.1f,+0.05f, +0.1f,+0.05f, +0.4f,+0.05f,
-0.3f,-0.05f, +0.0f,-0.05f, +0.3f,-0.05f,
-0.4f,-0.15f, -0.1f,-0.15f, +0.1f,-0.15f, +0.4f,-0.15f
};
// sniper discrete zoom values - 4 (1x,2x,4x,6x)
// synchronize this with sniper properties (properties 233-237)
static INDEX iSniperDiscreteZoomLevels = 4;
static FLOAT afSniperZoom[] =
{
90.0f,1.0f, 53.1f, 2.0f, 28.0f,4.0f, 14.2f,6.0f,
//7.2f,8.0f, 3.56f,10.0f ,1.8f,12.0f
};
// crosshair console variables
static INDEX hud_bCrosshairFixed = FALSE;
static INDEX hud_bCrosshairColoring = TRUE;
static FLOAT hud_fCrosshairScale = 1.0f;
static FLOAT hud_fCrosshairOpacity = 1.0f;
static FLOAT hud_fCrosshairRatio = 0.5f; // max distance size ratio
// misc HUD vars
static INDEX hud_bShowPlayerName = TRUE;
static INDEX hud_bShowCoords = FALSE;
static FLOAT plr_tmSnoopingDelay = 1.0f; // seconds
FLOAT plr_tmSnoopingTime = 1.0f; // seconds
// some static vars
static INDEX _iLastCrosshairType=-1;
static CTextureObject _toCrosshair;
// must do this to keep dependency catcher happy
CTFileName fn1 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair1.tex");
CTFileName fn2 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair2.tex");
CTFileName fn3 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair3.tex");
CTFileName fn4 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair4.tex");
CTFileName fn5 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair5.tex");
CTFileName fn6 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair6.tex");
CTFileName fn7 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair7.tex");
void CPlayerWeapons_Precache(ULONG ulAvailable)
{
CDLLEntityClass *pdec = &CPlayerWeapons_DLLClass;
// precache general stuff always
pdec->PrecacheTexture(TEX_REFL_BWRIPLES01 );
pdec->PrecacheTexture(TEX_REFL_BWRIPLES02 );
pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01 );
pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01);
pdec->PrecacheTexture(TEX_REFL_DARKMETAL );
pdec->PrecacheTexture(TEX_REFL_PURPLE01 );
pdec->PrecacheTexture(TEX_SPEC_WEAK );
pdec->PrecacheTexture(TEX_SPEC_MEDIUM );
pdec->PrecacheTexture(TEX_SPEC_STRONG );
pdec->PrecacheTexture(TEXTURE_HAND );
pdec->PrecacheTexture(TEXTURE_FLARE01 );
pdec->PrecacheModel(MODEL_FLARE01);
pdec->PrecacheClass(CLASS_BULLET);
pdec->PrecacheSound(SOUND_SILENCE);
// precache other weapons if available
if ( ulAvailable&(1<<(WEAPON_KNIFE-1)) ) {
pdec->PrecacheModel(MODEL_KNIFE );
pdec->PrecacheModel(MODEL_KNIFEITEM );
pdec->PrecacheTexture(TEXTURE_KNIFEITEM );
pdec->PrecacheSound(SOUND_KNIFE_BACK );
pdec->PrecacheSound(SOUND_KNIFE_HIGH );
pdec->PrecacheSound(SOUND_KNIFE_LONG );
pdec->PrecacheSound(SOUND_KNIFE_LOW );
}
if ( ulAvailable&(1<<(WEAPON_COLT-1)) ) {
pdec->PrecacheModel(MODEL_COLT );
pdec->PrecacheModel(MODEL_COLTCOCK );
pdec->PrecacheModel(MODEL_COLTMAIN );
pdec->PrecacheModel(MODEL_COLTBULLETS );
pdec->PrecacheTexture(TEXTURE_COLTMAIN );
pdec->PrecacheTexture(TEXTURE_COLTCOCK );
pdec->PrecacheTexture(TEXTURE_COLTBULLETS );
pdec->PrecacheSound(SOUND_COLT_FIRE );
pdec->PrecacheSound(SOUND_COLT_RELOAD );
}
if ( ulAvailable&(1<<(WEAPON_SINGLESHOTGUN-1)) ) {
pdec->PrecacheModel(MODEL_SINGLESHOTGUN );
pdec->PrecacheModel(MODEL_SS_SLIDER );
pdec->PrecacheModel(MODEL_SS_HANDLE );
pdec->PrecacheModel(MODEL_SS_BARRELS );
pdec->PrecacheTexture(TEXTURE_SS_HANDLE );
pdec->PrecacheTexture(TEXTURE_SS_BARRELS );
pdec->PrecacheSound(SOUND_SINGLESHOTGUN_FIRE);
}
if ( ulAvailable&(1<<(WEAPON_DOUBLESHOTGUN-1)) ) {
pdec->PrecacheModel(MODEL_DOUBLESHOTGUN );
pdec->PrecacheModel(MODEL_DS_HANDLE );
pdec->PrecacheModel(MODEL_DS_BARRELS );
pdec->PrecacheModel(MODEL_DS_AMMO );
pdec->PrecacheModel(MODEL_DS_SWITCH );
pdec->PrecacheModel(MODEL_DS_HANDWITHAMMO );
pdec->PrecacheTexture(TEXTURE_DS_HANDLE );
pdec->PrecacheTexture(TEXTURE_DS_BARRELS );
pdec->PrecacheTexture(TEXTURE_DS_AMMO );
pdec->PrecacheTexture(TEXTURE_DS_SWITCH );
pdec->PrecacheSound(SOUND_DOUBLESHOTGUN_FIRE );
pdec->PrecacheSound(SOUND_DOUBLESHOTGUN_RELOAD );
}
if ( ulAvailable&(1<<(WEAPON_TOMMYGUN-1)) ) {
pdec->PrecacheModel(MODEL_TOMMYGUN );
pdec->PrecacheModel(MODEL_TG_BODY );
pdec->PrecacheModel(MODEL_TG_SLIDER );
pdec->PrecacheTexture(TEXTURE_TG_BODY );
pdec->PrecacheSound(SOUND_TOMMYGUN_FIRE );
}
if ( ulAvailable&(1<<(WEAPON_SNIPER-1)) ) {
pdec->PrecacheModel(MODEL_SNIPER );
pdec->PrecacheModel(MODEL_SNIPER_BODY );
pdec->PrecacheTexture(TEXTURE_SNIPER_BODY );
pdec->PrecacheSound(SOUND_SNIPER_FIRE );
}
if ( ulAvailable&(1<<(WEAPON_MINIGUN-1)) ) {
pdec->PrecacheModel(MODEL_MINIGUN );
pdec->PrecacheModel(MODEL_MG_BARRELS );
pdec->PrecacheModel(MODEL_MG_BODY );
pdec->PrecacheModel(MODEL_MG_ENGINE );
pdec->PrecacheTexture(TEXTURE_MG_BODY );
pdec->PrecacheTexture(TEXTURE_MG_BARRELS );
pdec->PrecacheSound(SOUND_MINIGUN_FIRE );
pdec->PrecacheSound(SOUND_MINIGUN_ROTATE );
pdec->PrecacheSound(SOUND_MINIGUN_SPINUP );
pdec->PrecacheSound(SOUND_MINIGUN_SPINDOWN );
pdec->PrecacheSound(SOUND_MINIGUN_CLICK );
}
if ( ulAvailable&(1<<(WEAPON_ROCKETLAUNCHER-1)) ) {
pdec->PrecacheModel(MODEL_ROCKETLAUNCHER );
pdec->PrecacheModel(MODEL_RL_BODY );
pdec->PrecacheModel(MODEL_RL_ROTATINGPART );
pdec->PrecacheModel(MODEL_RL_ROCKET );
pdec->PrecacheTexture(TEXTURE_RL_BODY );
pdec->PrecacheTexture(TEXTURE_RL_ROCKET );
pdec->PrecacheSound(SOUND_ROCKETLAUNCHER_FIRE);
pdec->PrecacheClass(CLASS_PROJECTILE, PRT_ROCKET);
}
if ( ulAvailable&(1<<(WEAPON_GRENADELAUNCHER-1)) ) {
pdec->PrecacheModel(MODEL_GRENADELAUNCHER );
pdec->PrecacheModel(MODEL_GL_BODY );
pdec->PrecacheModel(MODEL_GL_MOVINGPART );
pdec->PrecacheModel(MODEL_GL_GRENADE );
pdec->PrecacheTexture(TEXTURE_GL_BODY );
pdec->PrecacheTexture(TEXTURE_GL_MOVINGPART );
pdec->PrecacheSound(SOUND_GRENADELAUNCHER_FIRE );
pdec->PrecacheClass(CLASS_PROJECTILE, PRT_GRENADE);
}
/*
if ( ulAvailable&(1<<(WEAPON_PIPEBOMB-1)) ) {
pdec->PrecacheModel(MODEL_PIPEBOMB_STICK );
pdec->PrecacheModel(MODEL_PIPEBOMB_HAND );
pdec->PrecacheModel(MODEL_PB_BUTTON );
pdec->PrecacheModel(MODEL_PB_SHIELD );
pdec->PrecacheModel(MODEL_PB_STICK );
pdec->PrecacheModel(MODEL_PB_BOMB );
pdec->PrecacheTexture(TEXTURE_PB_STICK );
pdec->PrecacheTexture(TEXTURE_PB_BOMB );
pdec->PrecacheSound(SOUND_PIPEBOMB_FIRE );
pdec->PrecacheSound(SOUND_PIPEBOMB_OPEN );
pdec->PrecacheSound(SOUND_PIPEBOMB_THROW );
pdec->PrecacheClass(CLASS_PIPEBOMB);
}
*/
if ( ulAvailable&(1<<(WEAPON_CHAINSAW-1))) {
pdec->PrecacheModel(MODEL_CHAINSAW );
pdec->PrecacheModel(MODEL_CS_BODY );
pdec->PrecacheModel(MODEL_CS_BLADE );
pdec->PrecacheModel(MODEL_CS_TEETH );
pdec->PrecacheTexture(TEXTURE_CS_BODY );
pdec->PrecacheTexture(TEXTURE_CS_BLADE );
pdec->PrecacheTexture(TEXTURE_CS_TEETH );
pdec->PrecacheSound(SOUND_CS_FIRE );
pdec->PrecacheSound(SOUND_CS_BEGINFIRE );
pdec->PrecacheSound(SOUND_CS_ENDFIRE );
pdec->PrecacheSound(SOUND_CS_BRINGUP );
pdec->PrecacheSound(SOUND_CS_BRINGDOWN );
pdec->PrecacheSound(SOUND_CS_IDLE );
}
if ( ulAvailable&(1<<(WEAPON_FLAMER-1)) ) {
pdec->PrecacheModel(MODEL_FLAMER );
pdec->PrecacheModel(MODEL_FL_BODY );
pdec->PrecacheModel(MODEL_FL_RESERVOIR);
pdec->PrecacheModel(MODEL_FL_FLAME );
pdec->PrecacheTexture(TEXTURE_FL_BODY );
pdec->PrecacheTexture(TEXTURE_FL_FLAME);
pdec->PrecacheTexture(TEXTURE_FL_FUELRESERVOIR);
pdec->PrecacheSound(SOUND_FL_FIRE );
pdec->PrecacheSound(SOUND_FL_START );
pdec->PrecacheSound(SOUND_FL_STOP );
pdec->PrecacheClass(CLASS_PROJECTILE, PRT_FLAME);
}
if ( ulAvailable&(1<<(WEAPON_LASER-1)) ) {
pdec->PrecacheModel(MODEL_LASER );
pdec->PrecacheModel(MODEL_LS_BODY );
pdec->PrecacheModel(MODEL_LS_BARREL );
pdec->PrecacheTexture(TEXTURE_LS_BODY );
pdec->PrecacheTexture(TEXTURE_LS_BARREL);
pdec->PrecacheSound(SOUND_LASER_FIRE);
pdec->PrecacheClass(CLASS_PROJECTILE, PRT_LASER_RAY);
}
/*
if ( ulAvailable&(1<<(WEAPON_GHOSTBUSTER-1)) ) {
pdec->PrecacheModel(MODEL_GHOSTBUSTER );
pdec->PrecacheModel(MODEL_GB_BODY );
pdec->PrecacheModel(MODEL_GB_ROTATOR );
pdec->PrecacheModel(MODEL_GB_EFFECT1 );
pdec->PrecacheModel(MODEL_GB_EFFECT1FLARE );
pdec->PrecacheTexture(TEXTURE_GB_ROTATOR );
pdec->PrecacheTexture(TEXTURE_GB_BODY );
pdec->PrecacheTexture(TEXTURE_GB_LIGHTNING);
pdec->PrecacheTexture(TEXTURE_GB_FLARE );
pdec->PrecacheSound(SOUND_GB_FIRE );
pdec->PrecacheClass(CLASS_GHOSTBUSTERRAY);
}
*/
if ( ulAvailable&(1<<(WEAPON_IRONCANNON-1)) /*||
ulAvailable&(1<<(WEAPON_NUKECANNON-1))*/ ) {
pdec->PrecacheModel(MODEL_CANNON );
pdec->PrecacheModel(MODEL_CN_BODY );
// pdec->PrecacheModel(MODEL_CN_NUKEBOX);
pdec->PrecacheTexture(TEXTURE_CANNON);
pdec->PrecacheSound(SOUND_CANNON );
pdec->PrecacheSound(SOUND_CANNON_PREPARE);
pdec->PrecacheClass(CLASS_CANNONBALL);
}
// precache animator too
extern void CPlayerAnimator_Precache(ULONG ulAvailable);
CPlayerAnimator_Precache(ulAvailable);
}
void CPlayerWeapons_Init(void) {
// declare weapon position controls
_pShell->DeclareSymbol("user INDEX wpn_iCurrent;", &wpn_iCurrent);
#include "Common/WeaponPositions.h"
// declare crosshair and its coordinates
_pShell->DeclareSymbol("persistent user INDEX hud_bCrosshairFixed;", &hud_bCrosshairFixed);
_pShell->DeclareSymbol("persistent user INDEX hud_bCrosshairColoring;", &hud_bCrosshairColoring);
_pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairScale;", &hud_fCrosshairScale);
_pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairRatio;", &hud_fCrosshairRatio);
_pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairOpacity;", &hud_fCrosshairOpacity);
_pShell->DeclareSymbol("persistent user INDEX hud_bShowPlayerName;", &hud_bShowPlayerName);
_pShell->DeclareSymbol("persistent user INDEX hud_bShowCoords;", &hud_bShowCoords);
_pShell->DeclareSymbol("persistent user FLOAT plr_tmSnoopingTime;", &plr_tmSnoopingTime);
_pShell->DeclareSymbol("persistent user FLOAT plr_tmSnoopingDelay;", &plr_tmSnoopingDelay);
// precache base weapons
CPlayerWeapons_Precache(0x03);
}
// weapons positions for raycasting and firing
/*
static FLOAT afKnifePos[4] = { -0.01f, 0.25f, 0.0f};
static FLOAT afColtPos[4] = { -0.01f, 0.1f, 0.0f};
static FLOAT afDoubleColtPos[4] = { -0.01f, 0.1f, 0.0f};
static FLOAT afSingleShotgunPos[4] = { 0.0f, 0.1f, 0.0f};
static FLOAT afDoubleShotgunPos[4] = { 0.0f, 0.1f, 0.0f};
static FLOAT afTommygunPos[4] = { 0.0f, 0.1f, 0.0f};
static FLOAT afMinigunPos[4] = { 0.0f, -0.075f, 0.0f};
static FLOAT afRocketLauncherPos[4] = { -0.175f, 0.19f, -0.23f};
static FLOAT afGrenadeLauncherPos[4] = { 0.0f, 0.16f, -1.42f};
static FLOAT afPipebombPos[4] = { 0.01f, 0.04f, -0.44f};
static FLOAT afFlamerPos[4] = { 0.0f, 0.18f, -0.62f};
static FLOAT afLaserPos[4] = { 0.0f, -0.095f, -0.65f};
static FLOAT afGhostBusterPos[4] = { 0.0f, 0.0f, -0.74f};
static FLOAT afCannonPos[4] = { 0.0f, 0.0f, -0.74f};
*/
// extra weapon positions for shells dropout
static FLOAT afSingleShotgunShellPos[3] = { 0.2f, 0.0f, -0.31f};
static FLOAT afDoubleShotgunShellPos[3] = { 0.0f, 0.0f, -0.5f};
static FLOAT afTommygunShellPos[3] = { 0.2f, 0.0f, -0.31f};
static FLOAT afMinigunShellPos[3] = { 0.2f, 0.0f, -0.31f};
static FLOAT afMinigunShellPos3rdView[3] = { 0.2f, 0.2f, -0.31f};
static FLOAT afSniperShellPos[3] = { 0.2f, 0.0f, -0.15f};
static FLOAT afRightColtPipe[3] = { 0.07f, -0.05f, -0.26f};
static FLOAT afSingleShotgunPipe[3] = { 0.2f, 0.0f, -1.25f};
static FLOAT afDoubleShotgunPipe[3] = { 0.2f, 0.0f, -1.25f};
static FLOAT afTommygunPipe[3] = { -0.06f, 0.1f, -0.6f};
static FLOAT afMinigunPipe[3] = { -0.06f, 0.0f, -0.6f};
static FLOAT afMinigunPipe3rdView[3] = { 0.25f, 0.3f, -2.5f};
//static FLOAT afLaserPos[4] = { 0.0f, -0.095f, -0.65f};
//static FLOAT afLaser1Pos[4] = { -0.115f, -0.05f, -0.65f};
//static FLOAT afLaser2Pos[4] = { 0.115f, -0.05f, -0.65f};
//static FLOAT afLaser3Pos[4] = { -0.145f, -0.14f, -0.8f};
//static FLOAT afLaser4Pos[4] = { 0.145f, -0.14f, -0.8f};
#define TM_START m_aMiniGun
#define F_OFFSET_CHG m_aMiniGunLast
#define F_TEMP m_aMiniGunSpeed
// decrement ammo taking infinite ammo options in account
void DecAmmo(INDEX &ctAmmo, INDEX iDec = 1)
{
if (!GetSP()->sp_bInfiniteAmmo) {
ctAmmo-=iDec;
}
}
%}
class export CPlayerWeapons : CRationalEntity {
name "Player Weapons";
thumbnail "";
features "CanBePredictable";
properties:
1 CEntityPointer m_penPlayer, // player which owns it
2 BOOL m_bFireWeapon = FALSE, // weapon is firing
3 BOOL m_bHasAmmo = FALSE, // weapon has ammo
4 enum WeaponType m_iCurrentWeapon = WEAPON_KNIFE, // currently active weapon (internal)
5 enum WeaponType m_iWantedWeapon = WEAPON_KNIFE, // wanted weapon (internal)
6 enum WeaponType m_iPreviousWeapon = WEAPON_KNIFE, // previous active weapon (internal)
11 INDEX m_iAvailableWeapons = 0x01, // avaible weapons
12 BOOL m_bChangeWeapon = FALSE, // change current weapon
13 BOOL m_bReloadWeapon = FALSE, // reload weapon
14 BOOL m_bMirrorFire = FALSE, // fire with mirror model
15 INDEX m_iAnim = 0, // temporary anim variable
16 FLOAT m_fAnimWaitTime = 0.0f, // animation wait time
17 FLOAT m_tmRangeSoundSpawned = 0.0f, // for not spawning range sounds too often
23 BOOL m_bSniperZoom = FALSE, // zoom sniper
24 FLOAT m_fSniperFOV = 90.0f, // sniper FOV
28 FLOAT m_fSniperFOVlast = 90.0f, // sniper FOV for lerping
18 CTString m_strLastTarget = "", // string for last target
19 FLOAT m_tmTargetingStarted = -99.0f, // when targeting started
20 FLOAT m_tmLastTarget = -99.0f, // when last target was seen
21 FLOAT m_tmSnoopingStarted = -99.0f, // is player spying another player
22 CEntityPointer m_penTargeting, // who is the target
25 CModelObject m_moWeapon, // current weapon model
26 CModelObject m_moWeaponSecond, // current weapon second (additional) model
27 FLOAT m_tmWeaponChangeRequired = 0.0f, // time when weapon change was required
30 CEntityPointer m_penRayHit, // entity hit by ray
31 FLOAT m_fRayHitDistance = 100.0f, // distance from hit point
32 FLOAT m_fEnemyHealth = 0.0f, // normalized health of enemy in target (for coloring of crosshair)
33 FLOAT3D m_vRayHit = FLOAT3D(0,0,0), // coordinates where ray hit
34 FLOAT3D m_vRayHitLast = FLOAT3D(0,0,0), // for lerping
35 FLOAT3D m_vBulletSource = FLOAT3D(0,0,0), // bullet launch position remembered here
36 FLOAT3D m_vBulletTarget = FLOAT3D(0,0,0), // bullet hit (if hit) position remembered here
// ammo for all weapons
40 INDEX m_iBullets = 0,
41 INDEX m_iMaxBullets = MAX_BULLETS,
42 INDEX m_iShells = 0,
43 INDEX m_iMaxShells = MAX_SHELLS,
44 INDEX m_iRockets = 0,
45 INDEX m_iMaxRockets = MAX_ROCKETS,
46 INDEX m_iGrenades = 0,
47 INDEX m_iMaxGrenades = MAX_GRENADES,
48 INDEX m_iNapalm = 0,
49 INDEX m_iMaxNapalm = MAX_NAPALM,
50 INDEX m_iElectricity = 0,
51 INDEX m_iMaxElectricity = MAX_ELECTRICITY,
52 INDEX m_iIronBalls = 0,
53 INDEX m_iMaxIronBalls = MAX_IRONBALLS,
// 54 INDEX m_iNukeBalls = 0,
// 55 INDEX m_iMaxNukeBalls = MAX_NUKEBALLS,
54 INDEX m_iSniperBullets = 0,
55 INDEX m_iMaxSniperBullets = MAX_SNIPERBULLETS,
// weapons specific
// knife
210 INDEX m_iKnifeStand = 1,
// colt
215 INDEX m_iColtBullets = 6,
// minigun
220 FLOAT m_aMiniGun = 0.0f,
221 FLOAT m_aMiniGunLast = 0.0f,
222 FLOAT m_aMiniGunSpeed = 0.0f,
// lerped bullets fire
230 FLOAT3D m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f),
231 INDEX m_iBulletsOnFireStart = 0,
// sniper
233 FLOAT m_fSniperMaxFOV = 90.0f,
234 FLOAT m_fSniperMinFOV = 14.2f,
235 FLOAT m_fSnipingZoomSpeed = 2.0f,
236 BOOL m_bSniping = FALSE,
237 FLOAT m_fMinimumZoomFOV = 53.1f,
238 FLOAT m_tmLastSniperFire = 0.0f,
// pipebomb
//235 CEntityPointer m_penPipebomb,
//236 INDEX m_bPipeBombDropped = FALSE,
// flamer
240 CEntityPointer m_penFlame,
// laser
245 INDEX m_iLaserBarrel = 0,
// ghostbuster
//250 CEntityPointer m_penGhostBusterRay,
// fire flare
251 INDEX m_iFlare = FLARE_REMOVE, // 0-none, 1-remove, 2-add
252 INDEX m_iSecondFlare = FLARE_REMOVE, // 0-none, 1-remove, 2-add
// cannon
260 FLOAT m_fWeaponDrawPowerOld = 0,
261 FLOAT m_fWeaponDrawPower = 0,
262 FLOAT m_tmDrawStartTime = 0.0f,
270 FLOAT m_tmFlamerStart=1e6,
271 FLOAT m_tmFlamerStop=1e9,
272 FLOAT m_tmLastChainsawSpray = 0.0f,
{
CEntity *penBullet;
CPlacement3D plBullet;
FLOAT3D vBulletDestination;
}
components:
1 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
2 class CLASS_BULLET "Classes\\Bullet.ecl",
3 class CLASS_WEAPONEFFECT "Classes\\PlayerWeaponsEffects.ecl",
4 class CLASS_PIPEBOMB "Classes\\Pipebomb.ecl",
// 5 class CLASS_GHOSTBUSTERRAY "Classes\\GhostBusterRay.ecl",
6 class CLASS_CANNONBALL "Classes\\CannonBall.ecl",
7 class CLASS_WEAPONITEM "Classes\\WeaponItem.ecl",
8 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
// ************** HAND **************
10 texture TEXTURE_HAND "Models\\Weapons\\Hand.tex",
// ************** KNIFE **************
20 model MODEL_KNIFEITEM "Models\\Weapons\\Knife\\KnifeItem.mdl",
21 texture TEXTURE_KNIFEITEM "Models\\Weapons\\Knife\\KnifeItem.tex",
22 model MODEL_KNIFE "Models\\Weapons\\Knife\\Knife.mdl",
23 sound SOUND_KNIFE_BACK "Models\\Weapons\\Knife\\Sounds\\Back.wav",
24 sound SOUND_KNIFE_HIGH "Models\\Weapons\\Knife\\Sounds\\High.wav",
25 sound SOUND_KNIFE_LONG "Models\\Weapons\\Knife\\Sounds\\Long.wav",
26 sound SOUND_KNIFE_LOW "Models\\Weapons\\Knife\\Sounds\\Low.wav",
// ************** COLT **************
30 model MODEL_COLT "Models\\Weapons\\Colt\\Colt.mdl",
31 model MODEL_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.mdl",
32 model MODEL_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.mdl",
33 model MODEL_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.mdl",
34 texture TEXTURE_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.tex",
35 texture TEXTURE_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.tex",
36 texture TEXTURE_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.tex",
37 sound SOUND_COLT_FIRE "Models\\Weapons\\Colt\\Sounds\\Fire.wav",
38 sound SOUND_COLT_RELOAD "Models\\Weapons\\Colt\\Sounds\\Reload.wav",
// ************** SINGLE SHOTGUN ************
40 model MODEL_SINGLESHOTGUN "Models\\Weapons\\SingleShotgun\\SingleShotgun.mdl",
41 model MODEL_SS_SLIDER "Models\\Weapons\\SingleShotgun\\Slider.mdl",
42 model MODEL_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.mdl",
43 model MODEL_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.mdl",
44 texture TEXTURE_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.tex",
45 texture TEXTURE_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.tex",
46 sound SOUND_SINGLESHOTGUN_FIRE "Models\\Weapons\\SingleShotgun\\Sounds\\_Fire.wav",
// ************** DOUBLE SHOTGUN **************
50 model MODEL_DOUBLESHOTGUN "Models\\Weapons\\DoubleShotgun\\DoubleShotgun.mdl",
51 model MODEL_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl",
52 model MODEL_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl",
53 model MODEL_DS_AMMO "Models\\Weapons\\DoubleShotgun\\Ammo.mdl",
54 model MODEL_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.mdl",
55 model MODEL_DS_HANDWITHAMMO "Models\\Weapons\\DoubleShotgun\\HandWithAmmo.mdl",
56 texture TEXTURE_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Handle.tex",
57 texture TEXTURE_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Barrels.tex",
58 texture TEXTURE_DS_AMMO "Models\\Weapons\\DoubleShotgun\\Ammo.tex",
59 texture TEXTURE_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.tex",
60 sound SOUND_DOUBLESHOTGUN_FIRE "Models\\Weapons\\DoubleShotgun\\Sounds\\Fire.wav",
61 sound SOUND_DOUBLESHOTGUN_RELOAD "Models\\Weapons\\DoubleShotgun\\Sounds\\Reload.wav",
// ************** TOMMYGUN **************
70 model MODEL_TOMMYGUN "Models\\Weapons\\TommyGun\\TommyGun.mdl",
71 model MODEL_TG_BODY "Models\\Weapons\\TommyGun\\Body.mdl",
72 model MODEL_TG_SLIDER "Models\\Weapons\\TommyGun\\Slider.mdl",
73 texture TEXTURE_TG_BODY "Models\\Weapons\\TommyGun\\Body.tex",
74 sound SOUND_TOMMYGUN_FIRE "Models\\Weapons\\TommyGun\\Sounds\\_Fire.wav",
// ************** MINIGUN **************
80 model MODEL_MINIGUN "Models\\Weapons\\MiniGun\\MiniGun.mdl",
81 model MODEL_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.mdl",
82 model MODEL_MG_BODY "Models\\Weapons\\MiniGun\\Body.mdl",
83 model MODEL_MG_ENGINE "Models\\Weapons\\MiniGun\\Engine.mdl",
84 texture TEXTURE_MG_BODY "Models\\Weapons\\MiniGun\\Body.tex",
99 texture TEXTURE_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.tex",
85 sound SOUND_MINIGUN_FIRE "Models\\Weapons\\MiniGun\\Sounds\\Fire.wav",
86 sound SOUND_MINIGUN_ROTATE "Models\\Weapons\\MiniGun\\Sounds\\Rotate.wav",
87 sound SOUND_MINIGUN_SPINUP "Models\\Weapons\\MiniGun\\Sounds\\RotateUp.wav",
88 sound SOUND_MINIGUN_SPINDOWN "Models\\Weapons\\MiniGun\\Sounds\\RotateDown.wav",
89 sound SOUND_MINIGUN_CLICK "Models\\Weapons\\MiniGun\\Sounds\\Click.wav",
// ************** ROCKET LAUNCHER **************
90 model MODEL_ROCKETLAUNCHER "Models\\Weapons\\RocketLauncher\\RocketLauncher.mdl",
91 model MODEL_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.mdl",
92 texture TEXTURE_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.tex",
93 model MODEL_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl",
94 texture TEXTURE_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.tex",
95 model MODEL_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl",
96 texture TEXTURE_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex",
97 sound SOUND_ROCKETLAUNCHER_FIRE "Models\\Weapons\\RocketLauncher\\Sounds\\_Fire.wav",
// ************** GRENADE LAUNCHER **************
100 model MODEL_GRENADELAUNCHER "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncher.mdl",
101 model MODEL_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.mdl",
102 model MODEL_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl",
103 model MODEL_GL_GRENADE "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl",
104 texture TEXTURE_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.tex",
105 texture TEXTURE_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex",
106 sound SOUND_GRENADELAUNCHER_FIRE "Models\\Weapons\\GrenadeLauncher\\Sounds\\_Fire.wav",
// ************** SNIPER **************
110 model MODEL_SNIPER "ModelsMP\\Weapons\\Sniper\\Sniper.mdl",
111 model MODEL_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.mdl",
112 texture TEXTURE_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.tex",
113 sound SOUND_SNIPER_FIRE "ModelsMP\\Weapons\\Sniper\\Sounds\\Fire.wav",
//114 sound SOUND_SNIPER_RELOAD "ModelsMP\\Weapons\\Sniper\\Sounds\\Reload.wav",
//115 sound SOUND_SNIPER_ZOOM "ModelsMP\\Weapons\\Sniper\\Sounds\\Zoom.wav",
/*
// ************** PIPEBOMB **************
110 model MODEL_PIPEBOMB_STICK "Models\\Weapons\\Pipebomb\\HandWithStick.mdl",
111 model MODEL_PIPEBOMB_HAND "Models\\Weapons\\Pipebomb\\HandWithBomb.mdl",
112 model MODEL_PB_BUTTON "Models\\Weapons\\Pipebomb\\Button.mdl",
113 model MODEL_PB_SHIELD "Models\\Weapons\\Pipebomb\\Shield.mdl",
114 model MODEL_PB_STICK "Models\\Weapons\\Pipebomb\\Stick.mdl",
115 model MODEL_PB_BOMB "Models\\Weapons\\Pipebomb\\Bomb.mdl",
116 texture TEXTURE_PB_STICK "Models\\Weapons\\Pipebomb\\Stick.tex",
117 texture TEXTURE_PB_BOMB "Models\\Weapons\\Pipebomb\\Bomb.tex",
118 sound SOUND_PIPEBOMB_FIRE "Models\\Weapons\\Pipebomb\\Sounds\\Fire.wav",
119 sound SOUND_PIPEBOMB_OPEN "Models\\Weapons\\Pipebomb\\Sounds\\Open.wav",
120 sound SOUND_PIPEBOMB_THROW "Models\\Weapons\\Pipebomb\\Sounds\\Throw.wav",
*/
// ************** FLAMER **************
130 model MODEL_FLAMER "ModelsMP\\Weapons\\Flamer\\Flamer.mdl",
131 model MODEL_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.mdl",
132 model MODEL_FL_RESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl",
133 model MODEL_FL_FLAME "ModelsMP\\Weapons\\Flamer\\Flame.mdl",
134 texture TEXTURE_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.tex",
135 texture TEXTURE_FL_FLAME "ModelsMP\\Effects\\Flame\\Flame.tex",
136 sound SOUND_FL_FIRE "ModelsMP\\Weapons\\Flamer\\Sounds\\Fire.wav",
137 sound SOUND_FL_START "ModelsMP\\Weapons\\Flamer\\Sounds\\Start.wav",
138 sound SOUND_FL_STOP "ModelsMP\\Weapons\\Flamer\\Sounds\\Stop.wav",
139 texture TEXTURE_FL_FUELRESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex",
// ************** LASER **************
140 model MODEL_LASER "Models\\Weapons\\Laser\\Laser.mdl",
141 model MODEL_LS_BODY "Models\\Weapons\\Laser\\Body.mdl",
142 model MODEL_LS_BARREL "Models\\Weapons\\Laser\\Barrel.mdl",
144 texture TEXTURE_LS_BODY "Models\\Weapons\\Laser\\Body.tex",
145 texture TEXTURE_LS_BARREL "Models\\Weapons\\Laser\\Barrel.tex",
146 sound SOUND_LASER_FIRE "Models\\Weapons\\Laser\\Sounds\\_Fire.wav",
// ************** CHAINSAW **************
150 model MODEL_CHAINSAW "ModelsMP\\Weapons\\Chainsaw\\Chainsaw.mdl",
151 model MODEL_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.mdl",
152 model MODEL_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl",
160 model MODEL_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl",
153 texture TEXTURE_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.tex",
154 texture TEXTURE_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.tex",
161 texture TEXTURE_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex",
155 sound SOUND_CS_FIRE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\Fire.wav",
156 sound SOUND_CS_BEGINFIRE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BeginFire.wav",
157 sound SOUND_CS_ENDFIRE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\EndFire.wav",
158 sound SOUND_CS_BRINGUP "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BringUp.wav",
159 sound SOUND_CS_IDLE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\Idle.wav",
162 sound SOUND_CS_BRINGDOWN "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BringDown.wav",
/*
// ************** GHOSTBUSTER **************
150 model MODEL_GHOSTBUSTER "Models\\Weapons\\GhostBuster\\GhostBuster.mdl",
151 model MODEL_GB_BODY "Models\\Weapons\\GhostBuster\\Body.mdl",
152 model MODEL_GB_ROTATOR "Models\\Weapons\\GhostBuster\\Rotator.mdl",
153 model MODEL_GB_EFFECT1 "Models\\Weapons\\GhostBuster\\Effect01.mdl",
154 model MODEL_GB_EFFECT1FLARE "Models\\Weapons\\GhostBuster\\EffectFlare01.mdl",
155 texture TEXTURE_GB_ROTATOR "Models\\Weapons\\GhostBuster\\Rotator.tex",
156 texture TEXTURE_GB_BODY "Models\\Weapons\\GhostBuster\\Body.tex",
157 texture TEXTURE_GB_LIGHTNING "Models\\Weapons\\GhostBuster\\Lightning.tex",
158 texture TEXTURE_GB_FLARE "Models\\Weapons\\GhostBuster\\EffectFlare.tex",
159 sound SOUND_GB_FIRE "Models\\Weapons\\GhostBuster\\Sounds\\_Fire.wav",
*/
// ************** CANNON **************
170 model MODEL_CANNON "Models\\Weapons\\Cannon\\Cannon.mdl",
171 model MODEL_CN_BODY "Models\\Weapons\\Cannon\\Body.mdl",
//172 model MODEL_CN_NUKEBOX "Models\\Weapons\\Cannon\\NukeBox.mdl",
173 texture TEXTURE_CANNON "Models\\Weapons\\Cannon\\Body.tex",
174 sound SOUND_CANNON "Models\\Weapons\\Cannon\\Sounds\\Fire.wav",
175 sound SOUND_CANNON_PREPARE "Models\\Weapons\\Cannon\\Sounds\\Prepare.wav",
//175 model MODEL_CN_LIGHT "Models\\Weapons\\Cannon\\Light.mdl",
// ************** REFLECTIONS **************
200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex",
201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex",
202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex",
204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex",
205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex",
// ************** SPECULAR **************
210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex",
211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex",
// ************** FLARES **************
250 model MODEL_FLARE01 "Models\\Effects\\Weapons\\Flare01\\Flare.mdl",
251 texture TEXTURE_FLARE01 "Models\\Effects\\Weapons\\Flare01\\Flare.tex",
280 sound SOUND_SILENCE "Sounds\\Misc\\Silence.wav",
functions:
// add to prediction any entities that this entity depends on
void AddDependentsToPrediction(void)
{
m_penPlayer->AddToPrediction();
//m_penPipebomb->AddToPrediction();
//m_penGhostBusterRay->AddToPrediction();
m_penFlame->AddToPrediction();
}
void Precache(void)
{
CPlayerWeapons_Precache(m_iAvailableWeapons);
}
CPlayer *GetPlayer(void)
{
ASSERT(m_penPlayer!=NULL);
return (CPlayer *)&*m_penPlayer;
}
CPlayerAnimator *GetAnimator(void)
{
ASSERT(m_penPlayer!=NULL);
return ((CPlayerAnimator*)&*((CPlayer&)*m_penPlayer).m_penAnimator);
}
CModelObject *GetChainSawTeeth(void)
{
CPlayer *ppl=GetPlayer();
if(ppl==NULL) { return NULL;}
CModelObject *pmoPlayer = ppl->GetModelObject();
if(pmoPlayer==NULL) { return NULL;}
CAttachmentModelObject *pamoTorso = pmoPlayer->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO);
if(pamoTorso==NULL) { return NULL;}
CAttachmentModelObject *pamoChainSaw = pamoTorso->amo_moModelObject.GetAttachmentModel(BODY_ATTACHMENT_MINIGUN);
if(pamoChainSaw==NULL) { return NULL;}
CAttachmentModelObject *pamoBlade = pamoChainSaw->amo_moModelObject.GetAttachmentModel(CHAINSAWFORPLAYER_ATTACHMENT_BLADE);
if(pamoBlade==NULL) { return NULL;}
CAttachmentModelObject *pamoTeeth = pamoBlade->amo_moModelObject.GetAttachmentModel(BLADE_ATTACHMENT_TEETH);
if(pamoTeeth==NULL) { return NULL;}
return &pamoTeeth->amo_moModelObject;
}
// recoil
void DoRecoil(void)
{
// CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator;
// plan.m_fRecoilSpeed += wpn_fRecoilSpeed[m_iCurrentWeapon];
}
//
BOOL HoldingFire(void)
{
return m_bFireWeapon && !m_bChangeWeapon;
}
// render weapon model(s)
void RenderWeaponModel( CPerspectiveProjection3D &prProjection, CDrawPort *pdp,
FLOAT3D vViewerLightDirection, COLOR colViewerLight, COLOR colViewerAmbient,
BOOL bRender, INDEX iEye)
{
_mrpModelRenderPrefs.SetRenderType( RT_TEXTURE|RT_SHADING_PHONG);
// flare attachment
ControlFlareAttachment();
if( !bRender || m_iCurrentWeapon==WEAPON_NONE
|| GetPlayer()->GetSettings()->ps_ulFlags&PSF_HIDEWEAPON) { return; }
// nuke and iron cannons have the same view settings
INDEX iWeaponData = m_iCurrentWeapon;
// store FOV for Crosshair
const FLOAT fFOV = ((CPerspectiveProjection3D &)prProjection).FOVL();
CPlacement3D plView;
plView = ((CPlayer&)*m_penPlayer).en_plViewpoint;
plView.RelativeToAbsolute(m_penPlayer->GetPlacement());
// added: chainsaw shaking
CPlacement3D plWeapon;
if (m_iCurrentWeapon==WEAPON_CHAINSAW) {
CPlayer *plPlayer = (CPlayer*)&*m_penPlayer;
plWeapon = CPlacement3D ( FLOAT3D(wpn_fX[iWeaponData]+plPlayer->m_fChainsawShakeDX*0.35f,
wpn_fY[iWeaponData]+plPlayer->m_fChainsawShakeDY*0.35f,
wpn_fZ[iWeaponData]),
ANGLE3D(AngleDeg(wpn_fH[iWeaponData]),
AngleDeg(wpn_fP[iWeaponData]),
AngleDeg(wpn_fB[iWeaponData])));
} else {
plWeapon = CPlacement3D ( FLOAT3D(wpn_fX[iWeaponData],
wpn_fY[iWeaponData],
wpn_fZ[iWeaponData]),
ANGLE3D(AngleDeg(wpn_fH[iWeaponData]),
AngleDeg(wpn_fP[iWeaponData]),
AngleDeg(wpn_fB[iWeaponData])));
}
// make sure that weapon will be bright enough
UBYTE ubLR,ubLG,ubLB, ubAR,ubAG,ubAB;
ColorToRGB( colViewerLight, ubLR,ubLG,ubLB);
ColorToRGB( colViewerAmbient, ubAR,ubAG,ubAB);
INDEX iMinDL = Min( Min(ubLR,ubLG),ubLB) -32;
INDEX iMinDA = Min( Min(ubAR,ubAG),ubAB) -32;
if( iMinDL<0) {
ubLR = ClampUp( ubLR-iMinDL, (INDEX)255);
ubLG = ClampUp( ubLG-iMinDL, (INDEX)255);
ubLB = ClampUp( ubLB-iMinDL, (INDEX)255);
}
if( iMinDA<0) {
ubAR = ClampUp( ubAR-iMinDA, (INDEX)255);
ubAG = ClampUp( ubAG-iMinDA, (INDEX)255);
ubAB = ClampUp( ubAB-iMinDA, (INDEX)255);
}
const COLOR colLight = RGBToColor( ubLR,ubLG,ubLB);
const COLOR colAmbient = RGBToColor( ubAR,ubAG,ubAB);
const FLOAT tmNow = _pTimer->GetLerpedCurrentTick();
UBYTE ubBlend = INVISIBILITY_ALPHA_LOCAL;
FLOAT tmInvisibility = ((CPlayer *)&*m_penPlayer)->m_tmInvisibility;
//FLOAT tmSeriousDamage = ((CPlayer *)&*m_penPlayer)->m_tmSeriousDamage;
//FLOAT tmInvulnerability = ((CPlayer *)&*m_penPlayer)->m_tmInvulnerability;
if (tmInvisibility>tmNow) {
FLOAT fIntensity=0.0f;
if((tmInvisibility-tmNow)<3.0f)
{
fIntensity = 0.5f-0.5f*cos((tmInvisibility-tmNow)*(6.0f*3.1415927f/3.0f));
ubBlend =(INDEX)(INVISIBILITY_ALPHA_LOCAL+(FLOAT)(254-INVISIBILITY_ALPHA_LOCAL)*fIntensity);
}
}
// DRAW WEAPON MODEL
// Double colt - second colt in mirror
// Double shotgun - hand with ammo
if( iWeaponData==WEAPON_DOUBLECOLT|| iWeaponData==WEAPON_DOUBLESHOTGUN )
{
// prepare render model structure and projection
CRenderModel rmMain;
CPerspectiveProjection3D prMirror = prProjection;
prMirror.ViewerPlacementL() = plView;
prMirror.FrontClipDistanceL() = wpn_fClip[iWeaponData];
prMirror.DepthBufferNearL() = 0.0f;
prMirror.DepthBufferFarL() = 0.1f;
// This line confuses gcc 2.95.3 unless split up. --ryan.
//CPlacement3D plWeaponMirror( FLOAT3D(wpn_fX[iWeaponData], wpn_fY[iWeaponData], wpn_fZ[iWeaponData]),
// ANGLE3D(AngleDeg(wpn_fH[iWeaponData]), AngleDeg(wpn_fP[iWeaponData]),
// AngleDeg(wpn_fB[iWeaponData])));
FLOAT3D f3d(wpn_fX[iWeaponData], wpn_fY[iWeaponData], wpn_fZ[iWeaponData]);
ANGLE3D a3d(AngleDeg(wpn_fH[iWeaponData]), AngleDeg(wpn_fP[iWeaponData]),
AngleDeg(wpn_fB[iWeaponData]));
CPlacement3D plWeaponMirror(f3d, a3d);
if( iWeaponData==WEAPON_DOUBLECOLT /*|| iWeaponData==WEAPON_PIPEBOMB*/) {
FLOATmatrix3D mRotation;
MakeRotationMatrixFast(mRotation, plView.pl_OrientationAngle);
plWeaponMirror.pl_PositionVector(1) = -plWeaponMirror.pl_PositionVector(1);
plWeaponMirror.pl_OrientationAngle(1) = -plWeaponMirror.pl_OrientationAngle(1);
plWeaponMirror.pl_OrientationAngle(3) = -plWeaponMirror.pl_OrientationAngle(3);
}
((CPerspectiveProjection3D &)prMirror).FOVL() = AngleDeg(wpn_fFOV[iWeaponData]);
CAnyProjection3D apr;
apr = prMirror;
Stereo_AdjustProjection(*apr, iEye, 0.1f);
BeginModelRenderingView(apr, pdp);
WeaponMovingOffset(plWeaponMirror.pl_PositionVector);
plWeaponMirror.RelativeToAbsoluteSmooth(plView);
rmMain.SetObjectPlacement(plWeaponMirror);
rmMain.rm_colLight = colLight;
rmMain.rm_colAmbient = colAmbient;
rmMain.rm_vLightDirection = vViewerLightDirection;
rmMain.rm_ulFlags |= RMF_WEAPON; // TEMP: for Truform
if (tmInvisibility>tmNow) {
rmMain.rm_colBlend = (rmMain.rm_colBlend&0xffffff00)|ubBlend;
}
m_moWeaponSecond.SetupModelRendering(rmMain);
m_moWeaponSecond.RenderModel(rmMain);
EndModelRenderingView();
}
// minigun specific (update rotation)
if( iWeaponData==WEAPON_MINIGUN) { RotateMinigun(); }
// prepare render model structure
CRenderModel rmMain;
prProjection.ViewerPlacementL() = plView;
prProjection.FrontClipDistanceL() = wpn_fClip[iWeaponData];
prProjection.DepthBufferNearL() = 0.0f;
prProjection.DepthBufferFarL() = 0.1f;
((CPerspectiveProjection3D &)prProjection).FOVL() = AngleDeg(wpn_fFOV[iWeaponData]);
CAnyProjection3D apr;
apr = prProjection;
Stereo_AdjustProjection(*apr, iEye, 0.1f);
BeginModelRenderingView(apr, pdp);
WeaponMovingOffset(plWeapon.pl_PositionVector);
plWeapon.RelativeToAbsoluteSmooth(plView);
rmMain.SetObjectPlacement(plWeapon);
rmMain.rm_colLight = colLight;
rmMain.rm_colAmbient = colAmbient;
rmMain.rm_vLightDirection = vViewerLightDirection;
rmMain.rm_ulFlags |= RMF_WEAPON; // TEMP: for Truform
if (tmInvisibility>tmNow) {
rmMain.rm_colBlend = (rmMain.rm_colBlend&0xffffff00)|ubBlend;
}
m_moWeapon.SetupModelRendering(rmMain);
m_moWeapon.RenderModel(rmMain);
/*if (tmSeriousDamage>tmNow && tmInvulnerability>tmNow) {
Particle_PrepareSystem(pdp, apr);
Particle_PrepareEntity( 1, 0, 0, NULL);
Particles_ModelGlow2(&m_moWeapon, plWeapon, Max(tmSeriousDamage, tmInvulnerability),PT_STAR08, 0.025f, 2, 0.01f, 0xff00ff00);
Particle_EndSystem();
} else if (tmInvulnerability>tmNow) {
Particle_PrepareSystem(pdp, apr);
Particle_PrepareEntity( 1, 0, 0, NULL);
Particles_ModelGlow2(&m_moWeapon, plWeapon, tmInvulnerability, PT_STAR05, 0.025f, tmp_ai[1], 0.01f, 0x3333ff00);
Particle_EndSystem();
} else if (tmSeriousDamage>tmNow) {
Particle_PrepareSystem(pdp, apr);
Particle_PrepareEntity( 1, 0, 0, NULL);
Particles_ModelGlow2(&m_moWeapon, plWeapon, tmSeriousDamage, PT_STAR08, 0.025f, 2, 0.01f, 0xff777700);
Particle_EndSystem();
}*/
EndModelRenderingView();
// restore FOV for Crosshair
((CPerspectiveProjection3D &)prProjection).FOVL() = fFOV;
};
// Weapon moving offset
void WeaponMovingOffset(FLOAT3D &plPos)
{
CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator;
FLOAT fXOffset = Lerp(plan.m_fMoveLastBanking, plan.m_fMoveBanking, _pTimer->GetLerpFactor()) * -0.02f;
FLOAT fYOffset = Lerp(plan.m_fWeaponYLastOffset, plan.m_fWeaponYOffset, _pTimer->GetLerpFactor()) * 0.15f;
fYOffset += (fXOffset * fXOffset) * 30.0f;
plPos(1) += fXOffset;
plPos(2) += fYOffset;
// apply grenade launcher pumping
if( m_iCurrentWeapon == WEAPON_GRENADELAUNCHER)
{
// obtain moving part attachment
CAttachmentModelObject *amo = m_moWeapon.GetAttachmentModel(GRENADELAUNCHER_ATTACHMENT_MOVING_PART);
FLOAT fLerpedMovement = Lerp(m_fWeaponDrawPowerOld, m_fWeaponDrawPower, _pTimer->GetLerpFactor());
amo->amo_plRelative.pl_PositionVector(3) = fLerpedMovement;
plPos(3) += fLerpedMovement/2.0f;
if( m_tmDrawStartTime != 0.0f)
{
FLOAT tmPassed = _pTimer->GetLerpedCurrentTick()-m_tmDrawStartTime;
plPos(1) += Sin(tmPassed*360.0f*10)*0.0125f*tmPassed/6.0f;
plPos(2) += Sin(tmPassed*270.0f*8)*0.01f*tmPassed/6.0f;
}
}
// apply cannon draw
else if( m_iCurrentWeapon == WEAPON_IRONCANNON /*||
(m_iCurrentWeapon == WEAPON_NUKECANNON) */)
{
FLOAT fLerpedMovement = Lerp(m_fWeaponDrawPowerOld, m_fWeaponDrawPower, _pTimer->GetLerpFactor());
plPos(3) += fLerpedMovement;
if( m_tmDrawStartTime != 0.0f)
{
FLOAT tmPassed = _pTimer->GetLerpedCurrentTick()-m_tmDrawStartTime;
plPos(1) += Sin(tmPassed*360.0f*10)*0.0125f*tmPassed/2.0f;
plPos(2) += Sin(tmPassed*270.0f*8)*0.01f*tmPassed/2.0f;
}
}
};
// check target for time prediction updating
void CheckTargetPrediction(CEntity *penTarget)
{
// if target is not predictable
if (!penTarget->IsPredictable()) {
// do nothing
return;
}
extern FLOAT cli_tmPredictFoe;
extern FLOAT cli_tmPredictAlly;
extern FLOAT cli_tmPredictEnemy;
// get your and target's bases for prediction
CEntity *penMe = GetPlayer();
if (IsPredictor()) {
penMe = penMe->GetPredicted();
}
CEntity *penYou = penTarget;
if (penYou->IsPredictor()) {
penYou = penYou->GetPredicted();
}
// if player
if (IsOfClass(penYou, "Player")) {
// if ally player
if (GetSP()->sp_bCooperative) {
// if ally prediction is on and this player is local
if (cli_tmPredictAlly>0 && _pNetwork->IsPlayerLocal(penMe)) {
// predict the ally
penYou->SetPredictionTime(cli_tmPredictAlly);
}
// if foe player
} else {
// if foe prediction is on
if (cli_tmPredictFoe>0) {
// if this player is local
if (_pNetwork->IsPlayerLocal(penMe)) {
// predict the foe
penYou->SetPredictionTime(cli_tmPredictFoe);
}
// if the target is local
if (_pNetwork->IsPlayerLocal(penYou)) {
// predict self
penMe->SetPredictionTime(cli_tmPredictFoe);
}
}
}
} else {
// if enemy prediction is on an it is an enemy
if( cli_tmPredictEnemy>0 && IsDerivedFromClass( penYou, "Enemy Base")) {
// if this player is local
if (_pNetwork->IsPlayerLocal(penMe)) {
// set enemy prediction time
penYou->SetPredictionTime(cli_tmPredictEnemy);
}
}
}
}
// cast a ray from weapon
void UpdateTargetingInfo(void)
{
// crosshair start position from weapon
CPlacement3D plCrosshair;
FLOAT fFX = wpn_fFX[m_iCurrentWeapon]; // get weapon firing position
FLOAT fFY = wpn_fFY[m_iCurrentWeapon];
if (GetPlayer()->m_iViewState == PVT_3RDPERSONVIEW) {
fFX = fFY = 0;
}
CalcWeaponPosition(FLOAT3D(fFX, fFY, 0), plCrosshair, FALSE);
// cast ray
CCastRay crRay( m_penPlayer, plCrosshair);
crRay.cr_bHitTranslucentPortals = FALSE;
crRay.cr_bPhysical = FALSE;
crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX;
GetWorld()->CastRay(crRay);
// store required cast ray results
m_vRayHitLast = m_vRayHit; // for lerping purposes
m_vRayHit = crRay.cr_vHit;
m_penRayHit = crRay.cr_penHit;
m_fRayHitDistance = crRay.cr_fHitDistance;
m_fEnemyHealth = 0.0f;
// set some targeting properties (snooping and such...)
TIME tmNow = _pTimer->CurrentTick();
if( m_penRayHit!=NULL)
{
CEntity *pen = m_penRayHit;
// if alive
if( pen->GetFlags()&ENF_ALIVE)
{
// check the target for time prediction updating
CheckTargetPrediction(pen);
// if player
if( IsOfClass( pen, "Player")) {
// rememer when targeting begun
if( m_tmTargetingStarted==0) {
m_penTargeting = pen;
m_tmTargetingStarted = tmNow;
}
// keep player name, mana and health for eventual printout or coloring
m_fEnemyHealth = ((CPlayer*)pen)->GetHealth() / ((CPlayer*)pen)->m_fMaxHealth;
m_strLastTarget.PrintF( "%s", (const char *) ((CPlayer*)pen)->GetPlayerName());
if( GetSP()->sp_gmGameMode==CSessionProperties::GM_SCOREMATCH) {
// add mana to player name
CTString strMana="";
strMana.PrintF( " (%d)", ((CPlayer*)pen)->m_iMana);
m_strLastTarget += strMana;
}
if( hud_bShowPlayerName) { m_tmLastTarget = tmNow+1.5f; }
}
// not targeting player
else {
// reset targeting
m_tmTargetingStarted = 0;
}
// keep enemy health for eventual crosshair coloring
if( IsDerivedFromClass( pen, "Enemy Base")) {
m_fEnemyHealth = ((CEnemyBase*)pen)->GetHealth() / ((CEnemyBase*)pen)->m_fMaxHealth;
}
// cannot snoop while firing
if( m_bFireWeapon) { m_tmTargetingStarted = 0; }
}
// if not alive
else
{
// not targeting player
m_tmTargetingStarted = 0;
// check switch relaying by moving brush
if( IsOfClass( pen, "Moving Brush") && ((CMovingBrush&)*pen).m_penSwitch!=NULL) {
pen = ((CMovingBrush&)*pen).m_penSwitch;
}
// if switch and near enough
if( IsOfClass( pen, "Switch") && m_fRayHitDistance<2.0f) {
CSwitch &enSwitch = (CSwitch&)*pen;
// if switch is useable
if( enSwitch.m_bUseable) {
// show switch message
if( enSwitch.m_strMessage!="") { m_strLastTarget = enSwitch.m_strMessage; }
else { m_strLastTarget = TRANS("Use"); }
m_tmLastTarget = tmNow+0.5f;
}
}
// if analyzable
if( IsOfClass( pen, "MessageHolder")
&& m_fRayHitDistance < ((CMessageHolder*)&*pen)->m_fDistance
&& ((CMessageHolder*)&*pen)->m_bActive) {
const CTFileName &fnmMessage = ((CMessageHolder*)&*pen)->m_fnmMessage;
// if player doesn't have that message it database
CPlayer &pl = (CPlayer&)*m_penPlayer;
if( !pl.HasMessage(fnmMessage)) {
// show analyse message
m_strLastTarget = TRANS("Analyze");
m_tmLastTarget = tmNow+0.5f;
}
}
}
}
// if didn't hit anything
else {
// not targeting player
m_tmTargetingStarted = 0;
// remember position ahead
FLOAT3D vDir = crRay.cr_vTarget-crRay.cr_vOrigin;
vDir.Normalize();
m_vRayHit = crRay.cr_vOrigin+vDir*50.0f;
}
// determine snooping time
TIME tmDelta = tmNow - m_tmTargetingStarted;
if( m_tmTargetingStarted>0 && plr_tmSnoopingDelay>0 && tmDelta>plr_tmSnoopingDelay) {
m_tmSnoopingStarted = tmNow;
}
}
// Render Crosshair
void RenderCrosshair( CProjection3D &prProjection, CDrawPort *pdp, CPlacement3D &plViewSource)
{
INDEX iCrossHair = GetPlayer()->GetSettings()->ps_iCrossHairType+1;
// adjust crosshair type
if( iCrossHair<=0) {
iCrossHair = 0;
_iLastCrosshairType = 0;
}
// create new crosshair texture (if needed)
if( _iLastCrosshairType != iCrossHair) {
_iLastCrosshairType = iCrossHair;
CTString fnCrosshair;
fnCrosshair.PrintF( "Textures\\Interface\\Crosshairs\\Crosshair%d.tex", iCrossHair);
try {
// load new crosshair texture
_toCrosshair.SetData_t( fnCrosshair);
} catch( char *strError) {
// didn't make it! - reset crosshair
CPrintF( strError);
iCrossHair = 0;
return;
}
}
COLOR colCrosshair = C_WHITE;
TIME tmNow = _pTimer->CurrentTick();
// if hit anything
FLOAT3D vOnScreen;
FLOAT fDistance = m_fRayHitDistance;
//const FLOAT3D vRayHit = Lerp( m_vRayHitLast, m_vRayHit, _pTimer->GetLerpFactor());
const FLOAT3D vRayHit = m_vRayHit; // lerping doesn't seem to work ???
// if hit anything
if( m_penRayHit!=NULL) {
CEntity *pen = m_penRayHit;
// do screen projection
prProjection.ViewerPlacementL() = plViewSource;
prProjection.ObjectPlacementL() = CPlacement3D( FLOAT3D(0.0f, 0.0f, 0.0f), ANGLE3D( 0, 0, 0));
prProjection.Prepare();
prProjection.ProjectCoordinate( vRayHit, vOnScreen);
// if required, show enemy health thru crosshair color
if( hud_bCrosshairColoring && m_fEnemyHealth>0) {
if( m_fEnemyHealth<0.25f) { colCrosshair = C_RED; }
else if( m_fEnemyHealth<0.60f) { colCrosshair = C_YELLOW; }
else { colCrosshair = C_GREEN; }
}
}
// if didn't hit anything
else
{
// far away in screen center
vOnScreen(1) = (FLOAT)pdp->GetWidth() *0.5f;
vOnScreen(2) = (FLOAT)pdp->GetHeight() *0.5f;
fDistance = 100.0f;
}
// if croshair should be of fixed position
if( hud_bCrosshairFixed || GetPlayer()->m_iViewState == PVT_3RDPERSONVIEW) {
// reset it to screen center
vOnScreen(1) = (FLOAT)pdp->GetWidth() *0.5f;
vOnScreen(2) = (FLOAT)pdp->GetHeight() *0.5f;
//fDistance = 100.0f;
}
// clamp console variables
hud_fCrosshairScale = Clamp( hud_fCrosshairScale, 0.1f, 2.0f);
hud_fCrosshairRatio = Clamp( hud_fCrosshairRatio, 0.1f, 1.0f);
hud_fCrosshairOpacity = Clamp( hud_fCrosshairOpacity, 0.1f, 1.0f);
const ULONG ulAlpha = NormFloatToByte( hud_fCrosshairOpacity);
// draw crosshair if needed
if( iCrossHair>0) {
// determine crosshair size
const FLOAT fMinD = 1.0f;
const FLOAT fMaxD = 100.0f;
fDistance = Clamp( fDistance, fMinD, fMaxD);
const FLOAT fRatio = (fDistance-fMinD) / (fMaxD-fMinD);
const FLOAT fMaxSize = (FLOAT)pdp->GetWidth() / 640.0f;
const FLOAT fMinSize = fMaxSize * hud_fCrosshairRatio;
const FLOAT fSize = 16 * Lerp( fMaxSize, fMinSize, fRatio) * hud_fCrosshairScale;
// draw crosshair
const FLOAT fI0 = + (PIX)vOnScreen(1) - fSize;
const FLOAT fI1 = + (PIX)vOnScreen(1) + fSize;
const FLOAT fJ0 = - (PIX)vOnScreen(2) - fSize +pdp->GetHeight();
const FLOAT fJ1 = - (PIX)vOnScreen(2) + fSize +pdp->GetHeight();
pdp->InitTexture( &_toCrosshair);
pdp->AddTexture( fI0, fJ0, fI1, fJ1, colCrosshair|ulAlpha);
pdp->FlushRenderingQueue();
}
// if there is still time
TIME tmDelta = m_tmLastTarget - tmNow;
if( tmDelta>0) {
// printout current target info
SLONG slDPWidth = pdp->GetWidth();
SLONG slDPHeight = pdp->GetHeight();
FLOAT fScaling = (FLOAT)slDPWidth/640.0f;
// set font and scale
pdp->SetFont( _pfdDisplayFont);
pdp->SetTextScaling( fScaling);
pdp->SetTextAspect( 1.0f);
// do faded printout
ULONG ulA = (ULONG) ((FLOAT)ulAlpha * Clamp( 2*tmDelta, 0.0f, 1.0f));
pdp->PutTextC( m_strLastTarget, slDPWidth*0.5f, slDPHeight*0.75f, SE_COL_BLUE_NEUTRAL|ulA);
}
// printout crosshair world coordinates if needed
if( hud_bShowCoords) {
CTString strCoords;
SLONG slDPWidth = pdp->GetWidth();
SLONG slDPHeight = pdp->GetHeight();
// set font and scale
pdp->SetFont( _pfdDisplayFont);
pdp->SetTextAspect( 1.0f);
pdp->SetTextScaling( (FLOAT)slDPWidth/640.0f);
// do printout only if coordinates are valid
const FLOAT fMax = Max( Max( vRayHit(1), vRayHit(2)), vRayHit(3));
const FLOAT fMin = Min( Min( vRayHit(1), vRayHit(2)), vRayHit(3));
if( fMax<+100000 && fMin>-100000) {
strCoords.PrintF( "%.0f,%.0f,%.0f", vRayHit(1), vRayHit(2), vRayHit(3));
pdp->PutTextC( strCoords, slDPWidth*0.5f, slDPHeight*0.10f, C_WHITE|CT_OPAQUE);
}
}
};
/************************************************************
* FIRE FLARE *
************************************************************/
// show flare
void ShowFlare(CModelObject &moWeapon, INDEX iAttachObject, INDEX iAttachFlare, FLOAT fSize) {
CModelObject *pmo = &(moWeapon.GetAttachmentModel(iAttachObject)->amo_moModelObject);
CAttachmentModelObject *pamo = pmo->GetAttachmentModel(iAttachFlare);
pamo->amo_plRelative.pl_OrientationAngle(3) = (rand()*360.0f)/RAND_MAX;
pmo = &(pamo->amo_moModelObject);
pmo->StretchModel(FLOAT3D(fSize, fSize, fSize));
};
// hide flare
void HideFlare(CModelObject &moWeapon, INDEX iAttachObject, INDEX iAttachFlare) {
CModelObject *pmo = &(moWeapon.GetAttachmentModel(iAttachObject)->amo_moModelObject);
pmo = &(pmo->GetAttachmentModel(iAttachFlare)->amo_moModelObject);
pmo->StretchModel(FLOAT3D(0, 0, 0));
};
void SetFlare(INDEX iFlare, INDEX iAction)
{
// if not a prediction head
if (!IsPredictionHead()) {
// do nothing
return;
}
// get your prediction tail
CPlayerWeapons *pen = (CPlayerWeapons*)GetPredictionTail();
if (iFlare==0) {
pen->m_iFlare = iAction;
pen->GetPlayer()->GetPlayerAnimator()->m_iFlare = iAction;
} else {
pen->m_iSecondFlare = iAction;
pen->GetPlayer()->GetPlayerAnimator()->m_iSecondFlare = iAction;
}
}
// flare attachment
void ControlFlareAttachment(void) {
// if not a prediction head
/* if (!IsPredictionHead()) {
// do nothing
return;
}
*/
// get your prediction tail
CPlayerWeapons *pen = (CPlayerWeapons *)GetPredictionTail();
// second colt only
if (m_iCurrentWeapon==WEAPON_DOUBLECOLT) {
// add flare
if (pen->m_iSecondFlare==FLARE_ADD) {
pen->m_iSecondFlare = FLARE_REMOVE;
ShowFlare(m_moWeaponSecond, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE, 1.0f);
// remove flare
} else if (pen->m_iSecondFlare==FLARE_REMOVE) {
HideFlare(m_moWeaponSecond, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE);
}
}
// add flare
if (pen->m_iFlare==FLARE_ADD) {
pen->m_iFlare = FLARE_REMOVE;
switch(m_iCurrentWeapon) {
case WEAPON_DOUBLECOLT: case WEAPON_COLT:
ShowFlare(m_moWeapon, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE, 0.75f);
break;
case WEAPON_SINGLESHOTGUN:
ShowFlare(m_moWeapon, SINGLESHOTGUN_ATTACHMENT_BARRELS, BARRELS_ATTACHMENT_FLARE, 1.0f);
break;
case WEAPON_DOUBLESHOTGUN:
ShowFlare(m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_BARRELS, DSHOTGUNBARRELS_ATTACHMENT_FLARE, 1.75f);
break;
case WEAPON_TOMMYGUN:
ShowFlare(m_moWeapon, TOMMYGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE, 0.5f);
break;
case WEAPON_SNIPER:
ShowFlare(m_moWeapon, SNIPER_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE, 0.5f);
break;
case WEAPON_MINIGUN:
ShowFlare(m_moWeapon, MINIGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE, 1.25f);
break;
}
// remove
} else if (pen->m_iFlare==FLARE_REMOVE) {
switch(m_iCurrentWeapon) {
case WEAPON_DOUBLECOLT: case WEAPON_COLT:
HideFlare(m_moWeapon, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE);
break;
case WEAPON_SINGLESHOTGUN:
HideFlare(m_moWeapon, SINGLESHOTGUN_ATTACHMENT_BARRELS, BARRELS_ATTACHMENT_FLARE);
break;
case WEAPON_DOUBLESHOTGUN:
HideFlare(m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_BARRELS, DSHOTGUNBARRELS_ATTACHMENT_FLARE);
break;
case WEAPON_TOMMYGUN:
HideFlare(m_moWeapon, TOMMYGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE);
break;
case WEAPON_SNIPER:
HideFlare(m_moWeapon, SNIPER_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE);
break;
case WEAPON_MINIGUN:
HideFlare(m_moWeapon, MINIGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE);
break;
}
} else {
ASSERT(FALSE);
}
};
// play light animation
void PlayLightAnim(INDEX iAnim, ULONG ulFlags) {
CPlayer &pl = (CPlayer&)*m_penPlayer;
if (pl.m_aoLightAnimation.GetData()!=NULL) {
pl.m_aoLightAnimation.PlayAnim(iAnim, ulFlags);
}
};
// Set weapon model for current weapon.
void SetCurrentWeaponModel(void) {
// WARNING !!! ---> Order of attachment must be the same with order in RenderWeaponModel()
switch (m_iCurrentWeapon) {
case WEAPON_NONE:
break;
// knife
case WEAPON_KNIFE:
SetComponents(this, m_moWeapon, MODEL_KNIFE, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, KNIFE_ATTACHMENT_KNIFEITEM, MODEL_KNIFEITEM,
TEXTURE_KNIFEITEM, TEX_REFL_BWRIPLES02, TEX_SPEC_WEAK, 0);
m_moWeapon.PlayAnim(KNIFE_ANIM_WAIT1, 0);
break;
// colt
case WEAPON_DOUBLECOLT: {
SetComponents(this, m_moWeaponSecond, MODEL_COLT, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeaponSecond, COLT_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeaponSecond, COLT_ATTACHMENT_COCK, MODEL_COLTCOCK, TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeaponSecond, COLT_ATTACHMENT_COLT, MODEL_COLTMAIN, TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
CModelObject &mo = m_moWeaponSecond.GetAttachmentModel(COLT_ATTACHMENT_COLT)->amo_moModelObject;
AddAttachmentToModel(this, mo, COLTMAIN_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); }
m_moWeaponSecond.StretchModel(FLOAT3D(-1,1,1));
m_moWeaponSecond.PlayAnim(COLT_ANIM_WAIT1, 0);
case WEAPON_COLT: {
SetComponents(this, m_moWeapon, MODEL_COLT, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, COLT_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, COLT_ATTACHMENT_COCK, MODEL_COLTCOCK, TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, COLT_ATTACHMENT_COLT, MODEL_COLTMAIN, TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
CModelObject &mo = m_moWeapon.GetAttachmentModel(COLT_ATTACHMENT_COLT)->amo_moModelObject;
AddAttachmentToModel(this, mo, COLTMAIN_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0);
m_moWeapon.PlayAnim(COLT_ANIM_WAIT1, 0);
break; }
case WEAPON_SINGLESHOTGUN: {
SetComponents(this, m_moWeapon, MODEL_SINGLESHOTGUN, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, SINGLESHOTGUN_ATTACHMENT_BARRELS, MODEL_SS_BARRELS, TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_WEAK, 0);
AddAttachmentToModel(this, m_moWeapon, SINGLESHOTGUN_ATTACHMENT_HANDLE, MODEL_SS_HANDLE, TEXTURE_SS_HANDLE, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, SINGLESHOTGUN_ATTACHMENT_SLIDER, MODEL_SS_SLIDER, TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0);
CModelObject &mo = m_moWeapon.GetAttachmentModel(SINGLESHOTGUN_ATTACHMENT_BARRELS)->amo_moModelObject;
AddAttachmentToModel(this, mo, BARRELS_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0);
m_moWeapon.PlayAnim(SINGLESHOTGUN_ANIM_WAIT1, 0);
break; }
case WEAPON_DOUBLESHOTGUN: {
SetComponents(this, m_moWeapon, MODEL_DOUBLESHOTGUN, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_BARRELS, MODEL_DS_BARRELS, TEXTURE_DS_BARRELS, TEX_REFL_BWRIPLES01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_HANDLE, MODEL_DS_HANDLE, TEXTURE_DS_HANDLE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_SWITCH, MODEL_DS_SWITCH, TEXTURE_DS_SWITCH, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_AMMO, MODEL_DS_AMMO, TEXTURE_DS_AMMO, 0 ,0, 0);
SetComponents(this, m_moWeaponSecond, MODEL_DS_HANDWITHAMMO, TEXTURE_HAND, 0, 0, 0);
CModelObject &mo = m_moWeapon.GetAttachmentModel(DOUBLESHOTGUN_ATTACHMENT_BARRELS)->amo_moModelObject;
AddAttachmentToModel(this, mo, DSHOTGUNBARRELS_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0);
m_moWeaponSecond.StretchModel(FLOAT3D(1,1,1));
m_moWeapon.PlayAnim(DOUBLESHOTGUN_ANIM_WAIT1, 0);
break; }
case WEAPON_TOMMYGUN: {
SetComponents(this, m_moWeapon, MODEL_TOMMYGUN, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, TOMMYGUN_ATTACHMENT_BODY, MODEL_TG_BODY, TEXTURE_TG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, TOMMYGUN_ATTACHMENT_SLIDER, MODEL_TG_SLIDER, TEXTURE_TG_BODY, 0, TEX_SPEC_MEDIUM, 0);
CModelObject &mo = m_moWeapon.GetAttachmentModel(TOMMYGUN_ATTACHMENT_BODY)->amo_moModelObject;
AddAttachmentToModel(this, mo, BODY_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0);
break; }
case WEAPON_SNIPER: {
SetComponents(this, m_moWeapon, MODEL_SNIPER, TEXTURE_SNIPER_BODY, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, SNIPER_ATTACHMENT_BODY, MODEL_SNIPER_BODY, TEXTURE_SNIPER_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
CModelObject &mo = m_moWeapon.GetAttachmentModel(SNIPER_ATTACHMENT_BODY)->amo_moModelObject;
AddAttachmentToModel(this, mo, BODY_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0);
break; }
case WEAPON_MINIGUN: {
SetComponents(this, m_moWeapon, MODEL_MINIGUN, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, MINIGUN_ATTACHMENT_BARRELS, MODEL_MG_BARRELS, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, MINIGUN_ATTACHMENT_BODY, MODEL_MG_BODY, TEXTURE_MG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, MINIGUN_ATTACHMENT_ENGINE, MODEL_MG_ENGINE, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
CModelObject &mo = m_moWeapon.GetAttachmentModel(MINIGUN_ATTACHMENT_BODY)->amo_moModelObject;
AddAttachmentToModel(this, mo, BODY_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0);
break; }
case WEAPON_ROCKETLAUNCHER:
SetComponents(this, m_moWeapon, MODEL_ROCKETLAUNCHER, TEXTURE_RL_BODY, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_BODY, MODEL_RL_BODY, TEXTURE_RL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROTATINGPART, MODEL_RL_ROTATINGPART, TEXTURE_RL_ROTATINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROCKET1, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROCKET2, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROCKET3, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
break;
case WEAPON_GRENADELAUNCHER:
SetComponents(this, m_moWeapon, MODEL_GRENADELAUNCHER, TEXTURE_GL_BODY, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, GRENADELAUNCHER_ATTACHMENT_BODY, MODEL_GL_BODY, TEXTURE_GL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, GRENADELAUNCHER_ATTACHMENT_MOVING_PART, MODEL_GL_MOVINGPART, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, GRENADELAUNCHER_ATTACHMENT_GRENADE, MODEL_GL_GRENADE, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
break;
/*
case WEAPON_PIPEBOMB:
SetComponents(this, m_moWeapon, MODEL_PIPEBOMB_HAND, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB, MODEL_PB_BOMB, TEXTURE_PB_BOMB, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
SetComponents(this, m_moWeaponSecond, MODEL_PIPEBOMB_STICK, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeaponSecond, HANDWITHSTICK_ATTACHMENT_STICK, MODEL_PB_STICK, TEXTURE_PB_STICK, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeaponSecond, HANDWITHSTICK_ATTACHMENT_SHIELD, MODEL_PB_SHIELD, TEXTURE_PB_STICK, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeaponSecond, HANDWITHSTICK_ATTACHMENT_BUTTON, MODEL_PB_BUTTON, TEXTURE_PB_STICK, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
m_moWeaponSecond.StretchModel(FLOAT3D(1,1,1));
break;
*/
case WEAPON_FLAMER:
SetComponents(this, m_moWeapon, MODEL_FLAMER, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, FLAMER_ATTACHMENT_BODY, MODEL_FL_BODY, TEXTURE_FL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, FLAMER_ATTACHMENT_FUEL, MODEL_FL_RESERVOIR, TEXTURE_FL_FUELRESERVOIR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, FLAMER_ATTACHMENT_FLAME, MODEL_FL_FLAME, TEXTURE_FL_FLAME, 0, 0, 0);
break;
case WEAPON_CHAINSAW: {
SetComponents(this, m_moWeapon, MODEL_CHAINSAW, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, CHAINSAW_ATTACHMENT_CHAINSAW, MODEL_CS_BODY, TEXTURE_CS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, CHAINSAW_ATTACHMENT_BLADE, MODEL_CS_BLADE, TEXTURE_CS_BLADE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
CModelObject *pmo;
pmo = &(m_moWeapon.GetAttachmentModel(CHAINSAW_ATTACHMENT_BLADE)->amo_moModelObject);
AddAttachmentToModel(this, *pmo, BLADE_ATTACHMENT_TEETH, MODEL_CS_TEETH, TEXTURE_CS_TEETH, 0, 0, 0);
break; }
case WEAPON_LASER:
SetComponents(this, m_moWeapon, MODEL_LASER, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_BODY, MODEL_LS_BODY, TEXTURE_LS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_LEFTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_LEFTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_RIGHTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_RIGHTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
break;
/*
case WEAPON_GHOSTBUSTER:
SetComponents(this, m_moWeapon, MODEL_GHOSTBUSTER, TEXTURE_HAND, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_BODY, MODEL_GB_BODY, TEXTURE_GB_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_ROTATOR, MODEL_GB_ROTATOR, TEXTURE_GB_ROTATOR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT01, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT02, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT03, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT04, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0);
CModelObject *pmo;
pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT01)->amo_moModelObject);
AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0);
pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT02)->amo_moModelObject);
AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0);
pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT03)->amo_moModelObject);
AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0);
pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT04)->amo_moModelObject);
AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0);
break;
*/
case WEAPON_IRONCANNON:
// case WEAPON_NUKECANNON:
SetComponents(this, m_moWeapon, MODEL_CANNON, TEXTURE_CANNON, 0, 0, 0);
AddAttachmentToModel(this, m_moWeapon, CANNON_ATTACHMENT_BODY, MODEL_CN_BODY, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
// AddAttachmentToModel(this, m_moWeapon, CANNON_ATTACHMENT_NUKEBOX, MODEL_CN_NUKEBOX, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
// AddAttachmentToModel(this, m_moWeapon, CANNON_ATTACHMENT_LIGHT, MODEL_CN_LIGHT, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
break;
}
};
/*
* >>>--- ROTATE MINIGUN ---<<<
*/
void RotateMinigun(void) {
ANGLE aAngle = Lerp(m_aMiniGunLast, m_aMiniGun, _pTimer->GetLerpFactor());
// rotate minigun barrels
CAttachmentModelObject *amo = m_moWeapon.GetAttachmentModel(MINIGUN_ATTACHMENT_BARRELS);
amo->amo_plRelative.pl_OrientationAngle(3) = aAngle;
};
/*
* >>>--- SUPPORT (COMMON) FUNCTIONS ---<<<
*/
// calc weapon position for 3rd person view
void CalcWeaponPosition3rdPersonView(FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ) {
plPos.pl_OrientationAngle = ANGLE3D(0, 0, 0);
// weapon handle
if (!m_bMirrorFire) {
plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
} else {
plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
}
// weapon offset
if (!m_bMirrorFire) {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
} else {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
}
plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
if (bResetZ) {
plPos.pl_PositionVector(3) = 0.0f;
}
// player view and absolute position
CPlacement3D plView = ((CPlayer &)*m_penPlayer).en_plViewpoint;
plView.pl_PositionVector(2)= 1.25118f;
plPos.RelativeToAbsoluteSmooth(plView);
plPos.RelativeToAbsoluteSmooth(m_penPlayer->GetPlacement());
};
// calc weapon position
void CalcWeaponPosition(FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ) {
plPos.pl_OrientationAngle = ANGLE3D(0, 0, 0);
// weapon handle
if (!m_bMirrorFire) {
plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
if (m_bSniping) {
plPos.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f );
}
} else {
plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
}
// weapon offset
if (!m_bMirrorFire) {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
} else {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
}
plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
if (bResetZ) {
plPos.pl_PositionVector(3) = 0.0f;
}
// player view and absolute position
CPlacement3D plView = ((CPlayer &)*m_penPlayer).en_plViewpoint;
plView.pl_PositionVector(2)+= ((CPlayerAnimator&)*((CPlayer &)*m_penPlayer).m_penAnimator).
m_fEyesYOffset;
plPos.RelativeToAbsoluteSmooth(plView);
plPos.RelativeToAbsoluteSmooth(m_penPlayer->GetPlacement());
};
// calc lerped weapon position
void CalcLerpedWeaponPosition(FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ)
{
plPos.pl_OrientationAngle = ANGLE3D(0, 0, 0);
// weapon handle
if (!m_bMirrorFire) {
plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
if (m_bSniping) {
plPos.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f );
}
} else {
plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
}
// weapon offset
if (!m_bMirrorFire) {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
} else {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
}
plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
if (bResetZ) {
plPos.pl_PositionVector(3) = 0.0f;
}
// player view and absolute position
CPlacement3D plRes;
GetPlayer()->GetLerpedWeaponPosition( plPos.pl_PositionVector, plRes);
plPos=plRes;
};
// calc weapon position
void CalcWeaponPositionImprecise (FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ, FLOAT fImprecissionAngle) {
plPos.pl_OrientationAngle = ANGLE3D((FRnd()-0.5f)*fImprecissionAngle, (FRnd()-0.5f)*fImprecissionAngle, 0);
// weapon handle
if (!m_bMirrorFire) {
plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
if (m_bSniping) {
plPos.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f );
}
} else {
plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon],
wpn_fZ[m_iCurrentWeapon]);
}
// weapon offset
if (!m_bMirrorFire) {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
} else {
plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0)));
}
plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2);
if (bResetZ) {
plPos.pl_PositionVector(3) = 0.0f;
}
// player view and absolute position
CPlacement3D plView = ((CPlayer &)*m_penPlayer).en_plViewpoint;
plView.pl_PositionVector(2)+= ((CPlayerAnimator&)*((CPlayer &)*m_penPlayer).m_penAnimator).
m_fEyesYOffset;
plPos.RelativeToAbsoluteSmooth(plView);
plPos.RelativeToAbsoluteSmooth(m_penPlayer->GetPlacement());
};
// setup 3D sound parameters
void Setup3DSoundParameters(void) {
CPlayer &pl = (CPlayer&)*m_penPlayer;
// initialize sound 3D parameters
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f);
pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f);
pl.m_soWeapon2.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f);
pl.m_soWeapon3.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f);
pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 0.0f, 1.0f);
};
/*
* >>>--- FIRE FUNCTIONS ---<<<
*/
// cut in front of you with knife
BOOL CutWithKnife(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fWide, FLOAT fThickness, FLOAT fDamage)
{
// knife start position
CPlacement3D plKnife;
CalcWeaponPosition(FLOAT3D(fX, fY, 0), plKnife, TRUE);
// create a set of rays to test
const FLOAT3D &vBase = plKnife.pl_PositionVector;
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plKnife.pl_OrientationAngle);
FLOAT3D vRight = m.GetColumn(1)*fWide;
FLOAT3D vUp = m.GetColumn(2)*fWide;
FLOAT3D vFront = -m.GetColumn(3)*fRange;
FLOAT3D vDest[5];
vDest[0] = vBase+vFront;
vDest[1] = vBase+vFront+vUp;
vDest[2] = vBase+vFront-vUp;
vDest[3] = vBase+vFront+vRight;
vDest[4] = vBase+vFront-vRight;
CEntity *penClosest = NULL;
FLOAT fDistance = UpperLimit(0.0f);
FLOAT3D vHit;
FLOAT3D vDir;
// for each ray
for (INDEX i=0; i<5; i++) {
// cast a ray to find if any model
CCastRay crRay( m_penPlayer, vBase, vDest[i]);
crRay.cr_bHitTranslucentPortals = FALSE;
crRay.cr_fTestR = fThickness;
crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX;
GetWorld()->CastRay(crRay);
// if hit something
if (crRay.cr_penHit!=NULL /*&& crRay.cr_penHit->GetRenderType()==RT_MODEL*/ && crRay.cr_fHitDistance<fDistance) {
penClosest = crRay.cr_penHit;
fDistance = crRay.cr_fHitDistance;
vDir = vDest[i]-vBase;
vHit = crRay.cr_vHit;
if (i==0) {
if(crRay.cr_penHit->GetRenderType()==RT_BRUSH)
{
INDEX iSurfaceType=crRay.cr_pbpoBrushPolygon->bpo_bppProperties.bpp_ubSurfaceType;
EffectParticlesType eptType=GetParticleEffectTypeForSurface(iSurfaceType);
FLOAT3D vNormal=crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute;
FLOAT3D vReflected = vDir-vNormal*(2.0f*(vNormal%vDir));
((CPlayer&)*m_penPlayer).AddBulletSpray( vBase+vFront, eptType, vReflected);
}
else if(crRay.cr_penHit->GetRenderType()==RT_MODEL)
{
BOOL bRender=TRUE;
FLOAT3D vSpillDir=-((CPlayer&)*m_penPlayer).en_vGravityDir*0.5f;
SprayParticlesType sptType=SPT_NONE;
COLOR colParticles=C_WHITE|CT_OPAQUE;
FLOAT fPower=4.0f;
if( IsOfClass(crRay.cr_penHit, "ModelHolder2"))
{
bRender=FALSE;
CModelDestruction *penDestruction = ((CModelHolder2&)*crRay.cr_penHit).GetDestruction();
if( penDestruction!=NULL)
{
bRender=TRUE;
sptType= penDestruction->m_sptType;
}
CModelHolder2 *pmh2=(CModelHolder2*)crRay.cr_penHit;
colParticles=pmh2->m_colBurning;
}
FLOATaabbox3D boxCutted=FLOATaabbox3D(FLOAT3D(0,0,0),FLOAT3D(1,1,1));
if(bRender)
{
crRay.cr_penHit->en_pmoModelObject->GetCurrentFrameBBox( boxCutted);
((CPlayer&)*m_penPlayer).AddGoreSpray( vBase+vFront, vHit, sptType,
vSpillDir, boxCutted, fPower, colParticles);
}
}
// don't search any more
break;
}
}
}
// if any model hit
if (penClosest!=NULL) {
// in deathmatches check for backstab
if (!(GetSP()->sp_bCooperative) && IsOfClass(penClosest, "Player")) {
FLOAT3D vToTarget = penClosest->GetPlacement().pl_PositionVector - m_penPlayer->GetPlacement().pl_PositionVector;
FLOAT3D vTargetHeading = FLOAT3D(0.0, 0.0, -1.0f)*penClosest->GetRotationMatrix();
vToTarget.Normalize(); vTargetHeading.Normalize();
if (vToTarget%vTargetHeading>0.64279f) //CosFast(50.0f)
{
PrintCenterMessage(this, m_penPlayer, TRANS("Backstab!"), 4.0f, MSS_NONE);
fDamage *= 4.0f;
}
}
const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penPlayer);
InflictDirectDamage(penClosest, m_penPlayer, DMT_CLOSERANGE, fDamage*fDamageMul, vHit, vDir);
return TRUE;
}
return FALSE;
};
// cut in front of you with the chainsaw
BOOL CutWithChainsaw(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fWide, FLOAT fThickness, FLOAT fDamage)
{
// knife start position
CPlacement3D plKnife;
CalcWeaponPosition(FLOAT3D(fX, fY, 0), plKnife, TRUE);
// create a set of rays to test
const FLOAT3D &vBase = plKnife.pl_PositionVector;
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plKnife.pl_OrientationAngle);
FLOAT3D vRight = m.GetColumn(1)*fWide;
//FLOAT3D vUp = m.GetColumn(2)*fWide;
FLOAT3D vFront = -m.GetColumn(3)*fRange;
FLOAT3D vDest[3];
vDest[0] = vBase+vFront;
vDest[1] = vBase+vFront+vRight;
vDest[2] = vBase+vFront-vRight;
CEntity *penClosest = NULL;
FLOAT fDistance = UpperLimit(0.0f);
FLOAT3D vHit;
FLOAT3D vDir;
// for each ray
for (INDEX i=0; i<3; i++) {
// cast a ray to find if any model
CCastRay crRay( m_penPlayer, vBase, vDest[i]);
crRay.cr_bHitTranslucentPortals = FALSE;
crRay.cr_fTestR = fThickness;
crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX;
GetWorld()->CastRay(crRay);
// if hit something
if (crRay.cr_penHit!=NULL)
{
penClosest = crRay.cr_penHit;
fDistance = crRay.cr_fHitDistance;
vDir = vDest[i]-vBase;
vDir.Normalize();
vHit = crRay.cr_vHit;
if(i==0)
{
if(crRay.cr_penHit->GetRenderType()==RT_BRUSH)
{
INDEX iSurfaceType=crRay.cr_pbpoBrushPolygon->bpo_bppProperties.bpp_ubSurfaceType;
EffectParticlesType eptType=GetParticleEffectTypeForSurface(iSurfaceType);
FLOAT3D vNormal=crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute;
FLOAT3D vReflected = vDir-vNormal*(2.0f*(vNormal%vDir));
((CPlayer&)*m_penPlayer).AddBulletSpray( vBase+vFront, eptType, vReflected);
// shake view
((CPlayer&)*m_penPlayer).m_fChainShakeStrength = 0.85f;
((CPlayer&)*m_penPlayer).m_fChainShakeFreqMod = 1.0f;
((CPlayer&)*m_penPlayer).m_tmChainShakeEnd = _pTimer->CurrentTick() + CHAINSAW_UPDATETIME*1.5f;
}
else if(crRay.cr_penHit->GetRenderType()==RT_MODEL)
{
BOOL bRender=TRUE;
FLOAT3D vSpillDir=-((CPlayer&)*m_penPlayer).en_vGravityDir*0.5f;
SprayParticlesType sptType=SPT_BLOOD;
COLOR colParticles=C_WHITE|CT_OPAQUE;
if (!IsDerivedFromClass(crRay.cr_penHit, "Enemy Base")) {
sptType=SPT_NONE;
}
FLOAT fPower=4.0f;
if( IsOfClass(crRay.cr_penHit, "Boneman")) {sptType=SPT_BONES; fPower=6.0f;}
if( IsOfClass(crRay.cr_penHit, "Gizmo") ||
IsOfClass(crRay.cr_penHit, "Beast")) {sptType=SPT_SLIME; fPower=4.0f;}
if( IsOfClass(crRay.cr_penHit, "Woman")) {sptType=SPT_FEATHER; fPower=3.0f;}
if( IsOfClass(crRay.cr_penHit, "Elemental")) {sptType=SPT_LAVA_STONES; fPower=3.0f;}
if( IsOfClass(crRay.cr_penHit, "Walker")) {sptType=SPT_ELECTRICITY_SPARKS; fPower=30.0f;}
if( IsOfClass(crRay.cr_penHit, "AirElemental")) {sptType=SPT_AIRSPOUTS; fPower=6.0f;}
if( IsOfClass(crRay.cr_penHit, "CannonRotating") ||
IsOfClass(crRay.cr_penHit, "CannonStatic")) {sptType=SPT_WOOD;}
if( IsOfClass(crRay.cr_penHit, "ModelHolder2"))
{
bRender=FALSE;
CModelDestruction *penDestruction = ((CModelHolder2&)*crRay.cr_penHit).GetDestruction();
CModelHolder2 *pmh2=(CModelHolder2*)crRay.cr_penHit;
colParticles=pmh2->m_colBurning;
if( penDestruction!=NULL)
{
bRender=TRUE;
sptType= penDestruction->m_sptType;
if(sptType==SPT_COLOREDSTONE)
{
colParticles=MulColors(colParticles,penDestruction->m_colParticles);
}
}
}
FLOATaabbox3D boxCutted=FLOATaabbox3D(FLOAT3D(0,0,0),FLOAT3D(1,1,1));
if(bRender && m_tmLastChainsawSpray+0.2f<_pTimer->CurrentTick())
{
crRay.cr_penHit->en_pmoModelObject->GetCurrentFrameBBox( boxCutted);
((CPlayer&)*m_penPlayer).AddGoreSpray( vBase+vFront, vHit, sptType,
vSpillDir, boxCutted, fPower, colParticles);
m_tmLastChainsawSpray = _pTimer->CurrentTick();
}
// shake view
((CPlayer&)*m_penPlayer).m_fChainShakeStrength = 1.1f;
((CPlayer&)*m_penPlayer).m_fChainShakeFreqMod = 1.0f;
((CPlayer&)*m_penPlayer).m_tmChainShakeEnd = _pTimer->CurrentTick() + CHAINSAW_UPDATETIME*1.5f;
}
}
if(crRay.cr_penHit->GetRenderType()==RT_MODEL && crRay.cr_fHitDistance<=fDistance)
{
// if this is primary ray
if (i==0)
{
// don't search any more
break;
}
}
} else {
// because we're firing, add just a slight shake
((CPlayer&)*m_penPlayer).m_fChainShakeStrength = 0.1f;
((CPlayer&)*m_penPlayer).m_fChainShakeFreqMod = 1.0f;
((CPlayer&)*m_penPlayer).m_tmChainShakeEnd = _pTimer->CurrentTick() + CHAINSAW_UPDATETIME*1.5f;
}
}
// if any model hit
if (penClosest!=NULL) {
InflictDirectDamage(penClosest, m_penPlayer, DMT_CHAINSAW, fDamage, vHit, vDir);
return TRUE;
}
return FALSE;
};
// prepare Bullet
void PrepareSniperBullet(FLOAT fX, FLOAT fY, FLOAT fDamage, FLOAT fImprecission) {
// bullet start position
CalcWeaponPositionImprecise(FLOAT3D(fX, fY, 0), plBullet, TRUE, fImprecission);
// create bullet
penBullet = CreateEntity(plBullet, CLASS_BULLET);
m_vBulletSource = plBullet.pl_PositionVector;
// init bullet
EBulletInit eInit;
eInit.penOwner = m_penPlayer;
eInit.fDamage = fDamage;
penBullet->Initialize(eInit);
};
// prepare Bullet
void PrepareBullet(FLOAT fX, FLOAT fY, FLOAT fDamage) {
// bullet start position
CalcWeaponPosition(FLOAT3D(fX, fY, 0), plBullet, TRUE);
// create bullet
penBullet = CreateEntity(plBullet, CLASS_BULLET);
// init bullet
EBulletInit eInit;
eInit.penOwner = m_penPlayer;
eInit.fDamage = fDamage;
penBullet->Initialize(eInit);
};
// fire one bullet
void FireSniperBullet(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage, FLOAT fImprecission) {
PrepareSniperBullet(fX, fY, fDamage, fImprecission);
((CBullet&)*penBullet).CalcTarget(fRange);
((CBullet&)*penBullet).m_fBulletSize = 0.1f;
// launch bullet
((CBullet&)*penBullet).LaunchBullet(TRUE, FALSE, TRUE);
if (((CBullet&)*penBullet).m_vHitPoint != FLOAT3D(0.0f, 0.0f, 0.0f)) {
m_vBulletTarget = ((CBullet&)*penBullet).m_vHitPoint;
} else if (TRUE) {
m_vBulletTarget = m_vBulletSource + FLOAT3D(0.0f, 0.0f, -500.0f)*((CBullet&)*penBullet).GetRotationMatrix();
}
// spawn bullet effect
/*ESpawnEffect ese;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_SNIPER_RESIDUE;
ese.vStretch = FLOAT3D(1.0f, 1.0f, 1.0f);
ese.vNormal = m_vBulletSource;
ese.vDirection = ((CBullet&)*penBullet).m_vHitPoint;
CPlacement3D pl = CPlacement3D(GetPlacement().pl_PositionVector, ANGLE3D(0.0f, 0.0f, 0.0f));
CEntityPointer penFX = CreateEntity(pl, CLASS_BASIC_EFFECT);
penFX->Initialize(ese);*/
// bullet no longer needed
((CBullet&)*penBullet).DestroyBullet();
};
// fire one bullet
void FireOneBullet(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage) {
PrepareBullet(fX, fY, fDamage);
((CBullet&)*penBullet).CalcTarget(fRange);
((CBullet&)*penBullet).m_fBulletSize = 0.1f;
// launch bullet
((CBullet&)*penBullet).LaunchBullet(TRUE, FALSE, TRUE);
((CBullet&)*penBullet).DestroyBullet();
};
// fire bullets (x offset is used for double shotgun)
void FireBullets(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage, INDEX iBullets,
FLOAT *afPositions, FLOAT fStretch, FLOAT fJitter) {
PrepareBullet(fX, fY, fDamage);
((CBullet&)*penBullet).CalcTarget(fRange);
((CBullet&)*penBullet).m_fBulletSize = GetSP()->sp_bCooperative ? 0.1f : 0.3f;
// launch slugs
INDEX iSlug;
for (iSlug=0; iSlug<iBullets; iSlug++) {
// launch bullet
((CBullet&)*penBullet).CalcJitterTargetFixed(
afPositions[iSlug*2+0]*fRange*fStretch, afPositions[iSlug*2+1]*fRange*fStretch,
fJitter*fRange*fStretch);
((CBullet&)*penBullet).LaunchBullet(iSlug<2, FALSE, TRUE);
}
((CBullet&)*penBullet).DestroyBullet();
};
// fire one bullet for machine guns (tommygun and minigun)
void FireMachineBullet(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage,
FLOAT fJitter, FLOAT fBulletSize)
{
fJitter*=fRange; // jitter relative to range
PrepareBullet(fX, fY, fDamage);
((CBullet&)*penBullet).CalcTarget(fRange);
((CBullet&)*penBullet).m_fBulletSize = fBulletSize;
((CBullet&)*penBullet).CalcJitterTarget(fJitter);
((CBullet&)*penBullet).LaunchBullet(TRUE, FALSE, TRUE);
((CBullet&)*penBullet).DestroyBullet();
}
// fire grenade
void FireGrenade(INDEX iPower) {
// grenade start position
CPlacement3D plGrenade;
CalcWeaponPosition(
FLOAT3D(wpn_fFX[WEAPON_GRENADELAUNCHER],wpn_fFY[WEAPON_GRENADELAUNCHER], 0),
plGrenade, TRUE);
// create grenade
CEntityPointer penGrenade = CreateEntity(plGrenade, CLASS_PROJECTILE);
// init and launch grenade
ELaunchProjectile eLaunch;
eLaunch.penLauncher = m_penPlayer;
eLaunch.prtType = PRT_GRENADE;
eLaunch.fSpeed = 20.0f+iPower*5.0f;
penGrenade->Initialize(eLaunch);
};
// fire rocket
void FireRocket(void) {
// rocket start position
CPlacement3D plRocket;
CalcWeaponPosition(
FLOAT3D(wpn_fFX[WEAPON_ROCKETLAUNCHER],wpn_fFY[WEAPON_ROCKETLAUNCHER], 0),
plRocket, TRUE);
// create rocket
CEntityPointer penRocket= CreateEntity(plRocket, CLASS_PROJECTILE);
// init and launch rocket
ELaunchProjectile eLaunch;
eLaunch.penLauncher = m_penPlayer;
eLaunch.prtType = PRT_ROCKET;
penRocket->Initialize(eLaunch);
};
/*
// drop pipebomb
void DropPipebomb(void) {
// pipebomb start position
CPlacement3D plPipebomb;
CalcWeaponPosition(
FLOAT3D(wpn_fFX[WEAPON_PIPEBOMB],wpn_fFY[WEAPON_PIPEBOMB], 0),
plPipebomb, TRUE);
// create pipebomb
CEntityPointer penPipebomb = CreateEntity(plPipebomb, CLASS_PIPEBOMB);
// init and drop pipebomb
EDropPipebomb eDrop;
eDrop.penLauncher = m_penPlayer;
if (((CPlayer&)*m_penPlayer).en_plViewpoint.pl_OrientationAngle(2) > 10.0f) {
eDrop.fSpeed = 30.0f;
} else if (((CPlayer&)*m_penPlayer).en_plViewpoint.pl_OrientationAngle(2) > -20.0f) {
eDrop.fSpeed = 20.0f;
} else {
eDrop.fSpeed = 5.0f;
}
penPipebomb->Initialize(eDrop);
m_penPipebomb = penPipebomb;
};*/
// flamer source
void GetFlamerSourcePlacement(CPlacement3D &plSource, CPlacement3D &plInFrontOfPipe) {
CalcLerpedWeaponPosition(
FLOAT3D(wpn_fFX[WEAPON_FLAMER],wpn_fFY[WEAPON_FLAMER], -0.15f),
plSource, FALSE);
plInFrontOfPipe=plSource;
FLOAT3D vFront;
AnglesToDirectionVector( plSource.pl_OrientationAngle, vFront);
plInFrontOfPipe.pl_PositionVector=plSource.pl_PositionVector+vFront*1.0f;
};
// fire flame
void FireFlame(void) {
// flame start position
CPlacement3D plFlame;
CalcWeaponPosition(FLOAT3D(wpn_fFX[WEAPON_FLAMER],wpn_fFY[WEAPON_FLAMER], -0.15f), plFlame, TRUE);
// create flame
CEntityPointer penFlame = CreateEntity(plFlame, CLASS_PROJECTILE);
// init and launch flame
ELaunchProjectile eLaunch;
eLaunch.penLauncher = m_penPlayer;
eLaunch.prtType = PRT_FLAME;
penFlame->Initialize(eLaunch);
// link last flame with this one (if not NULL or deleted)
if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
((CProjectile&)*m_penFlame).m_penParticles = penFlame;
}
// link to player weapons
((CProjectile&)*penFlame).m_penParticles = this;
// store last flame
m_penFlame = penFlame;
};
// fire laser ray
void FireLaserRay(void) {
// laser start position
CPlacement3D plLaserRay;
FLOAT fFX = wpn_fFX[WEAPON_LASER]; // get laser center position
FLOAT fFY = wpn_fFY[WEAPON_LASER];
FLOAT fLUX = 0.0f;
FLOAT fRUX = 0.8f;
FLOAT fLUY = 0.0f;
FLOAT fRUY = 0.0f;
FLOAT fLDX = -0.1f;
FLOAT fRDX = 0.9f;
FLOAT fLDY = -0.3f;
FLOAT fRDY = -0.3f;
if (((CPlayer *)&*m_penPlayer)->m_pstState==PST_CROUCH) {
fLDY = -0.1f;
fRDY = -0.1f;
}
switch(m_iLaserBarrel) {
case 0: // barrel lu (*o-oo)
CalcWeaponPosition(FLOAT3D(fFX+fLUX, fFY+fLUY, 0), plLaserRay, TRUE);
break;
case 1: // barrel ld (oo-*o)
CalcWeaponPosition(FLOAT3D(fFX+fLDX, fFY+fLDY, 0), plLaserRay, TRUE);
break;
case 2: // barrel ru (o*-oo)
CalcWeaponPosition(FLOAT3D(fFX+fRUX, fFY+fRUY, 0), plLaserRay, TRUE);
break;
case 3: // barrel rd (oo-o*)
CalcWeaponPosition(FLOAT3D(fFX+fRDX, fFY+fRDY, 0), plLaserRay, TRUE);
break;
}
// create laser projectile
CEntityPointer penLaser = CreateEntity(plLaserRay, CLASS_PROJECTILE);
// init and launch laser projectile
ELaunchProjectile eLaunch;
eLaunch.penLauncher = m_penPlayer;
eLaunch.prtType = PRT_LASER_RAY;
penLaser->Initialize(eLaunch);
};
/*
// ghostbuster source
void GetGhostBusterSourcePlacement(CPlacement3D &plSource) {
CalcWeaponPosition(
FLOAT3D(wpn_fFX[WEAPON_GHOSTBUSTER],wpn_fFY[WEAPON_GHOSTBUSTER], 0),
plSource, TRUE);
};
// fire ghost buster ray
void FireGhostBusterRay(void) {
// ray start position
CPlacement3D plRay;
GetGhostBusterSourcePlacement(plRay);
// fire ray
((CGhostBusterRay&)*m_penGhostBusterRay).Fire(plRay);
};
*/
// fire cannon ball
void FireCannonBall(INDEX iPower)
{
// cannon ball start position
CPlacement3D plBall;
CalcWeaponPosition(
FLOAT3D(wpn_fFX[WEAPON_IRONCANNON],wpn_fFY[WEAPON_IRONCANNON], 0),
plBall, TRUE);
// create cannon ball
CEntityPointer penBall = CreateEntity(plBall, CLASS_CANNONBALL);
// init and launch cannon ball
ELaunchCannonBall eLaunch;
eLaunch.penLauncher = m_penPlayer;
eLaunch.fLaunchPower = 60.0f+iPower*4.0f; // ranges from 60-140 (since iPower can be max 20)
eLaunch.fSize = 3.0f;
/*if( m_iCurrentWeapon == WEAPON_NUKECANNON)
{
eLaunch.cbtType = CBT_NUKE;
}
else
{
*/
eLaunch.cbtType = CBT_IRON;
// }
penBall->Initialize(eLaunch);
};
// weapon sound when firing
void SpawnRangeSound( FLOAT fRange)
{
if( _pTimer->CurrentTick()>m_tmRangeSoundSpawned+0.5f) {
m_tmRangeSoundSpawned = _pTimer->CurrentTick();
::SpawnRangeSound( m_penPlayer, m_penPlayer, SNDT_PLAYER, fRange);
}
};
/*
* >>>--- WEAPON INTERFACE FUNCTIONS ---<<<
*/
// clear weapons
void ClearWeapons(void) {
// give/take weapons
m_iAvailableWeapons = 0x03;
m_iColtBullets = 6;
m_iBullets = 0;
m_iShells = 0;
m_iRockets = 0;
m_iGrenades = 0;
m_iNapalm = 0;
m_iElectricity = 0;
m_iIronBalls = 0;
// m_iNukeBalls = 0;
m_iSniperBullets = 0;
};
void ResetWeaponMovingOffset(void)
{
// reset weapon draw offset
m_fWeaponDrawPowerOld = m_fWeaponDrawPower = m_tmDrawStartTime = 0;
}
// initialize weapons
void InitializeWeapons(INDEX iGiveWeapons, INDEX iTakeWeapons, INDEX iTakeAmmo, FLOAT fMaxAmmoRatio)
{
ResetWeaponMovingOffset();
// remember old weapons
ULONG ulOldWeapons = m_iAvailableWeapons;
// give/take weapons
m_iAvailableWeapons &= ~iTakeWeapons;
m_iAvailableWeapons |= 0x03|iGiveWeapons;
m_iAvailableWeapons &= WEAPONS_ALLAVAILABLEMASK;
// m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK;
// find which weapons are new
ULONG ulNewWeapons = m_iAvailableWeapons&~ulOldWeapons;
// for each new weapon
for(INDEX iWeapon=WEAPON_KNIFE; iWeapon<WEAPON_LAST; iWeapon++) {
if ( ulNewWeapons & (1<<(iWeapon-1)) ) {
// add default amount of ammo
AddDefaultAmmoForWeapon(iWeapon, fMaxAmmoRatio);
}
}
// default ammo pack size
FLOAT fModifier = ClampDn(GetSP()->sp_fAmmoQuantity, 1.0f);
m_iMaxBullets = ClampUp((INDEX) ceil(MAX_BULLETS*fModifier), INDEX(999));
m_iMaxShells = ClampUp((INDEX) ceil(MAX_SHELLS*fModifier), INDEX(999));
m_iMaxRockets = ClampUp((INDEX) ceil(MAX_ROCKETS*fModifier), INDEX(999));
m_iMaxGrenades = ClampUp((INDEX) ceil(MAX_GRENADES*fModifier), INDEX(999));
m_iMaxNapalm = ClampUp((INDEX) ceil(MAX_NAPALM*fModifier), INDEX(999));
m_iMaxElectricity = ClampUp((INDEX) ceil(MAX_ELECTRICITY*fModifier), INDEX(999));
// m_iMaxNukeBalls = ClampUp((INDEX) ceil(MAX_NUKEBALLS*fModifier), INDEX(999));
m_iMaxIronBalls = ClampUp((INDEX) ceil(MAX_IRONBALLS*fModifier), INDEX(999));
m_iMaxSniperBullets = ClampUp((INDEX) ceil(MAX_SNIPERBULLETS*fModifier), INDEX(999));
// take away ammo
if( iTakeAmmo & (1<<AMMO_BULLETS)) {m_iBullets = 0;}
if( iTakeAmmo & (1<<AMMO_SHELLS)) {m_iShells = 0;}
if( iTakeAmmo & (1<<AMMO_ROCKETS)) {m_iRockets = 0;}
if( iTakeAmmo & (1<<AMMO_GRENADES)) {m_iGrenades = 0;}
if( iTakeAmmo & (1<<AMMO_NAPALM)) {m_iNapalm = 0;}
if( iTakeAmmo & (1<<AMMO_ELECTRICITY)) {m_iElectricity= 0;}
// if( iTakeAmmo & (1<<AMMO_NUKEBALLS)) {m_iNukeBalls = 0;}
if( iTakeAmmo & (1<<AMMO_IRONBALLS)) {m_iIronBalls = 0;}
if( iTakeAmmo & (1<<AMMO_SNIPERBULLETS)) {m_iSniperBullets = 0;}
// precache eventual new weapons
Precache();
// clear temp variables for some weapons
m_aMiniGun = 0;
m_aMiniGunLast = 0;
m_aMiniGunSpeed = 0;
// select best weapon
SelectNewWeapon();
m_iCurrentWeapon=m_iWantedWeapon;
wpn_iCurrent = m_iCurrentWeapon;
m_bChangeWeapon = FALSE;
// set weapon model for current weapon
SetCurrentWeaponModel();
PlayDefaultAnim();
// remove weapon attachment
((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).RemoveWeapon();
// add weapon attachment
((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).SetWeapon();
};
// get weapon ammo
INDEX GetAmmo(void)
{
switch (m_iCurrentWeapon) {
case WEAPON_KNIFE: return 0;
case WEAPON_COLT: return m_iColtBullets;
case WEAPON_DOUBLECOLT: return m_iColtBullets;
case WEAPON_SINGLESHOTGUN: return m_iShells;
case WEAPON_DOUBLESHOTGUN: return m_iShells;
case WEAPON_TOMMYGUN: return m_iBullets;
case WEAPON_MINIGUN: return m_iBullets;
case WEAPON_ROCKETLAUNCHER: return m_iRockets;
case WEAPON_GRENADELAUNCHER: return m_iGrenades;
case WEAPON_SNIPER: return m_iSniperBullets;
case WEAPON_FLAMER: return m_iNapalm;
case WEAPON_CHAINSAW: return 0;
case WEAPON_LASER: return m_iElectricity;
case WEAPON_IRONCANNON: return m_iIronBalls;
}
return 0;
};
// get weapon max ammo (capacity)
INDEX GetMaxAmmo(void)
{
switch (m_iCurrentWeapon) {
case WEAPON_KNIFE: return 0;
case WEAPON_COLT: return 6;
case WEAPON_DOUBLECOLT: return 6;
case WEAPON_SINGLESHOTGUN: return m_iMaxShells;
case WEAPON_DOUBLESHOTGUN: return m_iMaxShells;
case WEAPON_TOMMYGUN: return m_iMaxBullets;
case WEAPON_MINIGUN: return m_iMaxBullets;
case WEAPON_ROCKETLAUNCHER: return m_iMaxRockets;
case WEAPON_GRENADELAUNCHER: return m_iMaxGrenades;
case WEAPON_SNIPER: return m_iMaxSniperBullets;
case WEAPON_FLAMER: return m_iMaxNapalm;
case WEAPON_CHAINSAW: return m_iMaxNapalm;
case WEAPON_LASER: return m_iMaxElectricity;
case WEAPON_IRONCANNON: return m_iMaxIronBalls;
}
return 0;
};
void CheatOpen(void)
{
if (IsOfClass(m_penRayHit, "Moving Brush")) {
m_penRayHit->SendEvent(ETrigger());
}
}
// cheat give all
void CheatGiveAll(void) {
// all weapons
m_iAvailableWeapons = WEAPONS_ALLAVAILABLEMASK;
// m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK;
// ammo for all weapons
m_iBullets = m_iMaxBullets;
m_iShells = m_iMaxShells;
m_iRockets = m_iMaxRockets;
m_iGrenades = m_iMaxGrenades;
m_iNapalm = m_iMaxNapalm;
m_iElectricity = m_iMaxElectricity;
m_iIronBalls = m_iMaxIronBalls;
//m_iNukeBalls = m_iMaxNukeBalls;
// precache eventual new weapons
m_iSniperBullets = m_iMaxSniperBullets;
Precache();
};
// add a given amount of mana to the player
void AddManaToPlayer(INDEX iMana)
{
((CPlayer&)*m_penPlayer).m_iMana += iMana;
((CPlayer&)*m_penPlayer).m_fPickedMana += iMana;
}
/*
* >>>--- RECEIVE FUNCTIONS ---<<<
*/
// clamp ammounts of all ammunition to maximum values
void ClampAllAmmo(void)
{
m_iBullets = ClampUp(m_iBullets, m_iMaxBullets);
m_iShells = ClampUp(m_iShells, m_iMaxShells);
m_iRockets = ClampUp(m_iRockets, m_iMaxRockets);
m_iGrenades = ClampUp(m_iGrenades, m_iMaxGrenades);
m_iNapalm = ClampUp(m_iNapalm, m_iMaxNapalm);
m_iElectricity = ClampUp(m_iElectricity, m_iMaxElectricity);
m_iIronBalls = ClampUp(m_iIronBalls, m_iMaxIronBalls);
// m_iNukeBalls = ClampUp(m_iNukeBalls, m_iMaxNukeBalls);
m_iSniperBullets = ClampUp(m_iSniperBullets, m_iMaxSniperBullets);
}
// add default ammount of ammunition when receiving a weapon
void AddDefaultAmmoForWeapon(INDEX iWeapon, FLOAT fMaxAmmoRatio)
{
INDEX iAmmoPicked;
// add ammo
switch (iWeapon) {
// unlimited ammo
case WEAPON_KNIFE:
case WEAPON_COLT:
case WEAPON_DOUBLECOLT:
break;
// shells
case WEAPON_SINGLESHOTGUN:
iAmmoPicked = (INDEX) Max(10.0f, m_iMaxShells*fMaxAmmoRatio);
m_iShells += iAmmoPicked;
AddManaToPlayer(iAmmoPicked*70.0f*MANA_AMMO);
break;
case WEAPON_DOUBLESHOTGUN:
iAmmoPicked = (INDEX) Max(20.0f, m_iMaxShells*fMaxAmmoRatio);
m_iShells += iAmmoPicked;
AddManaToPlayer(iAmmoPicked*70.0f*MANA_AMMO);
break;
// bullets
case WEAPON_TOMMYGUN:
iAmmoPicked = (INDEX) Max(50.0f, m_iMaxBullets*fMaxAmmoRatio);
m_iBullets += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*10.0f*MANA_AMMO);
break;
case WEAPON_SNIPER:
iAmmoPicked = (INDEX) Max(15.0f, m_iMaxSniperBullets*fMaxAmmoRatio);
m_iSniperBullets += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*10.0f*MANA_AMMO);
break;
case WEAPON_MINIGUN:
iAmmoPicked = (INDEX) Max(100.0f, m_iMaxBullets*fMaxAmmoRatio);
m_iBullets += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*10.0f*MANA_AMMO);
break;
// rockets
case WEAPON_ROCKETLAUNCHER:
iAmmoPicked = (INDEX) Max(5.0f, m_iMaxRockets*fMaxAmmoRatio);
m_iRockets += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*150.0f*MANA_AMMO);
break;
// grenades
case WEAPON_GRENADELAUNCHER:
iAmmoPicked = (INDEX) Max(5.0f, m_iMaxGrenades*fMaxAmmoRatio);
m_iGrenades += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*100.0f*MANA_AMMO);
break;
/*
case WEAPON_PIPEBOMB:
iAmmoPicked = (INDEX) Max(5.0f, m_iMaxGrenades*fMaxAmmoRatio);
m_iGrenades += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*100.0f*MANA_AMMO);
break;
case WEAPON_GHOSTBUSTER:
iAmmoPicked = (INDEX) Max(100.0f, m_iMaxElectricity*fMaxAmmoRatio);
m_iElectricity += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO);
break;
*/
// electricity
case WEAPON_LASER:
iAmmoPicked = (INDEX) Max(50.0f, m_iMaxElectricity*fMaxAmmoRatio);
m_iElectricity += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO);
break;
// cannon balls
case WEAPON_IRONCANNON:
// for iron ball
iAmmoPicked = (INDEX) Max(1.0f, m_iMaxIronBalls*fMaxAmmoRatio);
m_iIronBalls += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*700.0f*MANA_AMMO);
break;
/* // for nuke ball
case WEAPON_NUKECANNON:
iAmmoPicked = (INDEX) Max(1.0f, m_iMaxNukeBalls*fMaxAmmoRatio);
m_iNukeBalls += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*1000.0f*MANA_AMMO);
break;*/
// flamer // !!!! how much mana exactly?
case WEAPON_FLAMER:
iAmmoPicked = (INDEX) Max(50.0f, m_iMaxNapalm*fMaxAmmoRatio);
m_iNapalm += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO);
break;
case WEAPON_CHAINSAW:
/*iAmmoPicked = (INDEX) Max(50.0f, m_iMaxNapalm*fMaxAmmoRatio);
m_iNapalm += iAmmoPicked;
AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO);*/
break;
// error
default:
ASSERTALWAYS("Unknown weapon type");
break;
}
// make sure we don't have more ammo than maximum
ClampAllAmmo();
}
// drop current weapon (in deathmatch)
void DropWeapon(void)
{
CEntityPointer penWeapon = CreateEntity(GetPlayer()->GetPlacement(), CLASS_WEAPONITEM);
CWeaponItem *pwi = (CWeaponItem*)&*penWeapon;
WeaponItemType wit = WIT_COLT;
switch (m_iCurrentWeapon) {
default:
ASSERT(FALSE);
case WEAPON_KNIFE:
case WEAPON_COLT:
case WEAPON_DOUBLECOLT:
NOTHING; break;
case WEAPON_SINGLESHOTGUN: wit = WIT_SINGLESHOTGUN; break;
case WEAPON_DOUBLESHOTGUN: wit = WIT_DOUBLESHOTGUN; break;
case WEAPON_TOMMYGUN: wit = WIT_TOMMYGUN; break;
case WEAPON_SNIPER: wit = WIT_SNIPER; break;
case WEAPON_MINIGUN: wit = WIT_MINIGUN; break;
case WEAPON_ROCKETLAUNCHER: wit = WIT_ROCKETLAUNCHER; break;
case WEAPON_GRENADELAUNCHER: wit = WIT_GRENADELAUNCHER; break;
case WEAPON_FLAMER: wit = WIT_FLAMER; break;
case WEAPON_CHAINSAW: wit = WIT_CHAINSAW; break;
case WEAPON_LASER : wit = WIT_LASER; break;
case WEAPON_IRONCANNON : wit = WIT_CANNON; break;
}
pwi->m_EwitType = wit;
pwi->m_bDropped = TRUE;
pwi->CEntity::Initialize();
const FLOATmatrix3D &m = GetPlayer()->GetRotationMatrix();
FLOAT3D vSpeed = FLOAT3D( 5.0f, 10.0f, -7.5f);
pwi->GiveImpulseTranslationAbsolute(vSpeed*m);
}
// receive weapon
BOOL ReceiveWeapon(const CEntityEvent &ee) {
ASSERT(ee.ee_slEvent == EVENTCODE_EWeaponItem);
EWeaponItem &Ewi = (EWeaponItem&)ee;
INDEX wit = Ewi.iWeapon;
switch (Ewi.iWeapon) {
case WIT_COLT: Ewi.iWeapon = WEAPON_COLT; break;
case WIT_SINGLESHOTGUN: Ewi.iWeapon = WEAPON_SINGLESHOTGUN; break;
case WIT_DOUBLESHOTGUN: Ewi.iWeapon = WEAPON_DOUBLESHOTGUN; break;
case WIT_TOMMYGUN: Ewi.iWeapon = WEAPON_TOMMYGUN; break;
case WIT_SNIPER: Ewi.iWeapon = WEAPON_SNIPER; break;
case WIT_MINIGUN: Ewi.iWeapon = WEAPON_MINIGUN; break;
case WIT_ROCKETLAUNCHER: Ewi.iWeapon = WEAPON_ROCKETLAUNCHER; break;
case WIT_GRENADELAUNCHER: Ewi.iWeapon = WEAPON_GRENADELAUNCHER; break;
case WIT_FLAMER: Ewi.iWeapon = WEAPON_FLAMER; break;
case WIT_CHAINSAW: Ewi.iWeapon = WEAPON_CHAINSAW; break;
case WIT_LASER: Ewi.iWeapon = WEAPON_LASER; break;
case WIT_CANNON: Ewi.iWeapon = WEAPON_IRONCANNON; break;
default:
ASSERTALWAYS("Uknown weapon type");
}
// add weapon
if (Ewi.iWeapon==WEAPON_COLT && (m_iAvailableWeapons&(1<<(WEAPON_COLT-1)))) {
Ewi.iWeapon = WEAPON_DOUBLECOLT;
}
ULONG ulOldWeapons = m_iAvailableWeapons;
m_iAvailableWeapons |= 1<<(Ewi.iWeapon-1);
// m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK;
/*
if( Ewi.iWeapon == WEAPON_IRONCANNON)
{
m_iAvailableWeapons |= 1<<(WEAPON_NUKECANNON-1);
m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK;
}
*/
// precache eventual new weapons
Precache();
CTFileName fnmMsg;
switch (wit) {
case WIT_COLT:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Shofield .45 w/ TMAR"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\colt.txt");
break;
case WIT_SINGLESHOTGUN:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("12 Gauge Pump Action Shotgun"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\singleshotgun.txt");
break;
case WIT_DOUBLESHOTGUN:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Double Barrel Coach Gun"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\doubleshotgun.txt");
break;
case WIT_TOMMYGUN:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("M1-A2 Tommygun"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\tommygun.txt");
break;
case WIT_SNIPER:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("RAPTOR 16mm Sniper"), 0);
fnmMsg = CTFILENAME("DataMP\\Messages\\Weapons\\sniper.txt");
break;
case WIT_MINIGUN:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XM214-A Minigun"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\minigun.txt");
break;
case WIT_ROCKETLAUNCHER:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XPML21 Rocket Launcher"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\rocketlauncher.txt");
break;
case WIT_GRENADELAUNCHER:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("MKIII Grenade Launcher"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\grenadelauncher.txt");
break;
// case WIT_PIPEBOMB:
// fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\pipebomb.txt");
// break;
case WIT_FLAMER:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XOP Flamethrower"), 0);
fnmMsg = CTFILENAME("DataMP\\Messages\\Weapons\\flamer.txt");
break;
case WIT_CHAINSAW:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("'Bonecracker' P-LAH Chainsaw"), 0);
fnmMsg = CTFILENAME("DataMP\\Messages\\Weapons\\chainsaw.txt");
break;
case WIT_LASER:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XL2 Lasergun"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\laser.txt");
break;
// case WIT_GHOSTBUSTER:
// fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\ghostbuster.txt");
// break;
case WIT_CANNON:
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("SBC Cannon"), 0);
fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\cannon.txt");
break;
default:
ASSERTALWAYS("Uknown weapon type");
}
// send computer message
if (GetSP()->sp_bCooperative) {
EComputerMessage eMsg;
eMsg.fnmMessage = fnmMsg;
m_penPlayer->SendEvent(eMsg);
}
// must be -1 for default (still have to implement dropping weapons in deathmatch !!!!)
ASSERT(Ewi.iAmmo==-1);
// add the ammunition
AddDefaultAmmoForWeapon(Ewi.iWeapon, 0);
// if this weapon should be auto selected
BOOL bAutoSelect = FALSE;
INDEX iSelectionSetting = GetPlayer()->GetSettings()->ps_iWeaponAutoSelect;
if (iSelectionSetting==PS_WAS_ALL) {
bAutoSelect = TRUE;
} else if (iSelectionSetting==PS_WAS_ONLYNEW) {
if (m_iAvailableWeapons&~ulOldWeapons) {
bAutoSelect = TRUE;
}
} else if (iSelectionSetting==PS_WAS_BETTER) {
if (FindRemapedPos(m_iCurrentWeapon)<FindRemapedPos((WeaponType)Ewi.iWeapon)) {
bAutoSelect = TRUE;
}
}
if (bAutoSelect) {
// select it
if (WeaponSelectOk((WeaponType)Ewi.iWeapon)) {
SendEvent(EBegin());
}
}
return TRUE;
};
// receive ammo
BOOL ReceiveAmmo(const CEntityEvent &ee) {
ASSERT(ee.ee_slEvent == EVENTCODE_EAmmoItem);
// if infinite ammo is on
if (GetSP()->sp_bInfiniteAmmo) {
// pick all items anyway (items that exist in this mode are only those that
// trigger something when picked - so they must be picked)
return TRUE;
}
EAmmoItem &Eai = (EAmmoItem&)ee;
// add ammo
switch (Eai.EaitType) {
// shells
case AIT_SHELLS:
if (m_iShells>=m_iMaxShells) { m_iShells = m_iMaxShells; return FALSE; }
m_iShells += Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Shells"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_SHELLS*MANA_AMMO);
break;
// bullets
case AIT_BULLETS:
if (m_iBullets>=m_iMaxBullets) { m_iBullets = m_iMaxBullets; return FALSE; }
m_iBullets += Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Bullets"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_BULLETS *MANA_AMMO);
break;
// rockets
case AIT_ROCKETS:
if (m_iRockets>=m_iMaxRockets) { m_iRockets = m_iMaxRockets; return FALSE; }
m_iRockets += Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Rockets"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_ROCKETS *MANA_AMMO);
break;
// grenades
case AIT_GRENADES:
if (m_iGrenades>=m_iMaxGrenades) { m_iGrenades = m_iMaxGrenades; return FALSE; }
m_iGrenades += Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Grenades"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_GRENADES *MANA_AMMO);
break;
// electicity
case AIT_ELECTRICITY:
if (m_iElectricity>=m_iMaxElectricity) { m_iElectricity = m_iMaxElectricity; return FALSE; }
m_iElectricity += Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Cells"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_ELECTRICITY *MANA_AMMO);
break;
/* // cannon balls
case AIT_NUKEBALL:
if (m_iNukeBalls>=m_iMaxNukeBalls) { m_iNukeBalls = m_iMaxNukeBalls; return FALSE; }
m_iNukeBalls+= Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Nuke ball"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_NUKEBALLS *MANA_AMMO);
break;*/
case AIT_IRONBALLS:
if (m_iIronBalls>=m_iMaxIronBalls) { m_iIronBalls = m_iMaxIronBalls; return FALSE; }
m_iIronBalls+= Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Cannonballs"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_IRONBALLS *MANA_AMMO);
break;
case AIT_NAPALM:
if (m_iNapalm>=m_iMaxNapalm) { m_iNapalm = m_iMaxNapalm; return FALSE; }
m_iNapalm+= Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Napalm"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_NAPALM*MANA_AMMO);
break;
case AIT_BACKPACK:
m_iShells += (INDEX) (20*GetSP()->sp_fAmmoQuantity);
m_iBullets += (INDEX) (200*GetSP()->sp_fAmmoQuantity);
m_iRockets += (INDEX) (5*GetSP()->sp_fAmmoQuantity);
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Ammo pack"), 0);
AddManaToPlayer(100000000.0f *MANA_AMMO); // adjust mana value!!!!
break;
case AIT_SERIOUSPACK:
m_iShells += (INDEX) (MAX_SHELLS*GetSP()->sp_fAmmoQuantity);
m_iBullets += (INDEX) (MAX_BULLETS*GetSP()->sp_fAmmoQuantity);
m_iGrenades += (INDEX) (MAX_GRENADES*GetSP()->sp_fAmmoQuantity);
m_iRockets += (INDEX) (MAX_ROCKETS*GetSP()->sp_fAmmoQuantity);
m_iElectricity += (INDEX) (MAX_ELECTRICITY*GetSP()->sp_fAmmoQuantity);
m_iIronBalls += (INDEX) (MAX_IRONBALLS*GetSP()->sp_fAmmoQuantity);
// m_iNukeBalls += (INDEX) (MAX_NUKEBALLS*GetSP()->sp_fAmmoQuantity);
case AIT_SNIPERBULLETS:
if (m_iSniperBullets>=m_iMaxSniperBullets) { m_iSniperBullets = m_iMaxSniperBullets; return FALSE; }
m_iSniperBullets+= Eai.iQuantity;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Sniper bullets"), Eai.iQuantity);
AddManaToPlayer(Eai.iQuantity*AV_SNIPERBULLETS*MANA_AMMO);
break;
((CPlayer&)*m_penPlayer).ItemPicked(TRANS("All Ammo"), 0);
AddManaToPlayer(100000000.0f *MANA_AMMO); // adjust mana value!!!!
break;
// error
default:
ASSERTALWAYS("Uknown ammo type");
}
// make sure we don't have more ammo than maximum
ClampAllAmmo();
return TRUE;
};
// receive ammo
BOOL ReceivePackAmmo(const CEntityEvent &ee)
{
// if infinite ammo is on
if (GetSP()->sp_bInfiniteAmmo) {
// pick all items anyway (items that exist in this mode are only those that
// trigger something when picked - so they must be picked)
return TRUE;
}
ASSERT(ee.ee_slEvent == EVENTCODE_EAmmoPackItem);
EAmmoPackItem &eapi = (EAmmoPackItem &)ee;
if( (eapi.iShells>0 && m_iShells<m_iMaxShells) ||
(eapi.iBullets>0 && m_iBullets<m_iMaxBullets) ||
(eapi.iRockets>0 && m_iRockets<m_iMaxRockets) ||
(eapi.iGrenades>0 && m_iGrenades<m_iMaxGrenades) ||
(eapi.iNapalm>0 && m_iNapalm<m_iMaxNapalm) ||
(eapi.iElectricity>0 && m_iElectricity<m_iMaxElectricity) ||
(eapi.iIronBalls>0 && m_iIronBalls<m_iMaxIronBalls) ||
(eapi.iSniperBullets>0 && m_iSniperBullets<m_iMaxSniperBullets))
{
// add ammo from back pack
m_iShells+=eapi.iShells;
m_iBullets+=eapi.iBullets;
m_iRockets+=eapi.iRockets;
m_iGrenades+=eapi.iGrenades;
m_iNapalm+=eapi.iNapalm;
m_iElectricity+=eapi.iElectricity;
m_iIronBalls+=eapi.iIronBalls;
m_iSniperBullets+=eapi.iSniperBullets;
// make sure we don't have more ammo than maximum
ClampAllAmmo();
// preapare message string and count different types of ammo
INDEX iAmmoTypes = 0;
CTString strMessage;
if( eapi.iShells != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iShells, TRANS("Shells")); iAmmoTypes++; }
if( eapi.iBullets != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iBullets, TRANS("Bullets")); iAmmoTypes++; }
if( eapi.iRockets != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iRockets, TRANS("Rockets")); iAmmoTypes++; }
if( eapi.iGrenades != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iGrenades, TRANS("Grenades")); iAmmoTypes++; }
if( eapi.iNapalm != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iNapalm, TRANS("Napalm")); iAmmoTypes++; }
if( eapi.iElectricity != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iElectricity, TRANS("Cells")); iAmmoTypes++; }
if( eapi.iIronBalls != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iIronBalls, TRANS("Cannonballs")); iAmmoTypes++; }
if( eapi.iSniperBullets != 0) { strMessage.PrintF("%s %d %s,", (const char *) strMessage, eapi.iSniperBullets, TRANS("Sniper bullets")); iAmmoTypes++; }
INDEX iLen = strlen(strMessage);
if( iLen>0 && strMessage[iLen-1]==',')
{
strMessage.DeleteChar(iLen-1);
};
if( iAmmoTypes>4 ) {
strMessage.PrintF(TRANSV("Ammo pack"));
};
((CPlayer&)*m_penPlayer).ItemPicked(strMessage, 0);
return TRUE;
}
return FALSE;
}
/*
* >>>--- WEAPON CHANGE FUNCTIONS ---<<<
*/
// get weapon from selected number
WeaponType GetStrongerWeapon(INDEX iWeapon) {
switch(iWeapon) {
case 1: return WEAPON_CHAINSAW;
case 2: return WEAPON_DOUBLECOLT;
case 3: return WEAPON_DOUBLESHOTGUN;
case 4: return WEAPON_MINIGUN;
case 5: return WEAPON_ROCKETLAUNCHER;
case 6: return WEAPON_FLAMER;
case 7: return WEAPON_LASER;
case 8: return WEAPON_IRONCANNON;
}
return WEAPON_NONE;
};
// get selected number for weapon
INDEX GetSelectedWeapon(WeaponType EwtSelectedWeapon) {
switch(EwtSelectedWeapon) {
case WEAPON_KNIFE: case WEAPON_CHAINSAW: return 1;
case WEAPON_COLT: case WEAPON_DOUBLECOLT: return 2;
case WEAPON_SINGLESHOTGUN: case WEAPON_DOUBLESHOTGUN: return 3;
case WEAPON_TOMMYGUN: case WEAPON_MINIGUN: return 4;
case WEAPON_ROCKETLAUNCHER: case WEAPON_GRENADELAUNCHER: return 5;
case WEAPON_FLAMER: case WEAPON_SNIPER: return 6;
case WEAPON_LASER: return 7;
case WEAPON_IRONCANNON: return 8;
}
return 0;
};
// get secondary weapon from selected one
WeaponType GetAltWeapon(WeaponType EwtWeapon) {
switch (EwtWeapon) {
case WEAPON_KNIFE: return WEAPON_CHAINSAW;
case WEAPON_CHAINSAW: return WEAPON_KNIFE;
case WEAPON_COLT: return WEAPON_DOUBLECOLT;
case WEAPON_DOUBLECOLT: return WEAPON_COLT;
case WEAPON_SINGLESHOTGUN: return WEAPON_DOUBLESHOTGUN;
case WEAPON_DOUBLESHOTGUN: return WEAPON_SINGLESHOTGUN;
case WEAPON_TOMMYGUN: return WEAPON_MINIGUN;
case WEAPON_MINIGUN: return WEAPON_TOMMYGUN;
case WEAPON_ROCKETLAUNCHER: return WEAPON_GRENADELAUNCHER;
case WEAPON_GRENADELAUNCHER: return WEAPON_ROCKETLAUNCHER;
case WEAPON_FLAMER: return WEAPON_SNIPER;
case WEAPON_SNIPER: return WEAPON_FLAMER;
case WEAPON_LASER: return WEAPON_LASER;
case WEAPON_IRONCANNON: return WEAPON_IRONCANNON;
}
return WEAPON_NONE;
};
// select new weapon if possible
BOOL WeaponSelectOk(WeaponType wtToTry)
{
// if player has weapon and has enough ammo
if (((1<<(INDEX(wtToTry)-1))&m_iAvailableWeapons)
&&HasAmmo(wtToTry)) {
// if different weapon
if (wtToTry!=m_iCurrentWeapon) {
// initiate change
//m_bHasAmmo = FALSE;
m_iWantedWeapon = wtToTry;
m_bChangeWeapon = TRUE;
}
// selection ok
return TRUE;
// if no weapon or not enough ammo
} else {
// selection not ok
return FALSE;
}
}
// select new weapon when no more ammo
void SelectNewWeapon()
{
switch (m_iCurrentWeapon) {
case WEAPON_NONE:
case WEAPON_KNIFE: case WEAPON_COLT: case WEAPON_DOUBLECOLT:
case WEAPON_SINGLESHOTGUN: case WEAPON_DOUBLESHOTGUN:
case WEAPON_TOMMYGUN: case WEAPON_MINIGUN: case WEAPON_SNIPER:
WeaponSelectOk(WEAPON_MINIGUN)||
WeaponSelectOk(WEAPON_TOMMYGUN)||
WeaponSelectOk(WEAPON_DOUBLESHOTGUN)||
WeaponSelectOk(WEAPON_SINGLESHOTGUN)||
WeaponSelectOk(WEAPON_DOUBLECOLT)||
WeaponSelectOk(WEAPON_COLT)||
WeaponSelectOk(WEAPON_KNIFE);
break;
case WEAPON_IRONCANNON:
WeaponSelectOk(WEAPON_ROCKETLAUNCHER)||
WeaponSelectOk(WEAPON_GRENADELAUNCHER)||
WeaponSelectOk(WEAPON_MINIGUN)||
WeaponSelectOk(WEAPON_TOMMYGUN)||
WeaponSelectOk(WEAPON_DOUBLESHOTGUN)||
WeaponSelectOk(WEAPON_SINGLESHOTGUN)||
WeaponSelectOk(WEAPON_DOUBLECOLT)||
WeaponSelectOk(WEAPON_COLT)||
WeaponSelectOk(WEAPON_KNIFE);
break;
case WEAPON_ROCKETLAUNCHER:
case WEAPON_GRENADELAUNCHER:
WeaponSelectOk(WEAPON_ROCKETLAUNCHER)||
WeaponSelectOk(WEAPON_GRENADELAUNCHER)||
WeaponSelectOk(WEAPON_MINIGUN)||
WeaponSelectOk(WEAPON_TOMMYGUN)||
WeaponSelectOk(WEAPON_DOUBLESHOTGUN)||
WeaponSelectOk(WEAPON_SINGLESHOTGUN)||
WeaponSelectOk(WEAPON_DOUBLECOLT)||
WeaponSelectOk(WEAPON_COLT)||
WeaponSelectOk(WEAPON_KNIFE);
break;
case WEAPON_LASER: case WEAPON_FLAMER: case WEAPON_CHAINSAW:
WeaponSelectOk(WEAPON_LASER)||
WeaponSelectOk(WEAPON_FLAMER)||
WeaponSelectOk(WEAPON_MINIGUN)||
WeaponSelectOk(WEAPON_TOMMYGUN)||
WeaponSelectOk(WEAPON_DOUBLESHOTGUN)||
WeaponSelectOk(WEAPON_SINGLESHOTGUN)||
WeaponSelectOk(WEAPON_DOUBLECOLT)||
WeaponSelectOk(WEAPON_COLT)||
WeaponSelectOk(WEAPON_KNIFE);
break;
default:
WeaponSelectOk(WEAPON_KNIFE);
ASSERT(FALSE);
}
};
// does weapon have ammo
BOOL HasAmmo(WeaponType EwtWeapon) {
switch (EwtWeapon) {
case WEAPON_KNIFE: case WEAPON_COLT: case WEAPON_DOUBLECOLT: return TRUE;
case WEAPON_SINGLESHOTGUN: return (m_iShells>0);
case WEAPON_DOUBLESHOTGUN: return (m_iShells>1);
case WEAPON_TOMMYGUN: return (m_iBullets>0);
case WEAPON_SNIPER: return (m_iSniperBullets>0);
case WEAPON_MINIGUN: return (m_iBullets>0);
case WEAPON_ROCKETLAUNCHER: return (m_iRockets>0);
case WEAPON_GRENADELAUNCHER: return (m_iGrenades>0);
case WEAPON_FLAMER: return (m_iNapalm>0);
case WEAPON_CHAINSAW: return TRUE;
case WEAPON_LASER: return (m_iElectricity>0);
case WEAPON_IRONCANNON: return (m_iIronBalls>0);
}
return FALSE;
};
/*
* >>>--- DEFAULT ANIM ---<<<
*/
void PlayDefaultAnim(void) {
switch(m_iCurrentWeapon) {
case WEAPON_NONE:
break;
case WEAPON_KNIFE:
switch (m_iKnifeStand) {
case 1: m_moWeapon.PlayAnim(KNIFE_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case 3: m_moWeapon.PlayAnim(KNIFE_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
default: ASSERTALWAYS("Unknown knife stand.");
}
break;
case WEAPON_DOUBLECOLT:
m_moWeaponSecond.PlayAnim(COLT_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE);
case WEAPON_COLT:
m_moWeapon.PlayAnim(COLT_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_SINGLESHOTGUN:
m_moWeapon.PlayAnim(SINGLESHOTGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_DOUBLESHOTGUN:
m_moWeapon.PlayAnim(DOUBLESHOTGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_TOMMYGUN:
m_moWeapon.PlayAnim(TOMMYGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_SNIPER:
m_moWeapon.PlayAnim(SNIPER_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_MINIGUN:
m_moWeapon.PlayAnim(MINIGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_ROCKETLAUNCHER:
m_moWeapon.PlayAnim(ROCKETLAUNCHER_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_GRENADELAUNCHER:
m_moWeapon.PlayAnim(GRENADELAUNCHER_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
/*
case WEAPON_PIPEBOMB:
if (m_bPipeBombDropped) {
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKTHROWWAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
} else {
m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_BOMBWAIT2, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE);
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKWAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
}*/
case WEAPON_FLAMER:
m_moWeapon.PlayAnim(FLAMER_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_CHAINSAW:
m_moWeapon.PlayAnim(CHAINSAW_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
case WEAPON_LASER:
m_moWeapon.PlayAnim(LASER_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
/*
case WEAPON_GHOSTBUSTER:
m_moWeapon.PlayAnim(GHOSTBUSTER_ANIM_WAIT03, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
*/
case WEAPON_IRONCANNON:
// case WEAPON_NUKECANNON:
m_moWeapon.PlayAnim(CANNON_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break;
default:
ASSERTALWAYS("Unknown weapon.");
}
};
/*
* >>>--- WEAPON BORING ---<<<
*/
FLOAT KnifeBoring(void) {
// play boring anim
INDEX iAnim;
switch (m_iKnifeStand) {
case 1: iAnim = KNIFE_ANIM_WAIT1; break;
case 3: iAnim = KNIFE_ANIM_WAIT1; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT ColtBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = COLT_ANIM_WAIT3; break;
case 1: iAnim = COLT_ANIM_WAIT4; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT DoubleColtBoring(void) {
// play boring anim for one colt
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = COLT_ANIM_WAIT3; break;
case 1: iAnim = COLT_ANIM_WAIT4; break;
}
if (IRnd()&1) {
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
} else {
m_moWeaponSecond.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeaponSecond.GetAnimLength(iAnim);
}
};
FLOAT SingleShotgunBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = SINGLESHOTGUN_ANIM_WAIT2; break;
case 1: iAnim = SINGLESHOTGUN_ANIM_WAIT3; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT DoubleShotgunBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = DOUBLESHOTGUN_ANIM_WAIT2; break;
case 1: iAnim = DOUBLESHOTGUN_ANIM_WAIT3; break;
case 2: iAnim = DOUBLESHOTGUN_ANIM_WAIT4; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT TommyGunBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = TOMMYGUN_ANIM_WAIT2; break;
case 1: iAnim = TOMMYGUN_ANIM_WAIT3; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT SniperBoring(void) {
// play boring anim
INDEX iAnim;
iAnim = SNIPER_ANIM_WAIT01;
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT MiniGunBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = MINIGUN_ANIM_WAIT2; break;
case 1: iAnim = MINIGUN_ANIM_WAIT3; break;
case 2: iAnim = MINIGUN_ANIM_WAIT4; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT RocketLauncherBoring(void) {
// play boring anim
m_moWeapon.PlayAnim(ROCKETLAUNCHER_ANIM_WAIT2, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(ROCKETLAUNCHER_ANIM_WAIT2);
};
FLOAT GrenadeLauncherBoring(void) {
// play boring anim
m_moWeapon.PlayAnim(GRENADELAUNCHER_ANIM_WAIT2, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(GRENADELAUNCHER_ANIM_WAIT2);
};
/*
FLOAT PipeBombBoring(void) {
if (IRnd()&1 && !m_bPipeBombDropped) {
// play boring anim for hand with bomb
INDEX iAnim;
switch (IRnd()%4) {
case 0: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT1; break;
case 1: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT3; break;
case 2: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT4; break;
case 3: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT5; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
} else {
// play boring anim for hand with stick
INDEX iAnimSecond;
if (m_bPipeBombDropped) {
switch (IRnd()%2) {
case 0: iAnimSecond = HANDWITHSTICK_ANIM_STICKTHROWWAIT2; break;
case 1: iAnimSecond = HANDWITHSTICK_ANIM_STICKTHROWWAIT3; break;
}
} else {
switch (IRnd()%3) {
case 0: iAnimSecond = HANDWITHSTICK_ANIM_STICKWAIT2; break;
case 1: iAnimSecond = HANDWITHSTICK_ANIM_STICKWAIT3; break;
case 2: iAnimSecond = HANDWITHSTICK_ANIM_STICKWAIT4; break;
}
}
m_moWeaponSecond.PlayAnim(iAnimSecond, AOF_SMOOTHCHANGE);
return m_moWeaponSecond.GetAnimLength(iAnimSecond);
}
};*/
FLOAT FlamerBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%4) {
case 0: iAnim = FLAMER_ANIM_WAIT02; break;
case 1: iAnim = FLAMER_ANIM_WAIT03; break;
case 2: iAnim = FLAMER_ANIM_WAIT04; break;
case 3: iAnim = FLAMER_ANIM_WAIT05; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT ChainsawBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = CHAINSAW_ANIM_WAIT2; break;
case 1: iAnim = CHAINSAW_ANIM_WAIT3; break;
case 2: iAnim = CHAINSAW_ANIM_WAIT4; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
FLOAT LaserBoring(void) {
// play boring anim
INDEX iAnim;
iAnim = LASER_ANIM_WAIT02;
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
/*
FLOAT GhostBusterBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = GHOSTBUSTER_ANIM_WAIT01; break;
case 1: iAnim = GHOSTBUSTER_ANIM_WAIT02; break;
case 2: iAnim = GHOSTBUSTER_ANIM_WAIT04; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
*/
FLOAT CannonBoring(void) {
// play boring anim
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = CANNON_ANIM_WAIT02; break;
case 1: iAnim = CANNON_ANIM_WAIT03; break;
case 2: iAnim = CANNON_ANIM_WAIT04; break;
}
m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE);
return m_moWeapon.GetAnimLength(iAnim);
};
// find the weapon position in the remap array
WeaponType FindRemapedPos(WeaponType wt)
{
for (INDEX i=0; i<18; i++)
{
if (aiWeaponsRemap[i]==wt) {
return (WeaponType)i;
}
}
ASSERTALWAYS("Non-existant weapon in remap array!");
return (WeaponType)0;
}
// get secondary weapon for a given primary weapon
WeaponType PrimaryToSecondary(WeaponType wt)
{
if (wt==WEAPON_CHAINSAW) {
return WEAPON_KNIFE;
} else if (wt==WEAPON_DOUBLECOLT) {
return WEAPON_COLT;
} else if (wt==WEAPON_DOUBLESHOTGUN) {
return WEAPON_SINGLESHOTGUN;
} else if (wt==WEAPON_MINIGUN) {
return WEAPON_TOMMYGUN;
} else if (wt==WEAPON_ROCKETLAUNCHER) {
return WEAPON_GRENADELAUNCHER;
} else if (wt==WEAPON_SNIPER) {
return WEAPON_FLAMER;
} else {
return wt;
}
}
// get primary weapon for a given secondary weapon
WeaponType SecondaryToPrimary(WeaponType wt)
{
if (wt==WEAPON_KNIFE) {
return WEAPON_CHAINSAW;
} else if (wt==WEAPON_COLT) {
return WEAPON_DOUBLECOLT;
} else if (wt==WEAPON_SINGLESHOTGUN) {
return WEAPON_DOUBLESHOTGUN;
} else if (wt==WEAPON_TOMMYGUN) {
return WEAPON_MINIGUN;
} else if (wt==WEAPON_GRENADELAUNCHER) {
return WEAPON_ROCKETLAUNCHER;
} else if (wt==WEAPON_FLAMER) {
return WEAPON_SNIPER;
} else {
return wt;
}
}
/*
* >>>--- WEAPON CHANGE FUNCTIONS ---<<<
*/
// find first possible weapon in given direction
/* WeaponType FindWeaponInDirection(INDEX iDir)
{
WeaponType wtOrg = (WeaponType)m_iWantedWeapon;
WeaponType wt = wtOrg;
FOREVER {
(INDEX&)wt += iDir;
if (wt<WEAPON_KNIFE) {
wt = WEAPON_IRONCANNON;
}
if (wt>WEAPON_IRONCANNON) {
wt = WEAPON_KNIFE;
}
if (wt==wtOrg) {
break;
}
if ( ( ((1<<(wt-1))&m_iAvailableWeapons) && HasAmmo(wt)) ) {
return wt;
}
}
return m_iWantedWeapon;
}*/
WeaponType FindWeaponInDirection(INDEX iDir)
{
INDEX wtOrg = FindRemapedPos(m_iWantedWeapon);
INDEX wti = wtOrg;
FOREVER {
(INDEX&)wti += iDir;
if (wti<1) {
wti = WEAPON_IRONCANNON;
}
if (wti>14) {
wti = WEAPON_KNIFE;
}
if (wti==wtOrg) {
break;
}
WeaponType wt = (WeaponType) aiWeaponsRemap[wti];
if ( ( ((1<<(wt-1))&m_iAvailableWeapons) && HasAmmo(wt)) ) {
return wt;
}
}
return m_iWantedWeapon;
}
// select new weapon
void SelectWeaponChange(INDEX iSelect)
{
WeaponType EwtTemp;
// mark that weapon change is required
m_tmWeaponChangeRequired = _pTimer->CurrentTick();
// if storing current weapon
if (iSelect==0) {
m_bChangeWeapon = TRUE;
m_iWantedWeapon = WEAPON_NONE;
return;
}
// if restoring best weapon
if (iSelect==-4) {
SelectNewWeapon() ;
return;
}
// if flipping weapon
if (iSelect==-3) {
EwtTemp = GetAltWeapon(m_iWantedWeapon);
// if selecting previous weapon
} else if (iSelect==-2) {
EwtTemp = FindWeaponInDirection(-1);
// if selecting next weapon
} else if (iSelect==-1) {
EwtTemp = FindWeaponInDirection(+1);
// if selecting directly
} else {
// flip current weapon
if (iSelect == GetSelectedWeapon(m_iWantedWeapon)) {
EwtTemp = GetAltWeapon(m_iWantedWeapon);
// change to wanted weapon
} else {
EwtTemp = GetStrongerWeapon(iSelect);
// if weapon don't exist or don't have ammo flip it
if ( !((1<<(EwtTemp-1))&m_iAvailableWeapons) || !HasAmmo(EwtTemp)) {
EwtTemp = GetAltWeapon(EwtTemp);
}
}
}
// wanted weapon exist and has ammo
BOOL bChange = ( ((1<<(EwtTemp-1))&m_iAvailableWeapons) && HasAmmo(EwtTemp));
if (bChange) {
m_iWantedWeapon = EwtTemp;
m_bChangeWeapon = TRUE;
}
};
void MinigunSmoke()
{
if( !hud_bShowWeapon)
{
return;
}
// smoke
CPlayer &pl = (CPlayer&)*m_penPlayer;
if( pl.m_pstState!=PST_DIVE)
{
BOOL b3rdPersonView = TRUE;
if(pl.m_penCamera==NULL && pl.m_pen3rdPersonView==NULL)
{
b3rdPersonView = FALSE;
}
INDEX ctBulletsFired = ClampUp(m_iBulletsOnFireStart-m_iBullets, INDEX(200));
for( INDEX iSmoke=0; iSmoke<ctBulletsFired/10; iSmoke++)
{
ShellLaunchData *psldSmoke = &pl.m_asldData[pl.m_iFirstEmptySLD];
CPlacement3D plPipe;
if( b3rdPersonView)
{
CalcWeaponPosition3rdPersonView(FLOAT3D(afMinigunPipe3rdView[0],
afMinigunPipe3rdView[1], afMinigunPipe3rdView[2]), plPipe, FALSE);
}
else
{
CalcWeaponPosition(FLOAT3D(afMinigunPipe[0], afMinigunPipe[1], afMinigunPipe[2]), plPipe, FALSE);
}
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle);
psldSmoke->sld_vPos = plPipe.pl_PositionVector+pl.en_vCurrentTranslationAbsolute*iSmoke*_pTimer->TickQuantum;
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
psldSmoke->sld_vUp = vUp;
psldSmoke->sld_tmLaunch = _pTimer->CurrentTick()+iSmoke*_pTimer->TickQuantum;
psldSmoke->sld_estType = ESL_BULLET_SMOKE;
psldSmoke->sld_fSize = 0.75f+ctBulletsFired/50.0f;
FLOAT3D vSpeedRelative = FLOAT3D(-0.06f, FRnd()/4.0f, -0.06f);
psldSmoke->sld_vSpeed = vSpeedRelative*m+pl.en_vCurrentTranslationAbsolute;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
};
BOOL SniperZoomDiscrete(INDEX iDirection, BOOL &bZoomChanged)
{
bZoomChanged = FALSE;
// zoom in one zoom level
if (iDirection>0) {
for (INDEX i=0; i<iSniperDiscreteZoomLevels ; i++) {
if (afSniperZoom[2*i]<m_fSniperFOV) {
m_fSniperFOV=afSniperZoom[2*i];
m_fSniperFOVlast=m_fSniperFOV;
bZoomChanged = TRUE;
break;
}
}
// zoom out one zoom level
} else {
for (INDEX i=iSniperDiscreteZoomLevels ; i>0; i--) {
if (afSniperZoom[2*i]>m_fSniperFOV) {
m_fSniperFOV=afSniperZoom[2*i];
m_fSniperFOVlast=m_fSniperFOV;
bZoomChanged = TRUE;
break;
}
}
}
if (m_fSniperFOV<90.0f) {
m_bSniping = TRUE;
}
else {
m_bSniping = FALSE;
}
return m_bSniping;
};
procedures:
/*
* >>>--- WEAPON CHANGE PROCEDURE ---<<<
*/
ChangeWeapon() {
// if really changing weapon, make sure sniping is off and notify owner of the change
if (m_iCurrentWeapon!=m_iWantedWeapon) {
m_fSniperFOV = m_fSniperFOVlast = m_fSniperMaxFOV;
m_bSniping = FALSE;
m_penPlayer->SendEvent(EWeaponChanged());
}
// weapon is changed
m_bChangeWeapon = FALSE;
// if this is not current weapon change it
if (m_iCurrentWeapon!=m_iWantedWeapon) {
/*
// iron/nuke cannon changing is special
if( (m_iCurrentWeapon == WEAPON_IRONCANNON) && (m_iWantedWeapon == WEAPON_NUKECANNON) )
{
autocall ChangeToNukeCannon() EEnd;
// mark that weapon change has ended
m_tmWeaponChangeRequired = 0.0f;
jump Idle();
}
else if( (m_iCurrentWeapon == WEAPON_NUKECANNON) && (m_iWantedWeapon == WEAPON_IRONCANNON) )
{
autocall ChangeToIronCannon() EEnd;
// mark that weapon change has ended
m_tmWeaponChangeRequired = 0.0f;
jump Idle();
}
*/
// store current weapon
m_iPreviousWeapon = m_iCurrentWeapon;
autocall PutDown() EEnd;
// set new weapon
m_iCurrentWeapon = m_iWantedWeapon;
// remember current weapon for console usage
wpn_iCurrent = m_iCurrentWeapon;
autocall BringUp() EEnd;
// start engine sound if chainsaw
if (m_iCurrentWeapon==WEAPON_CHAINSAW) {
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 1.0f, 1.0f);
PlaySound(pl.m_soWeaponAmbient, SOUND_CS_IDLE, SOF_3D|SOF_VOLUMETRIC|SOF_LOOP|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawIdle");}
}
// knife change stand
} else if (m_iWantedWeapon == WEAPON_KNIFE) {
// mark that weapon change has ended
m_tmWeaponChangeRequired = 0.0f;
autocall ChangeKnifeStand() EEnd;
/* // pipebomb reload
} else if (m_iWantedWeapon == WEAPON_PIPEBOMB) {
// mark that weapon change has ended
m_tmWeaponChangeRequired = 0.0f;
jump Reload();
*/
}
jump Idle();
};
// put weapon down
PutDown() {
// start weapon put down animation
switch (m_iCurrentWeapon) {
case WEAPON_NONE:
break;
// knife have different stands
case WEAPON_KNIFE:
if (m_iKnifeStand==1) {
m_iAnim = KNIFE_ANIM_PULLOUT;
} else if (m_iKnifeStand==3) {
m_iAnim = KNIFE_ANIM_PULLOUT;
}
break;
case WEAPON_DOUBLECOLT: case WEAPON_COLT:
m_iAnim = COLT_ANIM_DEACTIVATE;
break;
case WEAPON_SINGLESHOTGUN:
m_iAnim = SINGLESHOTGUN_ANIM_DEACTIVATE;
break;
case WEAPON_DOUBLESHOTGUN:
m_iAnim = DOUBLESHOTGUN_ANIM_DEACTIVATE;
break;
case WEAPON_TOMMYGUN:
m_iAnim = TOMMYGUN_ANIM_DEACTIVATE;
break;
case WEAPON_SNIPER:
m_iAnim = SNIPER_ANIM_DEACTIVATE;
break;
case WEAPON_MINIGUN:
m_iAnim = MINIGUN_ANIM_DEACTIVATE;
break;
case WEAPON_ROCKETLAUNCHER:
m_iAnim = ROCKETLAUNCHER_ANIM_DEACTIVATE;
break;
case WEAPON_GRENADELAUNCHER:
m_iAnim = GRENADELAUNCHER_ANIM_DEACTIVATE;
break;
/* case WEAPON_PIPEBOMB:
m_iAnim = HANDWITHBOMB_ANIM_DEACTIVATE;
break;*/
case WEAPON_FLAMER:
m_iAnim = FLAMER_ANIM_DEACTIVATE;
break;
case WEAPON_CHAINSAW: {
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeaponAmbient, SOUND_CS_BRINGDOWN, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("ChainsawIdle");}
m_iAnim = CHAINSAW_ANIM_DEACTIVATE;
break; }
case WEAPON_LASER:
m_iAnim = LASER_ANIM_DEACTIVATE;
break;
/*
case WEAPON_GHOSTBUSTER:
m_iAnim = GHOSTBUSTER_ANIM_DEACTIVATE;
break;
*/
case WEAPON_IRONCANNON:
// case WEAPON_NUKECANNON:
m_iAnim = CANNON_ANIM_DEACTIVATE;
break;
default: ASSERTALWAYS("Unknown weapon.");
}
// start animator
CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator;
plan.BodyPushAnimation();
if (m_iCurrentWeapon==WEAPON_NONE) {
return EEnd();
}
// --->>> COLT -> DOUBLE COLT SPECIFIC <<<---
if (m_iCurrentWeapon==WEAPON_COLT && m_iWantedWeapon==WEAPON_DOUBLECOLT) {
return EEnd();
}
// --->>> DOUBLE COLT SPECIFIC <<<---
if (m_iCurrentWeapon==WEAPON_DOUBLECOLT) {
m_moWeaponSecond.PlayAnim(m_iAnim, 0);
}
// --->>> DOUBLE COLT -> COLT SPECIFIC <<<---
if (m_iCurrentWeapon==WEAPON_DOUBLECOLT && m_iWantedWeapon==WEAPON_COLT) {
autowait(m_moWeapon.GetAnimLength(m_iAnim));
return EEnd();
}
/*
// --->>> PIPEBOMB SPECIFIC <<<---
if (m_iCurrentWeapon==WEAPON_PIPEBOMB) {
m_moWeapon.PlayAnim(m_iAnim, 0);
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_DEACTIVATE, 0);
autowait(Max(m_moWeapon.GetAnimLength(m_iAnim), m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_DEACTIVATE)));
return EEnd();
}
*/
// reload colts automagicaly when puting them away
BOOL bNowColt = m_iCurrentWeapon==WEAPON_COLT || m_iCurrentWeapon==WEAPON_DOUBLECOLT;
BOOL bWantedColt = m_iWantedWeapon==WEAPON_COLT || m_iWantedWeapon==WEAPON_DOUBLECOLT;
if (bNowColt&&!bWantedColt) {
m_iColtBullets = 6;
}
m_moWeapon.PlayAnim(m_iAnim, 0);
autowait(m_moWeapon.GetAnimLength(m_iAnim));
return EEnd();
};
// bring up weapon
BringUp() {
// reset weapon draw offset
ResetWeaponMovingOffset();
// set weapon model for current weapon
SetCurrentWeaponModel();
// start current weapon bring up animation
switch (m_iCurrentWeapon) {
case WEAPON_KNIFE:
m_iAnim = KNIFE_ANIM_PULL;
m_iKnifeStand = 1;
break;
case WEAPON_COLT: case WEAPON_DOUBLECOLT:
m_iAnim = COLT_ANIM_ACTIVATE;
SetFlare(0, FLARE_REMOVE);
SetFlare(1, FLARE_REMOVE);
break;
case WEAPON_SINGLESHOTGUN:
m_iAnim = SINGLESHOTGUN_ANIM_ACTIVATE;
SetFlare(0, FLARE_REMOVE);
break;
case WEAPON_DOUBLESHOTGUN:
m_iAnim = DOUBLESHOTGUN_ANIM_ACTIVATE;
SetFlare(0, FLARE_REMOVE);
break;
case WEAPON_TOMMYGUN:
m_iAnim = TOMMYGUN_ANIM_ACTIVATE;
SetFlare(0, FLARE_REMOVE);
break;
case WEAPON_SNIPER:
m_iAnim = SNIPER_ANIM_ACTIVATE;
SetFlare(0, FLARE_REMOVE);
break;
case WEAPON_MINIGUN: {
CAttachmentModelObject *amo = m_moWeapon.GetAttachmentModel(MINIGUN_ATTACHMENT_BARRELS);
m_aMiniGunLast = m_aMiniGun = amo->amo_plRelative.pl_OrientationAngle(3);
m_iAnim = MINIGUN_ANIM_ACTIVATE;
SetFlare(0, FLARE_REMOVE);
break; }
case WEAPON_ROCKETLAUNCHER:
m_iAnim = ROCKETLAUNCHER_ANIM_ACTIVATE;
break;
case WEAPON_GRENADELAUNCHER:
m_iAnim = GRENADELAUNCHER_ANIM_ACTIVATE;
break;
/* case WEAPON_PIPEBOMB:
m_iAnim = HANDWITHBOMB_ANIM_ACTIVATE;
break;*/
case WEAPON_FLAMER:
m_iAnim = FLAMER_ANIM_ACTIVATE;
break;
case WEAPON_CHAINSAW: {
m_iAnim = CHAINSAW_ANIM_ACTIVATE;
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 1.0f, 1.0f);
PlaySound(pl.m_soWeaponAmbient, SOUND_CS_BRINGUP, SOF_3D|SOF_VOLUMETRIC|SOF_LOOP);
break; }
case WEAPON_LASER:
m_iAnim = LASER_ANIM_ACTIVATE;
break;
/* case WEAPON_GHOSTBUSTER:
m_iAnim = GHOSTBUSTER_ANIM_ACTIVATE;
break;
*/
case WEAPON_IRONCANNON:
// case WEAPON_NUKECANNON:
m_iAnim = CANNON_ANIM_ACTIVATE;
break;
case WEAPON_NONE:
break;
default: ASSERTALWAYS("Unknown weapon.");
}
// start animator
CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator;
plan.BodyPullAnimation();
// --->>> DOUBLE COLT -> COLT SPECIFIC <<<---
if (m_iPreviousWeapon==WEAPON_DOUBLECOLT && m_iCurrentWeapon==WEAPON_COLT) {
// mark that weapon change has ended
m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2;
return EEnd();
}
// --->>> DOUBLE COLT SPECIFIC <<<---
if (m_iCurrentWeapon==WEAPON_DOUBLECOLT) {
m_moWeaponSecond.PlayAnim(m_iAnim, 0);
}
// --->>> COLT -> COLT DOUBLE SPECIFIC <<<---
if (m_iPreviousWeapon==WEAPON_COLT && m_iCurrentWeapon==WEAPON_DOUBLECOLT) {
autowait(m_moWeapon.GetAnimLength(m_iAnim));
// mark that weapon change has ended
m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2;
return EEnd();
}
/*
// --->>> PIPEBOMB SPECIFIC <<<---
if (m_iCurrentWeapon==WEAPON_PIPEBOMB) {
m_moWeapon.PlayAnim(m_iAnim, 0);
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_ACTIVATE, 0);
autowait(Max(m_moWeapon.GetAnimLength(m_iAnim), m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_ACTIVATE)));
m_bPipeBombDropped = FALSE;
// mark that weapon change has ended
m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2;
return EEnd();
}
*/
m_moWeapon.PlayAnim(m_iAnim, 0);
autowait(m_moWeapon.GetAnimLength(m_iAnim));
/*
if( m_iCurrentWeapon == WEAPON_NUKECANNON)
{
autocall ChangeToNukeCannon() EEnd;
}
*/
// mark that weapon change has ended
m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2;
return EEnd();
};
/*
* >>>--- FIRE WEAPON ---<<<
*/
Fire()
{
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds
// force ending of weapon change
m_tmWeaponChangeRequired = 0;
m_bFireWeapon = TRUE;
m_bHasAmmo = HasAmmo(m_iCurrentWeapon);
// if has no ammo select new weapon
if (!m_bHasAmmo) {
SelectNewWeapon();
jump Idle();
}
// setup 3D sound parameters
Setup3DSoundParameters();
// start weapon firing animation for continuous firing
if (m_iCurrentWeapon==WEAPON_MINIGUN) {
jump MiniGunSpinUp();
} else if (m_iCurrentWeapon==WEAPON_FLAMER) {
jump FlamerStart();
} else if (m_iCurrentWeapon==WEAPON_CHAINSAW) {
jump ChainsawFire();
/* } else if (m_iCurrentWeapon==WEAPON_GHOSTBUSTER) {
autocall GhostBusterStart() EEnd; */
} else if (m_iCurrentWeapon==WEAPON_LASER) {
GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRESHORT, AOF_LOOPING);
} else if (m_iCurrentWeapon==WEAPON_TOMMYGUN) {
autocall TommyGunStart() EEnd;
} else if (m_iCurrentWeapon==WEAPON_IRONCANNON /*|| (m_iCurrentWeapon==WEAPON_NUKECANNON)*/) {
jump CannonFireStart();
}
// clear last lerped bullet position
m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f);
// reset laser barrel (to start shooting always from left up barrel)
m_iLaserBarrel = 0;
while (HoldingFire() && m_bHasAmmo) {
// boring animation
((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_fLastActionTime = _pTimer->CurrentTick();
wait() {
on (EBegin) : {
// fire one shot
switch (m_iCurrentWeapon) {
case WEAPON_KNIFE: call SwingKnife(); break;
case WEAPON_COLT: call FireColt(); break;
case WEAPON_DOUBLECOLT: call FireDoubleColt(); break;
case WEAPON_SINGLESHOTGUN: call FireSingleShotgun(); break;
case WEAPON_DOUBLESHOTGUN: call FireDoubleShotgun(); break;
case WEAPON_TOMMYGUN: call FireTommyGun(); break;
case WEAPON_SNIPER: call FireSniper(); break;
case WEAPON_ROCKETLAUNCHER: call FireRocketLauncher(); break;
case WEAPON_GRENADELAUNCHER: call FireGrenadeLauncher(); break;
case WEAPON_LASER: call FireLaser(); break;
default: ASSERTALWAYS("Unknown weapon.");
}
resume;
}
on (EEnd) : {
stop;
}
}
}
// stop weapon firing animation for continuous firing
switch (m_iCurrentWeapon) {
case WEAPON_TOMMYGUN: { jump TommyGunStop(); break; }
case WEAPON_MINIGUN: { jump MiniGunSpinDown(); break; }
case WEAPON_FLAMER: { jump FlamerStop(); break; }
// case WEAPON_GHOSTBUSTER: { jump GhostBusterStop(); break; }
case WEAPON_LASER: {
GetAnimator()->FireAnimationOff();
jump Idle();
}
default: { jump Idle(); }
}
};
// ***************** SWING KNIFE *****************
SwingKnife() {
INDEX iSwing;
// animator swing
GetAnimator()->FireAnimation(BODY_ANIM_KNIFE_ATTACK, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
// depending on stand choose random attack
switch (m_iKnifeStand) {
case 1:
iSwing = IRnd()%2;
switch (iSwing) {
case 0: m_iAnim = KNIFE_ANIM_ATTACK01; m_fAnimWaitTime = 0.25f;
PlaySound(pl.m_soWeapon0, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");}
break;
case 1: m_iAnim = KNIFE_ANIM_ATTACK02; m_fAnimWaitTime = 0.35f;
PlaySound(pl.m_soWeapon1, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");}
break;
}
break;
case 3:
iSwing = IRnd()%2;
switch (iSwing) {
case 0: m_iAnim = KNIFE_ANIM_ATTACK01; m_fAnimWaitTime = 0.50f;
PlaySound(pl.m_soWeapon1, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");}
break;
case 1: m_iAnim = KNIFE_ANIM_ATTACK02; m_fAnimWaitTime = 0.50f;
PlaySound(pl.m_soWeapon3, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");}
break;
}
break;
}
m_moWeapon.PlayAnim(m_iAnim, 0);
if (CutWithKnife(0, 0, 3.0f, 2.0f, 0.5f, ((GetSP()->sp_bCooperative) ? 100.0f : 50.0f))) {
autowait(m_fAnimWaitTime);
} else if (TRUE) {
autowait(m_fAnimWaitTime/2);
CutWithKnife(0, 0, 3.0f, 2.0f, 0.5f, ((GetSP()->sp_bCooperative) ? 100.0f : 50.0f));
autowait(m_fAnimWaitTime/2);
}
if (m_moWeapon.GetAnimLength(m_iAnim)-m_fAnimWaitTime>=_pTimer->TickQuantum) {
autowait(m_moWeapon.GetAnimLength(m_iAnim)-m_fAnimWaitTime);
}
return EEnd();
};
// ***************** FIRE COLT *****************
FireColt() {
GetAnimator()->FireAnimation(BODY_ANIM_COLT_FIRERIGHT, 0);
// fire bullet
FireOneBullet(wpn_fFX[WEAPON_COLT], wpn_fFY[WEAPON_COLT], 500.0f,
((GetSP()->sp_bCooperative) ? 10.0f : 20.0f));
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_fire");}
DoRecoil();
SpawnRangeSound(40.0f);
m_iColtBullets--;
SetFlare(0, FLARE_ADD);
PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_COLT_FIRE, SOF_3D|SOF_VOLUMETRIC);
/*
if( pl.m_pstState!=PST_DIVE)
{
// smoke
ShellLaunchData &sldRight = pl.m_asldData[pl.m_iFirstEmptySLD];
sldRight.sld_vPos = FLOAT3D(afRightColtPipe[0], afRightColtPipe[1], afRightColtPipe[2]);
sldRight.sld_tmLaunch = _pTimer->CurrentTick();
sldRight.sld_estType = ESL_COLT_SMOKE;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
*/
// random colt fire
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = COLT_ANIM_FIRE1; break;
case 1: iAnim = COLT_ANIM_FIRE2; break;
case 2: iAnim = COLT_ANIM_FIRE3; break;
}
m_moWeapon.PlayAnim(iAnim, 0);
autowait(m_moWeapon.GetAnimLength(iAnim)-0.05f);
m_moWeapon.PlayAnim(COLT_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART);
// no more bullets in colt -> reload
if (m_iColtBullets == 0) {
jump ReloadColt();
}
return EEnd();
};
// reload colt
ReloadColt() {
if (m_iColtBullets>=6) {
return EEnd();
}
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon1, SOUND_COLT_RELOAD, SOF_3D|SOF_VOLUMETRIC);
m_moWeapon.PlayAnim(COLT_ANIM_RELOAD, 0);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_reload");}
autowait(m_moWeapon.GetAnimLength(COLT_ANIM_RELOAD));
m_iColtBullets = 6;
return EEnd();
};
// ***************** FIRE DOUBLE COLT *****************
FireDoubleColt() {
// fire first colt - one bullet less in colt
GetAnimator()->FireAnimation(BODY_ANIM_COLT_FIRERIGHT, 0);
FireOneBullet(wpn_fFX[WEAPON_DOUBLECOLT], wpn_fFY[WEAPON_DOUBLECOLT], 500.0f, 10.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_fire");}
/*
CPlayer &pl1 = (CPlayer&)*m_penPlayer;
if( pl1.m_pstState!=PST_DIVE)
{
// smoke
ShellLaunchData &sldRight = pl1.m_asldData[pl1.m_iFirstEmptySLD];
sldRight.sld_vPos = FLOAT3D(afRightColtPipe[0], afRightColtPipe[1], afRightColtPipe[2]);
sldRight.sld_tmLaunch = _pTimer->CurrentTick();
sldRight.sld_estType = ESL_COLT_SMOKE;
pl1.m_iFirstEmptySLD = (pl1.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
*/
DoRecoil();
SpawnRangeSound(50.0f);
m_iColtBullets--;
SetFlare(0, FLARE_ADD);
PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0);
// sound
CPlayer &plSnd = (CPlayer&)*m_penPlayer;
PlaySound(plSnd.m_soWeapon0, SOUND_COLT_FIRE, SOF_3D|SOF_VOLUMETRIC);
// random colt fire
switch (IRnd()%3) {
case 0: m_iAnim = COLT_ANIM_FIRE1; break;
case 1: m_iAnim = COLT_ANIM_FIRE2; break;
case 2: m_iAnim = COLT_ANIM_FIRE3; break;
}
m_moWeapon.PlayAnim(m_iAnim, 0); // play first colt anim
autowait(m_moWeapon.GetAnimLength(m_iAnim)/2); // wait half of the anim
// fire second colt
GetAnimator()->FireAnimation(BODY_ANIM_COLT_FIRELEFT, 0);
m_bMirrorFire = TRUE;
FireOneBullet(wpn_fFX[WEAPON_DOUBLECOLT], wpn_fFY[WEAPON_DOUBLECOLT], 500.0f, 10.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_fire");}
/*
CPlayer &pl2 = (CPlayer&)*m_penPlayer;
if( pl2.m_pstState!=PST_DIVE)
{
// smoke
ShellLaunchData &sldLeft = pl2.m_asldData[pl2.m_iFirstEmptySLD];
sldLeft.sld_vPos = FLOAT3D(-afRightColtPipe[0], afRightColtPipe[1], afRightColtPipe[2]);
sldLeft.sld_tmLaunch = _pTimer->CurrentTick();
sldLeft.sld_estType = ESL_COLT_SMOKE;
pl2.m_iFirstEmptySLD = (pl2.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
*/
DoRecoil();
m_iSecondFlare = FLARE_ADD;
((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_iSecondFlare = FLARE_ADD;
PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0);
m_bMirrorFire = FALSE;
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon1, SOUND_COLT_FIRE, SOF_3D|SOF_VOLUMETRIC);
m_moWeaponSecond.PlayAnim(m_iAnim, 0);
autowait(m_moWeapon.GetAnimLength(m_iAnim)/2); // wait half of the anim
// no more bullets in colt -> reload
if (m_iColtBullets == 0) {
jump ReloadDoubleColt();
}
return EEnd();
};
// reload double colt
ReloadDoubleColt() {
if (m_iColtBullets>=6) {
return EEnd();
}
m_moWeapon.PlayAnim(COLT_ANIM_RELOAD, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon2, SOUND_COLT_RELOAD, SOF_3D|SOF_VOLUMETRIC);
// wait half of reload time
autowait(m_moWeapon.GetAnimLength(COLT_ANIM_RELOAD)/2);
m_moWeaponSecond.PlayAnim(COLT_ANIM_RELOAD, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon3, SOUND_COLT_RELOAD, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_reload");}
// wait second halt minus half shortest fire animation
autowait(m_moWeapon.GetAnimLength(COLT_ANIM_RELOAD)-0.25f);
m_iColtBullets = 6;
return EEnd();
};
// ***************** FIRE SINGLESHOTGUN *****************
FireSingleShotgun() {
// fire one shell
if (m_iShells>0) {
GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRELONG, 0);
FireBullets(wpn_fFX[WEAPON_SINGLESHOTGUN], wpn_fFY[WEAPON_SINGLESHOTGUN],
500.0f, 10.0f, 7, afSingleShotgunPellets, 0.2f, 0.03f);
DoRecoil();
SpawnRangeSound(60.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Snglshotgun_fire");}
DecAmmo(m_iShells, 1);
SetFlare(0, FLARE_ADD);
PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0);
m_moWeapon.PlayAnim(GetSP()->sp_bCooperative ? SINGLESHOTGUN_ANIM_FIRE1 : SINGLESHOTGUN_ANIM_FIRE1FAST, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_SINGLESHOTGUN_FIRE, SOF_3D|SOF_VOLUMETRIC);
if( hud_bShowWeapon)
{
if( pl.m_pstState==PST_DIVE)
{
// bubble
ShellLaunchData &sldBubble = pl.m_asldData[pl.m_iFirstEmptySLD];
CPlacement3D plShell;
CalcWeaponPosition(FLOAT3D(afSingleShotgunShellPos[0],
afSingleShotgunShellPos[1], afSingleShotgunShellPos[2]), plShell, FALSE);
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plShell.pl_OrientationAngle);
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sldBubble.sld_vPos = plShell.pl_PositionVector;
sldBubble.sld_vUp = vUp;
sldBubble.sld_tmLaunch = _pTimer->CurrentTick();
sldBubble.sld_estType = ESL_BUBBLE;
FLOAT3D vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f);
sldBubble.sld_vSpeed = vSpeedRelative*m;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
else
{
// smoke
ShellLaunchData &sldPipe1 = pl.m_asldData[pl.m_iFirstEmptySLD];
CPlacement3D plPipe;
CalcWeaponPosition(FLOAT3D(afSingleShotgunPipe[0], afSingleShotgunPipe[1], afSingleShotgunPipe[2]), plPipe, FALSE);
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle);
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sldPipe1.sld_vPos = plPipe.pl_PositionVector;
sldPipe1.sld_vUp = vUp;
sldPipe1.sld_tmLaunch = _pTimer->CurrentTick();
sldPipe1.sld_estType = ESL_SHOTGUN_SMOKE;
FLOAT3D vSpeedRelative = FLOAT3D(0, 0.0f, -12.5f);
sldPipe1.sld_vSpeed = vSpeedRelative*m;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
autowait(GetSP()->sp_bCooperative ? 0.5f : 0.375f);
/* drop shell */
/* add one empty bullet shell */
CPlacement3D plShell;
CalcWeaponPosition(FLOAT3D(afSingleShotgunShellPos[0], afSingleShotgunShellPos[1], afSingleShotgunShellPos[2]), plShell, FALSE);
FLOATmatrix3D mRot;
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
if( hud_bShowWeapon)
{
CPlayer *penPlayer = GetPlayer();
ShellLaunchData &sld = penPlayer->m_asldData[penPlayer->m_iFirstEmptySLD];
sld.sld_vPos = plShell.pl_PositionVector;
FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f);
sld.sld_vSpeed = vSpeedRelative*mRot;
const FLOATmatrix3D &m = penPlayer->GetRotationMatrix();
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sld.sld_vUp = vUp;
sld.sld_tmLaunch = _pTimer->CurrentTick();
sld.sld_estType = ESL_SHOTGUN;
// move to next shell position
penPlayer->m_iFirstEmptySLD = (penPlayer->m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
/* drop shell */
autowait(m_moWeapon.GetAnimLength(
(GetSP()->sp_bCooperative ? SINGLESHOTGUN_ANIM_FIRE1:SINGLESHOTGUN_ANIM_FIRE1FAST) ) -
(GetSP()->sp_bCooperative ? 0.5f : 0.375f) );
// no ammo -> change weapon
if (m_iShells<=0) { SelectNewWeapon(); }
} else {
ASSERTALWAYS("SingleShotgun - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
// ***************** FIRE DOUBLESHOTGUN *****************
FireDoubleShotgun() {
// fire two shell
if (m_iShells>1) {
GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRELONG, 0);
FireBullets(wpn_fFX[WEAPON_DOUBLESHOTGUN], wpn_fFY[WEAPON_DOUBLESHOTGUN],
500.0f, 10.0f, 14, afDoubleShotgunPellets, 0.3f, 0.03f);
DoRecoil();
SpawnRangeSound(70.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Dblshotgun_fire");}
DecAmmo(m_iShells, 2);
SetFlare(0, FLARE_ADD);
PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0);
m_moWeapon.PlayAnim(GetSP()->sp_bCooperative ? DOUBLESHOTGUN_ANIM_FIRE : DOUBLESHOTGUN_ANIM_FIREFAST, 0);
m_moWeaponSecond.PlayAnim(GetSP()->sp_bCooperative ? HANDWITHAMMO_ANIM_FIRE : HANDWITHAMMO_ANIM_FIREFAST, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f); // fire
PlaySound(pl.m_soWeapon0, SOUND_DOUBLESHOTGUN_FIRE, SOF_3D|SOF_VOLUMETRIC);
if( hud_bShowWeapon)
{
if( pl.m_pstState==PST_DIVE)
{
// bubble (pipe 1)
ShellLaunchData &sldBubble1 = pl.m_asldData[pl.m_iFirstEmptySLD];
CPlacement3D plShell;
CalcWeaponPosition(FLOAT3D(-0.11f, 0.1f, -0.3f), plShell, FALSE);
/*CalcWeaponPosition(FLOAT3D(afDoubleShotgunShellPos[0],
afDoubleShotgunShellPos[1], afDoubleShotgunShellPos[2]), plShell, FALSE);*/
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plShell.pl_OrientationAngle);
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sldBubble1.sld_vPos = plShell.pl_PositionVector;
sldBubble1.sld_vUp = vUp;
sldBubble1.sld_tmLaunch = _pTimer->CurrentTick();
sldBubble1.sld_estType = ESL_BUBBLE;
FLOAT3D vSpeedRelative = FLOAT3D(-0.1f, 0.0f, 0.01f);
sldBubble1.sld_vSpeed = vSpeedRelative*m;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
ShellLaunchData &sldBubble2 = pl.m_asldData[pl.m_iFirstEmptySLD];
// bubble (pipe 2)
sldBubble2 = sldBubble1;
vSpeedRelative = FLOAT3D(0.1f, 0.0f, -0.2f);
sldBubble2.sld_vSpeed = vSpeedRelative*m;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
else
{
// smoke (pipe 1)
ShellLaunchData &sldPipe1 = pl.m_asldData[pl.m_iFirstEmptySLD];
CPlacement3D plPipe;
CalcWeaponPosition(FLOAT3D(afDoubleShotgunPipe[0], afDoubleShotgunPipe[1], afDoubleShotgunPipe[2]), plPipe, FALSE);
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle);
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sldPipe1.sld_vPos = plPipe.pl_PositionVector;
sldPipe1.sld_vUp = vUp;
sldPipe1.sld_tmLaunch = _pTimer->CurrentTick();
sldPipe1.sld_estType = ESL_SHOTGUN_SMOKE;
FLOAT3D vSpeedRelative = FLOAT3D(-1, 0.0f, -12.5f);
sldPipe1.sld_vSpeed = vSpeedRelative*m;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
// smoke (pipe 2)
ShellLaunchData &sldPipe2 = pl.m_asldData[pl.m_iFirstEmptySLD];
sldPipe2 = sldPipe1;
vSpeedRelative = FLOAT3D(1, 0.0f, -12.5f);
sldPipe2.sld_vSpeed = vSpeedRelative*m;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
autowait(GetSP()->sp_bCooperative ? 0.25f : 0.15f);
if (m_iShells>=2) {
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon1, SOUND_DOUBLESHOTGUN_RELOAD, SOF_3D|SOF_VOLUMETRIC);
}
autowait( m_moWeapon.GetAnimLength(
(GetSP()->sp_bCooperative ? DOUBLESHOTGUN_ANIM_FIRE : DOUBLESHOTGUN_ANIM_FIREFAST)) -
(GetSP()->sp_bCooperative ? 0.25f : 0.15f) );
// no ammo -> change weapon
if (m_iShells<=1) { SelectNewWeapon(); }
} else {
ASSERTALWAYS("DoubleShotgun - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
// ***************** FIRE TOMMYGUN *****************
TommyGunStart() {
m_iBulletsOnFireStart = m_iBullets;
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f); // fire
PlaySound(pl.m_soWeapon0, SOUND_TOMMYGUN_FIRE, SOF_LOOP|SOF_3D|SOF_VOLUMETRIC);
PlayLightAnim(LIGHT_ANIM_TOMMYGUN, AOF_LOOPING);
GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRESHORT, AOF_LOOPING);
return EEnd();
};
TommyGunStop() {
// smoke
CPlayer &pl = (CPlayer&)*m_penPlayer;
if( pl.m_pstState!=PST_DIVE && hud_bShowWeapon)
{
INDEX ctBulletsFired = ClampUp(m_iBulletsOnFireStart-m_iBullets, INDEX(100));
for( INDEX iSmoke=0; iSmoke<ctBulletsFired/6.0; iSmoke++)
{
ShellLaunchData *psldSmoke = &pl.m_asldData[pl.m_iFirstEmptySLD];
CPlacement3D plPipe;
CalcWeaponPosition(FLOAT3D(afTommygunPipe[0], afTommygunPipe[1], afTommygunPipe[2]), plPipe, FALSE);
FLOATmatrix3D m;
MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle);
psldSmoke->sld_vPos = plPipe.pl_PositionVector+pl.en_vCurrentTranslationAbsolute*iSmoke*_pTimer->TickQuantum;
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
psldSmoke->sld_vUp = vUp;
psldSmoke->sld_tmLaunch = _pTimer->CurrentTick()+iSmoke*_pTimer->TickQuantum;
psldSmoke->sld_estType = ESL_BULLET_SMOKE;
psldSmoke->sld_fSize = 0.5f+ctBulletsFired/75.0f;
FLOAT3D vSpeedRelative = FLOAT3D(-0.06f, 0.0f, -0.06f);
psldSmoke->sld_vSpeed = vSpeedRelative*m+pl.en_vCurrentTranslationAbsolute;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f); // mute fire
PlayLightAnim(LIGHT_ANIM_NONE, 0);
GetAnimator()->FireAnimationOff();
jump Idle();
};
FireTommyGun() {
// fire one bullet
if (m_iBullets>0) {
FireMachineBullet(wpn_fFX[WEAPON_TOMMYGUN], wpn_fFY[WEAPON_TOMMYGUN],
500.0f, 10.0f, ((GetSP()->sp_bCooperative) ? 0.01f : 0.03f),
((GetSP()->sp_bCooperative) ? 0.5f : 0.0f));
SpawnRangeSound(50.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Tommygun_fire");}
DecAmmo(m_iBullets, 1);
SetFlare(0, FLARE_ADD);
m_moWeapon.PlayAnim(TOMMYGUN_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART);
// firing FX
CPlacement3D plShell;
CalcWeaponPosition(FLOAT3D(afTommygunShellPos[0], afTommygunShellPos[1], afTommygunShellPos[2]), plShell, FALSE);
FLOATmatrix3D mRot;
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
if( hud_bShowWeapon)
{
// empty bullet shell
CPlayer &pl = *GetPlayer();
ShellLaunchData &sld = pl.m_asldData[pl.m_iFirstEmptySLD];
sld.sld_vPos = plShell.pl_PositionVector;
FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f);
const FLOATmatrix3D &m = pl.GetRotationMatrix();
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sld.sld_vUp = vUp;
sld.sld_vSpeed = vSpeedRelative*mRot;
sld.sld_tmLaunch = _pTimer->CurrentTick();
sld.sld_estType = ESL_BULLET;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
// bubble
if( pl.m_pstState==PST_DIVE)
{
ShellLaunchData &sldBubble = pl.m_asldData[pl.m_iFirstEmptySLD];
CalcWeaponPosition(FLOAT3D(afTommygunShellPos[0], afTommygunShellPos[1], afTommygunShellPos[2]), plShell, FALSE);
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
sldBubble.sld_vPos = plShell.pl_PositionVector;
sldBubble.sld_vUp = vUp;
sldBubble.sld_tmLaunch = _pTimer->CurrentTick();
sldBubble.sld_estType = ESL_BUBBLE;
vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f);
sldBubble.sld_vSpeed = vSpeedRelative*mRot;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
autowait(0.1f);
// no ammo -> change weapon
if (m_iBullets<=0) { SelectNewWeapon(); }
} else {
ASSERTALWAYS("TommyGun - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
// ***************** FIRE SNIPER *****************
FireSniper() {
if (m_iSniperBullets>0) {
// fire one bullet
if (m_bSniping) {
FireSniperBullet(0.0f, 0.0f, 1500.0f,
(GetSP()->sp_bCooperative) ? 300.0f : 90.0f, 0.0f);
}
else {
FireSniperBullet(wpn_fFX[WEAPON_SNIPER], wpn_fFY[WEAPON_SNIPER], 1000.0f,
(GetSP()->sp_bCooperative) ? 75.0f : 30.0f, 5.0f);
}
m_tmLastSniperFire = _pTimer->CurrentTick();
SpawnRangeSound(50.0f);
DecAmmo(m_iSniperBullets, 1);
if (!m_bSniping) {
SetFlare(0, FLARE_ADD);
}
PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
if (GetSP()->sp_bCooperative) {
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f);
} else if (TRUE) {
pl.m_soWeapon0.Set3DParameters(250.0f, 75.0f, 1.5f, 1.0f);
}
PlaySound(pl.m_soWeapon0, SOUND_SNIPER_FIRE, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("SniperFire");}
// animation
m_moWeapon.PlayAnim(SNIPER_ANIM_FIRE, 0);
autowait(1.0f);
// firing FX
CPlacement3D plShell;
CalcWeaponPosition(FLOAT3D(afSniperShellPos[0], afSniperShellPos[1], afSniperShellPos[2]), plShell, FALSE);
FLOATmatrix3D mRot;
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
if( hud_bShowWeapon)
{
CPlayer *penPlayer = GetPlayer();
ShellLaunchData &sld = penPlayer->m_asldData[penPlayer->m_iFirstEmptySLD];
sld.sld_vPos = plShell.pl_PositionVector;
FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f);
sld.sld_vSpeed = vSpeedRelative*mRot;
const FLOATmatrix3D &m = penPlayer->GetRotationMatrix();
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sld.sld_vUp = vUp;
sld.sld_tmLaunch = _pTimer->CurrentTick();
sld.sld_estType = ESL_BULLET;
// move to next shell position
penPlayer->m_iFirstEmptySLD = (penPlayer->m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
// bubble
if( penPlayer->m_pstState==PST_DIVE)
{
ShellLaunchData &sldBubble = penPlayer->m_asldData[penPlayer->m_iFirstEmptySLD];
CalcWeaponPosition(FLOAT3D(afTommygunShellPos[0], afTommygunShellPos[1], afTommygunShellPos[2]), plShell, FALSE);
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
sldBubble.sld_vPos = plShell.pl_PositionVector;
sldBubble.sld_vUp = vUp;
sldBubble.sld_tmLaunch = _pTimer->CurrentTick();
sldBubble.sld_estType = ESL_BUBBLE;
vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f);
sldBubble.sld_vSpeed = vSpeedRelative*mRot;
penPlayer->m_iFirstEmptySLD = (penPlayer->m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
autowait(1.35f - 1.0f);
// no ammo -> change weapon
if (m_iSniperBullets<=0) { SelectNewWeapon(); }
}
else {
ASSERTALWAYS("Sniper - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
// ***************** FIRE MINIGUN *****************
MiniGunSpinUp() {
// steady anim
m_moWeapon.PlayAnim(MINIGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART);
// no boring animation
((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_fLastActionTime = _pTimer->CurrentTick();
// clear last lerped bullet position
m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f);
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds
// initialize sound 3D parameters
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 2.0f, 1.0f); // fire
pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); // spinup/spindown/spin
pl.m_soWeapon2.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); // turn on/off click
// spin start sounds
PlaySound(pl.m_soWeapon2, SOUND_MINIGUN_CLICK, SOF_3D|SOF_VOLUMETRIC);
PlaySound(pl.m_soWeapon1, SOUND_MINIGUN_SPINUP, SOF_3D|SOF_VOLUMETRIC);
//pl.m_soWeapon1.SetOffset((m_aMiniGunSpeed/MINIGUN_FULLSPEED)*MINIGUN_SPINUPSOUND);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_rotateup");}
// while not at full speed and fire is held
while (m_aMiniGunSpeed<MINIGUN_FULLSPEED && HoldingFire()) {
// every tick
autowait(MINIGUN_TICKTIME);
// increase speed
m_aMiniGunLast = m_aMiniGun;
m_aMiniGun+=m_aMiniGunSpeed*MINIGUN_TICKTIME;
m_aMiniGunSpeed+=MINIGUN_SPINUPACC*MINIGUN_TICKTIME;
}
// do not go over full speed
m_aMiniGunSpeed = ClampUp( m_aMiniGunSpeed, MINIGUN_FULLSPEED);
// if not holding fire anymore
if (!HoldingFire()) {
// start spindown
jump MiniGunSpinDown();
}
// start firing
jump MiniGunFire();
}
MiniGunFire() {
// spinning sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon1, SOUND_MINIGUN_ROTATE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_rotate");}
// if firing
if(HoldingFire() && m_iBullets>0) {
// play fire sound
PlaySound(pl.m_soWeapon0, SOUND_MINIGUN_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC);
PlayLightAnim(LIGHT_ANIM_TOMMYGUN, AOF_LOOPING);
GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRESHORT, AOF_LOOPING);
}
m_iBulletsOnFireStart = m_iBullets;
// while holding fire
while (HoldingFire()) {
// check for ammo pickup during empty spinning
if (!m_bHasAmmo && m_iBullets>0) {
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_MINIGUN_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_fire");}
PlayLightAnim(LIGHT_ANIM_TOMMYGUN, AOF_LOOPING);
GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRESHORT, AOF_LOOPING);
m_bHasAmmo = TRUE;
}
// if has ammo
if (m_iBullets>0) {
// fire a bullet
FireMachineBullet(wpn_fFX[WEAPON_MINIGUN], wpn_fFY[WEAPON_MINIGUN],
750.0f, 10.0f, (GetSP()->sp_bCooperative) ? 0.01f : 0.03f,
( (GetSP()->sp_bCooperative) ? 0.5f : 0.0f));
DoRecoil();
SpawnRangeSound(60.0f);
DecAmmo(m_iBullets, 1);
SetFlare(0, FLARE_ADD);
/* add one empty bullet shell */
CPlacement3D plShell;
// if 1st person view
CPlayer &pl = (CPlayer&)*m_penPlayer;
if(pl.m_penCamera==NULL && pl.m_pen3rdPersonView==NULL)
{
CalcWeaponPosition(FLOAT3D(afMinigunShellPos[0], afMinigunShellPos[1], afMinigunShellPos[2]), plShell, FALSE);
}
// if 3rd person view
else
{
/*CalcWeaponPosition3rdPersonView(FLOAT3D(tmp_af[0], tmp_af[1], tmp_af[2]), plShell, FALSE);*/
CalcWeaponPosition3rdPersonView(FLOAT3D(afMinigunShellPos3rdView[0],
afMinigunShellPos3rdView[1], afMinigunShellPos3rdView[2]), plShell, FALSE);
}
FLOATmatrix3D mRot;
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
if( hud_bShowWeapon)
{
CPlayer &pl = *GetPlayer();
ShellLaunchData &sld = pl.m_asldData[pl.m_iFirstEmptySLD];
sld.sld_vPos = plShell.pl_PositionVector;
FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f);
const FLOATmatrix3D &m = pl.GetRotationMatrix();
FLOAT3D vUp( m(1,2), m(2,2), m(3,2));
sld.sld_vUp = vUp;
sld.sld_vSpeed = vSpeedRelative*mRot;
sld.sld_tmLaunch = _pTimer->CurrentTick();
sld.sld_estType = ESL_BULLET;
// move to next shell position
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
// bubble
if( pl.m_pstState==PST_DIVE)
{
ShellLaunchData &sldBubble = pl.m_asldData[pl.m_iFirstEmptySLD];
CalcWeaponPosition(FLOAT3D(afMinigunShellPos[0], afMinigunShellPos[1], afMinigunShellPos[2]), plShell, FALSE);
MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle);
sldBubble.sld_vPos = plShell.pl_PositionVector;
sldBubble.sld_vUp = vUp;
sldBubble.sld_tmLaunch = _pTimer->CurrentTick();
sldBubble.sld_estType = ESL_BUBBLE;
vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f);
sldBubble.sld_vSpeed = vSpeedRelative*mRot;
pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS;
}
}
// if no ammo
} else {
if( m_bHasAmmo)
{
MinigunSmoke();
}
// stop fire sound
m_bHasAmmo = FALSE;
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds
PlayLightAnim(LIGHT_ANIM_NONE, AOF_LOOPING);
GetAnimator()->FireAnimationOff();
}
autowait(MINIGUN_TICKTIME);
// spin
m_aMiniGunLast = m_aMiniGun;
m_aMiniGun+=m_aMiniGunSpeed*MINIGUN_TICKTIME;
}
if( m_bHasAmmo)
{
MinigunSmoke();
}
GetAnimator()->FireAnimationOff();
// stop fire sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f); // mute fire
PlayLightAnim(LIGHT_ANIM_NONE, AOF_LOOPING);
// start spin down
jump MiniGunSpinDown();
}
MiniGunSpinDown() {
CPlayer &pl = (CPlayer&)*m_penPlayer;
// spin down sounds
PlaySound(pl.m_soWeapon3, SOUND_MINIGUN_CLICK, SOF_3D|SOF_VOLUMETRIC);
PlaySound(pl.m_soWeapon1, SOUND_MINIGUN_SPINDOWN, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("Minigun_rotate");}
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_rotatedown");}
//pl.m_soWeapon1.SetOffset((1-m_aMiniGunSpeed/MINIGUN_FULLSPEED)*MINIGUN_SPINDNSOUND);
// while still spinning and should not fire
while ( m_aMiniGunSpeed>0 && (!HoldingFire() || m_iBullets<=0)) {
autowait(MINIGUN_TICKTIME);
// spin
m_aMiniGunLast = m_aMiniGun;
m_aMiniGun+=m_aMiniGunSpeed*MINIGUN_TICKTIME;
m_aMiniGunSpeed-=MINIGUN_SPINDNACC*MINIGUN_TICKTIME;
if (m_iBullets<=0) {
SelectNewWeapon();
}
// if weapon should be changed
if (m_bChangeWeapon) {
// stop spinning immediately
m_aMiniGunSpeed = 0.0f;
m_aMiniGunLast = m_aMiniGun;
GetAnimator()->FireAnimationOff();
jump Idle();
}
}
// clamp some
m_aMiniGunSpeed = ClampDn( m_aMiniGunSpeed, 0.0f);
m_aMiniGunLast = m_aMiniGun;
// if should fire
if (HoldingFire() && m_iBullets>0) {
// start spinup
jump MiniGunSpinUp();
}
// no boring animation
((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_fLastActionTime = _pTimer->CurrentTick();
// if out of ammo
if (m_iBullets<=0) {
// can wait without changing while holding fire - specific for movie sequence
while(HoldingFire() && m_iBullets<=0) {
autowait(0.1f);
}
if (m_iBullets<=0) {
// select new weapon
SelectNewWeapon();
}
}
jump Idle();
};
// ***************** FIRE ROCKETLAUNCHER *****************
FireRocketLauncher() {
// fire one grenade
if (m_iRockets>0) {
GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0);
m_moWeapon.PlayAnim(ROCKETLAUNCHER_ANIM_FIRE, 0);
FireRocket();
DoRecoil();
SpawnRangeSound(20.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Rocketlauncher_fire");}
DecAmmo(m_iRockets, 1);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
if( pl.m_soWeapon0.IsPlaying())
{
PlaySound(pl.m_soWeapon1, SOUND_ROCKETLAUNCHER_FIRE, SOF_3D|SOF_VOLUMETRIC);
}
else
{
PlaySound(pl.m_soWeapon0, SOUND_ROCKETLAUNCHER_FIRE, SOF_3D|SOF_VOLUMETRIC);
}
autowait(0.05f);
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(ROCKETLAUNCHER_ATTACHMENT_ROCKET1)->amo_moModelObject);
pmo->StretchModel(FLOAT3D(0, 0, 0));
autowait(m_moWeapon.GetAnimLength(ROCKETLAUNCHER_ANIM_FIRE)-0.05f);
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(ROCKETLAUNCHER_ATTACHMENT_ROCKET1)->amo_moModelObject);
pmo->StretchModel(FLOAT3D(1, 1, 1));
// no ammo -> change weapon
if (m_iRockets<=0) { SelectNewWeapon(); }
} else {
ASSERTALWAYS("RocketLauncher - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
// ***************** FIRE GRENADELAUNCHER *****************
FireGrenadeLauncher()
{
TM_START = _pTimer->CurrentTick();
// remember time for spring release
F_TEMP = _pTimer->CurrentTick();
F_OFFSET_CHG = 0.0f;
m_fWeaponDrawPower = 0.0f;
m_tmDrawStartTime = _pTimer->CurrentTick();
while (HoldingFire() && ((_pTimer->CurrentTick()-TM_START)<0.75f) )
{
autowait(_pTimer->TickQuantum);
INDEX iPower = INDEX((_pTimer->CurrentTick()-TM_START)/_pTimer->TickQuantum);
F_OFFSET_CHG = 0.125f/(iPower+2);
m_fWeaponDrawPowerOld = m_fWeaponDrawPower;
m_fWeaponDrawPower += F_OFFSET_CHG;
}
m_tmDrawStartTime = 0.0f;
// release spring and fire one grenade
if (m_iGrenades>0)
{
// fire grenade
INDEX iPower = INDEX((_pTimer->CurrentTick()-F_TEMP)/_pTimer->TickQuantum);
FireGrenade( iPower);
SpawnRangeSound(10.0f);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Gnadelauncher");}
DecAmmo(m_iGrenades, 1);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_GRENADELAUNCHER_FIRE, SOF_3D|SOF_VOLUMETRIC);
GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0);
// release spring
TM_START = _pTimer->CurrentTick();
m_fWeaponDrawPowerOld = m_fWeaponDrawPower;
while (m_fWeaponDrawPower>0.0f)
{
autowait(_pTimer->TickQuantum);
m_fWeaponDrawPowerOld = m_fWeaponDrawPower;
m_fWeaponDrawPower -= F_OFFSET_CHG;
m_fWeaponDrawPower = ClampDn( m_fWeaponDrawPower, 0.0f);
F_OFFSET_CHG = F_OFFSET_CHG*10;
}
// reset moving part's offset
ResetWeaponMovingOffset();
// no ammo -> change weapon
if (m_iGrenades<=0)
{
SelectNewWeapon();
}
else if( TRUE)
{
autowait(0.25f);
}
} else {
ASSERTALWAYS("GrenadeLauncher - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
/*
// ***************** FIRE PIPEBOMB *****************
FirePipeBomb() {
// drop one pipebomb
if (m_iGrenades>=0) {
// fire bomb
if (m_bPipeBombDropped) {
m_bPipeBombDropped = FALSE;
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKFIRE, 0);
autowait(0.35f);
// activate pipebomb
SendToTarget(m_penPipebomb, EET_START);
m_penPipebomb = NULL;
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_PIPEBOMB_FIRE, SOF_3D|SOF_VOLUMETRIC);
// no ammo -> change weapon
if (m_iGrenades<=0) {
autowait(m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_STICKFIRE)-0.35f);
SelectNewWeapon();
return EEnd();
}
// get new bomb
AddAttachmentToModel(this, m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB, MODEL_PB_BOMB,
TEXTURE_PB_BOMB, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_ACTIVATE, 0);
autowait(m_moWeapon.GetAnimLength(HANDWITHBOMB_ANIM_ACTIVATE));
// drop bomb
} else if (TRUE) {
m_bPipeBombDropped = TRUE;
// low drop
if (((CPlayer&)*m_penPlayer).en_plViewpoint.pl_OrientationAngle(2) < -20.0f) {
m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_BOMBTHROW1 ,0);
// high drop
} else {
m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_BOMBTHROW2 ,0);
}
autowait(0.5f);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon1, SOUND_PIPEBOMB_THROW, SOF_3D|SOF_VOLUMETRIC);
SpawnRangeSound(5.0f);
autowait(0.2f);
// drop bomb
DropPipebomb();
DecAmmo(m_iGrenades, 1);
RemoveAttachmentFromModel(m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB);
autowait(0.2f);
// open stick shield
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKTHROW ,0);
// sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon2, SOUND_PIPEBOMB_OPEN, SOF_3D|SOF_VOLUMETRIC);
autowait(m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_STICKTHROW));
}
} else {
ASSERTALWAYS("Pipebomb - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
ReloadPipeBomb() {
if (m_bPipeBombDropped) {
m_bPipeBombDropped = FALSE;
// close stick
m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKRETURN, 0);
// get new bomb
AddAttachmentToModel(this, m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB, MODEL_PB_BOMB,
TEXTURE_PB_BOMB, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0);
m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_ACTIVATE, 0);
autowait(m_moWeapon.GetAnimLength(HANDWITHBOMB_ANIM_ACTIVATE));
}
return EEnd();
};*/
// ***************** FIRE FLAMER *****************
FlamerStart() {
m_tmFlamerStart=_pTimer->CurrentTick();
m_tmFlamerStop=1e9;
m_moWeapon.PlayAnim(FLAMER_ANIM_FIRESTART, 0);
autowait(m_moWeapon.GetAnimLength(FLAMER_ANIM_FIRESTART));
// play fire sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 2.0f, 0.31f);
pl.m_soWeapon2.Set3DParameters(50.0f, 5.0f, 2.0f, 0.3f);
PlaySound(pl.m_soWeapon0, SOUND_FL_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("FlamethrowerFire");}
PlaySound(pl.m_soWeapon2, SOUND_FL_START, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("FlamethrowerStart");}
FireFlame();
DecAmmo(m_iNapalm, 1);
autowait(0.05f);
jump FlamerFire();
};
FlamerFire() {
// while holding fire
while (HoldingFire() && m_iNapalm>0) {
// fire
FireFlame();
DecAmmo(m_iNapalm, 1);
SpawnRangeSound(30.0f);
autowait(0.1f);
}
if (m_iNapalm<=0) {
m_bHasAmmo = FALSE;
}
jump FlamerStop();
};
FlamerStop() {
m_tmFlamerStop=_pTimer->CurrentTick();
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_FL_STOP, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("FlamethrowerFire");}
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("FlamethrowerStop");}
//PlaySound(pl.m_soWeapon1, SOUND_FL_STOP, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
FireFlame();
// link last flame with nothing (if not NULL or deleted)
if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
((CProjectile&)*m_penFlame).m_penParticles = NULL;
m_penFlame = NULL;
}
m_moWeapon.PlayAnim(FLAMER_ANIM_FIREEND, 0);
autowait(m_moWeapon.GetAnimLength(FLAMER_ANIM_FIREEND));
if (m_iNapalm<=0) {
// select new weapon
SelectNewWeapon();
}
jump Idle();
};
// ***************** FIRE CHAINSAW *****************
ChainsawFire() {
CPlayer &pl = (CPlayer&)*m_penPlayer;
// set the firing sound level
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f);
PlaySound(pl.m_soWeapon0, SOUND_CS_BEGINFIRE, SOF_3D|SOF_VOLUMETRIC);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawBeginFire");}
// bring the chainsaw down to cutting height (fire position)
m_moWeapon.PlayAnim(CHAINSAW_ANIM_WAIT2FIRE, 0);
autowait(m_moWeapon.GetAnimLength(CHAINSAW_ANIM_WAIT2FIRE)-0.05f);
CPlayerAnimator &pa=*GetAnimator();
pa.FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0);
CModelObject *pmoTeeth=GetChainSawTeeth();
if( pmoTeeth!=NULL)
{
pmoTeeth->PlayAnim(TEETH_ANIM_ROTATE, AOF_LOOPING|AOF_NORESTART);
}
// firing
CPlayer &pl = (CPlayer&)*m_penPlayer;
// mute the chainsaw engine sound
pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 0.5f, 1.0f);
PlaySound(pl.m_soWeapon0, SOUND_CS_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("ChainsawIdle");}
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawFire");}
m_moWeapon.PlayAnim(CHAINSAW_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART);
// start teeth rotation
CModelObject *pmo1 = &(m_moWeapon.GetAttachmentModel(CHAINSAW_ATTACHMENT_BLADE)->amo_moModelObject);
CModelObject *pmo2 = &(pmo1->GetAttachmentModel(BLADE_ATTACHMENT_TEETH)->amo_moModelObject);
pmo2->PlayAnim(TEETH_ANIM_ROTATE, AOF_LOOPING);
while (HoldingFire())// && m_iNapalm>0)
{
autowait(CHAINSAW_UPDATETIME);
// 200 damage per second
CutWithChainsaw(0, 0, 3.0f, 2.0f, 1.0f,
((GetSP()->sp_bCooperative) ? 200.0f : 250.0f)*CHAINSAW_UPDATETIME);
//DecAmmo(m_iNapalm, 1);
}
// bring it back to idle position
CPlayer &pl = (CPlayer&)*m_penPlayer;
PlaySound(pl.m_soWeapon0, SOUND_CS_ENDFIRE, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("ChainsawFire");}
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawEnd");}
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawIdle");}
// PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC/*|SOF_SMOOTHCHANGE*/);
// restore volume to engine sound
pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 1.0f, 1.0f);
m_moWeapon.PlayAnim(CHAINSAW_ANIM_FIRE2WAIT, 0);
autowait(m_moWeapon.GetAnimLength(CHAINSAW_ANIM_FIRE2WAIT));
// stop teeth rotation
CModelObject *pmo1 = &(m_moWeapon.GetAttachmentModel(CHAINSAW_ATTACHMENT_BLADE)->amo_moModelObject);
CModelObject *pmo2 = &(pmo1->GetAttachmentModel(BLADE_ATTACHMENT_TEETH)->amo_moModelObject);
pmo2->PlayAnim(TEETH_ANIM_DEFAULT, 0);
CModelObject *pmoTeeth=GetChainSawTeeth();
if( pmoTeeth!=NULL)
{
pmoTeeth->PlayAnim(TEETH_ANIM_DEFAULT, 0);
}
jump Idle();
};
ChainsawBringUp()
{
// bring it back to idle position
m_moWeapon.PlayAnim(CHAINSAW_ANIM_FIRE2WAIT, 0);
autowait(m_moWeapon.GetAnimLength(CHAINSAW_ANIM_FIRE2WAIT));
jump Idle();
}
// ***************** FIRE LASER *****************
FireLaser() {
// fire one cell
if (m_iElectricity>0) {
autowait(0.1f);
m_moWeapon.PlayAnim(LASER_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART);
FireLaserRay();
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Laser_fire");}
DecAmmo(m_iElectricity, 1);
// sound
SpawnRangeSound(20.0f);
CPlayer &pl = (CPlayer&)*m_penPlayer;
// activate barrel anim
switch(m_iLaserBarrel) {
case 0: { // barrel lu
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_LEFTUP)->amo_moModelObject);
pmo->PlayAnim(BARREL_ANIM_FIRE, 0);
PlaySound(pl.m_soWeapon0, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC);
break; }
case 3: { // barrel rd
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_RIGHTDOWN)->amo_moModelObject);
pmo->PlayAnim(BARREL_ANIM_FIRE, 0);
PlaySound(pl.m_soWeapon1, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC);
break; }
case 1: { // barrel ld
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_LEFTDOWN)->amo_moModelObject);
pmo->PlayAnim(BARREL_ANIM_FIRE, 0);
PlaySound(pl.m_soWeapon2, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC);
break; }
case 2: { // barrel ru
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_RIGHTUP)->amo_moModelObject);
pmo->PlayAnim(BARREL_ANIM_FIRE, 0);
PlaySound(pl.m_soWeapon3, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC);
break; }
}
// next barrel
m_iLaserBarrel = (m_iLaserBarrel+1)&3;
// no electricity -> change weapon
if (m_iElectricity<=0) { SelectNewWeapon(); }
} else {
ASSERTALWAYS("Laser - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
/*
// ***************** FIRE GHOSTBUSTER *****************
GhostBusterStart() {
GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRESHORT, AOF_LOOPING);
// create ray
m_penGhostBusterRay = CreateEntity(GetPlacement(), CLASS_GHOSTBUSTERRAY);
EGhostBusterRay egbr;
egbr.penOwner = this;
m_penGhostBusterRay->Initialize(egbr);
// play anim
m_moWeapon.PlayAnim(GHOSTBUSTER_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART);
// play fire sound
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); // fire
PlaySound(pl.m_soWeapon0, SOUND_GB_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC);
return EEnd();
};
GhostBusterStop() {
GetAnimator()->FireAnimationOff();
// destroy ray
((CGhostBusterRay&)*m_penGhostBusterRay).DestroyGhostBusterRay();
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeapon0.Stop();
jump Idle();
};
FireGhostBuster() {
// fire one cell
if (m_iElectricity>0) {
FireGhostBusterRay();
DecAmmo(m_iElectricity, 1);
SpawnRangeSound(20.0f);
autowait(0.05f);
// no napalm -> change weapon
if (m_iElectricity<=0) { SelectNewWeapon(); }
} else {
ASSERTALWAYS("GhostBuster - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
return EEnd();
};
*/
// ***************** FIRE CANNON *****************
CannonFireStart()
{
m_tmDrawStartTime = _pTimer->CurrentTick();
TM_START = _pTimer->CurrentTick();
F_OFFSET_CHG = 0.0f;
m_fWeaponDrawPower = 0.0f;
CPlayer &pl = (CPlayer&)*m_penPlayer;
if( m_iIronBalls&1)
{
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 3.0f, 1.0f);
PlaySound(pl.m_soWeapon0, SOUND_CANNON_PREPARE, SOF_3D|SOF_VOLUMETRIC);
}
else
{
pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 3.0f, 1.0f);
PlaySound(pl.m_soWeapon1, SOUND_CANNON_PREPARE, SOF_3D|SOF_VOLUMETRIC);
}
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Canon_prepare");}
while (HoldingFire() && ((_pTimer->CurrentTick()-TM_START)<1.0f) )
{
autowait(_pTimer->TickQuantum);
INDEX iPower = INDEX((_pTimer->CurrentTick()-TM_START)/_pTimer->TickQuantum);
F_OFFSET_CHG = 0.25f/(iPower+2);
m_fWeaponDrawPowerOld = m_fWeaponDrawPower;
m_fWeaponDrawPower += F_OFFSET_CHG;
}
m_tmDrawStartTime = 0.0f;
CPlayer &pl = (CPlayer&)*m_penPlayer;
if( m_iIronBalls&1)
{
// turn off the sound
pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f);
}
else
{
// turn off the sound
pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f);
}
// fire one ball
if ( ((m_iIronBalls>0) && (m_iCurrentWeapon == WEAPON_IRONCANNON)) )
{
INDEX iPower = INDEX((_pTimer->CurrentTick()-TM_START)/_pTimer->TickQuantum);
GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0);
FLOAT fRange, fFalloff;
if (GetSP()->sp_bCooperative) {
fRange = 100.0f;
fFalloff = 25.0f;
} else if (TRUE) {
fRange = 150.0f;
fFalloff = 30.0f;
}
// adjust volume of cannon firing acording to launch power
if( m_iIronBalls&1)
{
pl.m_soWeapon2.Set3DParameters(fRange, fFalloff, 2.0f+iPower*0.05f, 1.0f);
PlaySound(pl.m_soWeapon2, SOUND_CANNON, SOF_3D|SOF_VOLUMETRIC);
}
else
{
pl.m_soWeapon3.Set3DParameters(fRange, fFalloff, 2.0f+iPower*0.05f, 1.0f);
PlaySound(pl.m_soWeapon3, SOUND_CANNON, SOF_3D|SOF_VOLUMETRIC);
}
m_moWeapon.PlayAnim(CANNON_ANIM_FIRE, 0);
FireCannonBall( iPower);
if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Canon");}
DecAmmo(m_iIronBalls, 1);
SpawnRangeSound(30.0f);
TM_START = _pTimer->CurrentTick();
m_fWeaponDrawPowerOld = m_fWeaponDrawPower;
while (m_fWeaponDrawPower>0.0f ||
((_pTimer->CurrentTick()-TM_START)<m_moWeapon.GetAnimLength(CANNON_ANIM_FIRE)) )
{
autowait(_pTimer->TickQuantum);
m_fWeaponDrawPowerOld = m_fWeaponDrawPower;
m_fWeaponDrawPower -= F_OFFSET_CHG;
m_fWeaponDrawPower = ClampDn( m_fWeaponDrawPower, 0.0f);
F_OFFSET_CHG = F_OFFSET_CHG*2;
}
// reset moving part's offset
ResetWeaponMovingOffset();
// no cannon balls -> change weapon
if ( ((m_iIronBalls<=0) && (m_iCurrentWeapon == WEAPON_IRONCANNON) ) /*||
((m_iNukeBalls<=0) && (m_iCurrentWeapon == WEAPON_NUKECANNON) ) */)
{
SelectNewWeapon();
}
}
else
{
ASSERTALWAYS("Cannon - Auto weapon change not working.");
m_bFireWeapon = m_bHasAmmo = FALSE;
}
jump Idle();
};
/*
* >>>--- RELOAD WEAPON ---<<<
*/
Reload() {
m_bReloadWeapon = FALSE;
// reload
if (m_iCurrentWeapon == WEAPON_COLT) {
autocall ReloadColt() EEnd;
} else if (m_iCurrentWeapon == WEAPON_DOUBLECOLT) {
autocall ReloadDoubleColt() EEnd;
/* } else if (m_iCurrentWeapon == WEAPON_PIPEBOMB) {
autocall ReloadPipeBomb() EEnd;*/
}
jump Idle();
};
/*
* >>>--- KNIFE STAND CHANGE ---<<<
*/
ChangeKnifeStand(EVoid) {
/* if (m_iKnifeStand==1) {
// change from knife stand 1 to stand 3
m_moWeapon.PlayAnim(KNIFE_ANIM_STAND1TOSTAND3, 0);
autowait(m_moWeapon.GetAnimLength(KNIFE_ANIM_STAND1TOSTAND3));
m_iKnifeStand = 3;
} else if (m_iKnifeStand==3) {
// change from knife stand 3 to stand 1
m_moWeapon.PlayAnim(KNIFE_ANIM_STAND3TOSTAND1, 0);
autowait(m_moWeapon.GetAnimLength(KNIFE_ANIM_STAND3TOSTAND1));
m_iKnifeStand = 1;
}
*/
return EEnd();
};
ChangeToIronCannon(EVoid)
{
/* CModelObject &moLight = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_LIGHT)->amo_moModelObject;
moLight.PlayAnim( LIGHT_ANIM_DOWN, 0);
autowait(moLight.GetAnimLength(LIGHT_ANIM_DOWN));
CModelObject &moNukeBox = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_NUKEBOX)->amo_moModelObject;
moNukeBox.PlayAnim( NUKEBOX_ANIM_CLOSE, 0);
autowait(moNukeBox.GetAnimLength(NUKEBOX_ANIM_CLOSE));
*/
m_iPreviousWeapon = m_iCurrentWeapon;
m_iCurrentWeapon = WEAPON_IRONCANNON;
m_iWantedWeapon = m_iCurrentWeapon;
return EEnd();
}
/* ChangeToNukeCannon(EVoid)
{
CModelObject &moNukeBox = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_NUKEBOX)->amo_moModelObject;
moNukeBox.PlayAnim( NUKEBOX_ANIM_OPEN, 0);
autowait(moNukeBox.GetAnimLength(NUKEBOX_ANIM_OPEN));
CModelObject &moLight = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_LIGHT)->amo_moModelObject;
moLight.PlayAnim( LIGHT_ANIM_UP, 0);
autowait(moLight.GetAnimLength(LIGHT_ANIM_UP));
m_iPreviousWeapon = m_iCurrentWeapon;
m_iCurrentWeapon = WEAPON_NUKECANNON;
m_iWantedWeapon = m_iCurrentWeapon;
return EEnd();
};
*/
/*
* >>>--- BORING WEAPON ANIMATION ---<<<
*/
BoringWeaponAnimation() {
// select new mode change animation
FLOAT fWait = 0.0f;
switch (m_iCurrentWeapon) {
case WEAPON_KNIFE: fWait = KnifeBoring(); break;
case WEAPON_COLT: fWait = ColtBoring(); break;
case WEAPON_DOUBLECOLT: fWait = DoubleColtBoring(); break;
case WEAPON_SINGLESHOTGUN: fWait = SingleShotgunBoring(); break;
case WEAPON_DOUBLESHOTGUN: fWait = DoubleShotgunBoring(); break;
case WEAPON_TOMMYGUN: fWait = TommyGunBoring(); break;
case WEAPON_SNIPER: fWait = SniperBoring(); break;
case WEAPON_MINIGUN: fWait = MiniGunBoring(); break;
case WEAPON_ROCKETLAUNCHER: fWait = RocketLauncherBoring(); break;
case WEAPON_GRENADELAUNCHER: fWait = GrenadeLauncherBoring(); break;
case WEAPON_FLAMER: fWait = FlamerBoring(); break;
case WEAPON_CHAINSAW: fWait = ChainsawBoring(); break;
case WEAPON_LASER: fWait = LaserBoring(); break;
case WEAPON_IRONCANNON: fWait = CannonBoring(); break;
default: ASSERTALWAYS("Unknown weapon.");
}
if (fWait > 0.0f) { autowait(fWait); }
return EBegin();
};
/*
* >>>--- NO WEAPON ACTION ---<<<
*/
Idle() {
wait() {
on (EBegin) : {
// play default anim
PlayDefaultAnim();
// weapon changed
if (m_bChangeWeapon) {
jump ChangeWeapon();
}
// fire pressed start firing
if (m_bFireWeapon) {
jump Fire();
}
// reload pressed
if (m_bReloadWeapon) {
jump Reload();
}
resume;
}
// select weapon
on (ESelectWeapon eSelect) : {
// try to change weapon
SelectWeaponChange(eSelect.iWeapon);
if (m_bChangeWeapon) {
jump ChangeWeapon();
}
resume;
}
// fire pressed
on (EFireWeapon) : {
jump Fire();
}
// reload pressed
on (EReloadWeapon) : {
jump Reload();
}
// boring weapon animation
on (EBoringWeapon) : {
call BoringWeaponAnimation();
}
}
};
// weapons wait here while player is dead, so that stupid animations wouldn't play
Stopped()
{
// make sure we restore all rockets if we are holding the rocket launcher
if (m_iCurrentWeapon==WEAPON_ROCKETLAUNCHER) {
CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(ROCKETLAUNCHER_ATTACHMENT_ROCKET1)->amo_moModelObject);
if (pmo) { pmo->StretchModel(FLOAT3D(1, 1, 1)); }
}
// kill all possible sounds, animations, etc
ResetWeaponMovingOffset();
CPlayer &pl = (CPlayer&)*m_penPlayer;
pl.m_soWeapon0.Stop();
pl.m_soWeapon1.Stop();
pl.m_soWeapon2.Stop();
pl.m_soWeapon3.Stop();
PlayLightAnim(LIGHT_ANIM_NONE, 0);
wait() {
// after level change
on (EPostLevelChange) : { return EBegin(); };
on (EStart) : { return EBegin(); };
otherwise() : { resume; };
}
}
/*
* >>>--- M A I N ---<<<
*/
Main(EWeaponsInit eInit) {
// remember the initial parameters
ASSERT(eInit.penOwner!=NULL);
m_penPlayer = eInit.penOwner;
// declare yourself as a void
InitAsVoid();
SetFlags(GetFlags()|ENF_CROSSESLEVELS|ENF_NOTIFYLEVELCHANGE);
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set weapon model for current weapon
SetCurrentWeaponModel();
// play default anim
PlayDefaultAnim();
wait() {
on (EBegin) : { call Idle(); }
on (ESelectWeapon eSelect) : {
// try to change weapon
SelectWeaponChange(eSelect.iWeapon);
resume;
};
// before level change
on (EPreLevelChange) : {
// stop everything
m_bFireWeapon = FALSE;
call Stopped();
resume;
}
on (EFireWeapon) : {
// start firing
m_bFireWeapon = TRUE;
resume;
}
on (EReleaseWeapon) : {
// stop firing
m_bFireWeapon = FALSE;
resume;
}
on (EReloadWeapon) : {
// reload wepon
m_bReloadWeapon = TRUE;
resume;
}
on (EStop) : { call Stopped(); }
on (EEnd) : { stop; }
}
// cease to exist
Destroy();
return;
};
};