mirror of
https://github.com/ENSL/NS.git
synced 2024-11-14 17:01:29 +00:00
3631 lines
120 KiB
C++
3631 lines
120 KiB
C++
//======== (C) Copyright 2001 Charles G. Cleveland All rights reserved. =========
|
|
//
|
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose: AvH event declarations
|
|
//
|
|
// $Workfile: AvHEvents.cpp$
|
|
// $Date: 2002/10/24 21:23:37 $
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
// $Log: AvHEvents.cpp,v $
|
|
// Revision 1.47 2002/10/24 21:23:37 Flayra
|
|
// - Reworked jetpacks
|
|
// - Removed bullet casing from grenade launcher
|
|
//
|
|
// Revision 1.46 2002/10/16 20:52:34 Flayra
|
|
// - Removed weapon upgrade sounds
|
|
// - Fixed acid projectile hitting player
|
|
// - Play HMG firing at full volume
|
|
// - Added paralysis projectile
|
|
// - Fixed spike orientation
|
|
//
|
|
// Revision 1.45 2002/10/16 00:54:44 Flayra
|
|
// - Removed unneeded events
|
|
// - Commented out broken parasite projectile
|
|
// - Added general particle event
|
|
// - Added distress beacon event
|
|
//
|
|
// Revision 1.44 2002/09/25 20:43:53 Flayra
|
|
// - Effects update
|
|
//
|
|
// Revision 1.43 2002/09/23 22:13:38 Flayra
|
|
// - Fixed bug where damage upgrades were applying when they shouldn't (for aliens)
|
|
// - Updated spike effect
|
|
// - Removed jetpack effect until it can be done properly
|
|
// - Lots of sound and effects changes
|
|
//
|
|
// Revision 1.42 2002/09/09 19:50:29 Flayra
|
|
// - Reworking jetpack effects, still needs more work
|
|
//
|
|
// Revision 1.41 2002/08/31 18:01:01 Flayra
|
|
// - Work at VALVe
|
|
//
|
|
// Revision 1.40 2002/08/16 02:34:42 Flayra
|
|
// - Removed ASSERTs when creating temporary entities, it can fail in big firefights
|
|
//
|
|
// Revision 1.39 2002/08/09 00:56:38 Flayra
|
|
// - Added particle system back when phasing in items from commander mode
|
|
//
|
|
// Revision 1.38 2002/08/02 22:00:53 Flayra
|
|
// - Removed old HL events, add correct bullet types for new bullet effects
|
|
//
|
|
// Revision 1.37 2002/07/26 23:04:14 Flayra
|
|
// - Generate numerical feedback for damage events
|
|
//
|
|
// Revision 1.36 2002/07/23 17:02:23 Flayra
|
|
// - Turret velocity is constructed on client in same way as server, instead of being sent across as calculated (network precision issues)
|
|
//
|
|
// Revision 1.35 2002/07/10 14:40:23 Flayra
|
|
// - Added special spike hit effect
|
|
//
|
|
// Revision 1.34 2002/07/08 16:57:19 Flayra
|
|
// - Added "invalid action" event, reworking for random spread for bullet fire
|
|
//
|
|
// Revision 1.33 2002/07/01 22:41:40 Flayra
|
|
// - Removed outdated overwatch target and tension events
|
|
//
|
|
// Revision 1.32 2002/07/01 21:31:49 Flayra
|
|
// - Regular update
|
|
//
|
|
// Revision 1.31 2002/06/25 17:57:15 Flayra
|
|
// - Removed old events, added new events, fixed infinite loop crash in PlayMeleeHitEffects, added parasite projectile
|
|
//
|
|
// Revision 1.30 2002/06/03 16:44:27 Flayra
|
|
// - Moved offense chamber firing into event, fixed duplicate empty sound (now it's an event, not server-side), weapons play view model anim in weapon (not event), started to add grenade event for grenade gun
|
|
//
|
|
// Revision 1.29 2002/05/28 17:36:55 Flayra
|
|
// - Don't play machine gun or pistol sounds louder when upgraded, changed welder from looping sound to periodic sound
|
|
//
|
|
// Revision 1.28 2002/05/23 02:33:42 Flayra
|
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
|
//
|
|
//===============================================================================
|
|
#include "cl_dll/hud.h"
|
|
#include "cl_dll/cl_util.h"
|
|
|
|
//#include "AvHMarineWeapons.h"
|
|
//#include "AvHAlienWeapons.h"
|
|
//#include "AvHAlienAbilities.h"
|
|
|
|
#include "cl_dll/eventscripts.h"
|
|
#include "cl_dll/in_defs.h"
|
|
#include "cl_dll/ev_hldm.h"
|
|
#include "../common/event_api.h"
|
|
#include "../common/event_args.h"
|
|
#include "../common/dlight.h"
|
|
#include "../common/r_efx.h"
|
|
#include "AvHMarineWeaponConstants.h"
|
|
#include "AvHAlienWeaponConstants.h"
|
|
#include "AvHParticleSystemManager.h"
|
|
#include "pm_shared/pm_defs.h"
|
|
#include "AvHSpecials.h"
|
|
#include "AvHEvents.h"
|
|
#include "AvHSelectionHelper.h"
|
|
#include "pm_shared/pm_defs.h"
|
|
#include "AvHPlayerUpgrade.h"
|
|
#include "AvHSharedUtil.h"
|
|
#include "AvHParticleConstants.h"
|
|
#include "AvHMarineEquipmentConstants.h"
|
|
#include "AvHAlienAbilityConstants.h"
|
|
#include "AvHAlienEquipmentConstants.h"
|
|
#include "AvHParticleTemplate.h"
|
|
#include "AvHParticleTemplateClient.h"
|
|
#include "AvHClientVariables.h"
|
|
#include "../util/MathUtil.h"
|
|
#include "AvHHulls.h"
|
|
|
|
//extern AvHKnife gKnife;
|
|
//extern AvHMachineGun gMachineGun;
|
|
//extern AvHPistol gPistol;
|
|
//extern AvHSonicGun gSonicGun;
|
|
//extern AvHHeavyMachineGun gHeavyMachineGun;
|
|
//extern AvHGrenadeGun gGrenadeGun;
|
|
//extern AvHWelder gWelder;
|
|
//extern AvHMine gMine;
|
|
//extern AvHSpitGun gSpitGun;
|
|
//extern AvHClaws gClaws;
|
|
//extern AvHSpore gSpores;
|
|
//extern AvHBite gBite;
|
|
//extern AvHBite2 gBite2;
|
|
//extern AvHSpikeGun gSpikeGun;
|
|
//extern AvHSwipe gSwipe;
|
|
//extern AvHWebSpinner gWebSpinner;
|
|
//extern AvHPrimalScream gPrimalScream;
|
|
//extern AvHParasiteGun gParasite;
|
|
//extern AvHUmbraGun gUmbra;
|
|
//extern AvHBlinkGun gBlink;
|
|
//extern AvHDivineWind gDivineWind;
|
|
//extern AvHParalysisGun gParalysisGun;
|
|
//extern AvHBileBombGun gBileBomb;
|
|
//extern AvHAcidRocketGun gAcidRocket;
|
|
//extern AvHHealingSpray gHealingSpray;
|
|
//extern AvHBabblerGun gBabblerGun;
|
|
|
|
// Alien abilities
|
|
//extern AvHLeap gLeap;
|
|
//extern AvHCharge gCharge;
|
|
|
|
|
|
// The sound constants are stored here, even though it's used on client
|
|
#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch
|
|
#define SND_CHANGE_VOL (1<<6) // duplicated in protocol.h change sound vol
|
|
|
|
void V_PunchAxis( int axis, float punch );
|
|
//extern double gClientTimeLastUpdate;
|
|
void DrawCircleOnGroundAtPoint(vec3_t inOrigin, int inNumSides, int inStartAngle, int inRadius, float inR, float inG, float inB, float inA, bool inUseRedInstead, float inInnerRadius);
|
|
|
|
extern void ComputeGrenadeVelocity(Vector& inForward, Vector& inVelocity, Vector& outVelocity);
|
|
|
|
class LightType
|
|
{
|
|
public:
|
|
LightType(int inIndex, dlight_t* inLight) : mIndex(inIndex), mLight(inLight)
|
|
{}
|
|
|
|
int mIndex;
|
|
dlight_t* mLight;
|
|
};
|
|
|
|
typedef vector<LightType> DLightListType;
|
|
|
|
DLightListType gJetpackLights;
|
|
const float kArbitraryLargeLightTime = 2000.0f;
|
|
//SelectionListType gSelectionList;
|
|
extern playermove_t* pmove;
|
|
/*
|
|
#include "pm_shared/pm_debug.h"
|
|
extern DebugPointListType gTriDebugLocations;
|
|
extern DebugPointListType gSquareDebugLocations;
|
|
extern DebugEntityListType gCubeDebugEntities;
|
|
*/
|
|
AvHSelectionHelper gSelectionHelper;
|
|
extern AvHParticleTemplateListClient gParticleTemplateList;
|
|
|
|
extern const Vector g_vecZero;
|
|
|
|
//
|
|
// Macros to make these things easier, less error-prone and clearer
|
|
//
|
|
#define AVH_DECLARE_EVENT(s) \
|
|
extern "C" \
|
|
{\
|
|
void EV_##s(struct event_args_s *args); \
|
|
}
|
|
|
|
extern "C" Vector gPredictedPlayerOrigin;
|
|
|
|
#define AVH_NAME_TO_EVENT(s) "events/"#s".sc"
|
|
|
|
#define AVH_HOOK_EVENT(s) \
|
|
gEngfuncs.pfnHookEvent(AVH_NAME_TO_EVENT(s), EV_##s)
|
|
|
|
//#define AVH_DEFINE_EVENT(s, Class) \
|
|
//void EV_##s(struct event_args_s *args) \
|
|
//{\
|
|
// static Class theWeapon(AVH_NAME_TO_EVENT(s));
|
|
|
|
//#define AVH_DEFINE_EVENT_END \
|
|
///* TODO: Add cleanup or other default behavior? */ \
|
|
//}
|
|
|
|
//physent_t* GetEntity(int inPhysIndex);
|
|
|
|
//
|
|
// Declare events
|
|
//
|
|
|
|
//// Marine weapon events
|
|
AVH_DECLARE_EVENT(Knife)
|
|
AVH_DECLARE_EVENT(MachineGun)
|
|
AVH_DECLARE_EVENT(Pistol)
|
|
AVH_DECLARE_EVENT(SonicGun)
|
|
AVH_DECLARE_EVENT(HeavyMachineGun)
|
|
AVH_DECLARE_EVENT(GrenadeGun)
|
|
AVH_DECLARE_EVENT(Grenade)
|
|
|
|
// Alien weapon events
|
|
AVH_DECLARE_EVENT(SpitGun)
|
|
AVH_DECLARE_EVENT(OffenseChamber)
|
|
AVH_DECLARE_EVENT(Claws)
|
|
AVH_DECLARE_EVENT(Swipe)
|
|
//AVH_DECLARE_EVENT(EnsnareShoot)
|
|
//AVH_DECLARE_EVENT(EnsnareHit)
|
|
|
|
AVH_DECLARE_EVENT(SporeShoot)
|
|
AVH_DECLARE_EVENT(SporeCloud)
|
|
AVH_DECLARE_EVENT(UmbraGun)
|
|
AVH_DECLARE_EVENT(UmbraCloud)
|
|
|
|
AVH_DECLARE_EVENT(Bite)
|
|
AVH_DECLARE_EVENT(Bite2)
|
|
AVH_DECLARE_EVENT(SpikeGun)
|
|
//AVH_DECLARE_EVENT(LayEgg)
|
|
AVH_DECLARE_EVENT(BuildGun)
|
|
AVH_DECLARE_EVENT(HealingSpray)
|
|
AVH_DECLARE_EVENT(Metabolize)
|
|
AVH_DECLARE_EVENT(MetabolizeSuccess)
|
|
AVH_DECLARE_EVENT(SpinWeb)
|
|
//AVH_DECLARE_EVENT(Babbler)
|
|
AVH_DECLARE_EVENT(PrimalScream)
|
|
AVH_DECLARE_EVENT(Cocoon)
|
|
|
|
AVH_DECLARE_EVENT(Jetpack)
|
|
AVH_DECLARE_EVENT(Welder)
|
|
AVH_DECLARE_EVENT(WelderConst)
|
|
AVH_DECLARE_EVENT(WelderStart)
|
|
AVH_DECLARE_EVENT(WelderEnd)
|
|
//AVH_DECLARE_EVENT(OverwatchStart)
|
|
//AVH_DECLARE_EVENT(OverwatchTarget)
|
|
//AVH_DECLARE_EVENT(OverwatchTension)
|
|
//AVH_DECLARE_EVENT(OverwatchEnd)
|
|
AVH_DECLARE_EVENT(Regeneration)
|
|
AVH_DECLARE_EVENT(StartCloak);
|
|
AVH_DECLARE_EVENT(EndCloak);
|
|
//AVH_DECLARE_EVENT(WallJump)
|
|
AVH_DECLARE_EVENT(Flight)
|
|
AVH_DECLARE_EVENT(Select)
|
|
AVH_DECLARE_EVENT(Teleport)
|
|
AVH_DECLARE_EVENT(PhaseIn)
|
|
AVH_DECLARE_EVENT(SiegeHit)
|
|
AVH_DECLARE_EVENT(SiegeViewHit)
|
|
AVH_DECLARE_EVENT(StopScream)
|
|
AVH_DECLARE_EVENT(CommandPoints)
|
|
AVH_DECLARE_EVENT(AlienSightOn)
|
|
AVH_DECLARE_EVENT(AlienSightOff)
|
|
//AVH_DECLARE_EVENT(ParalysisGun)
|
|
//AVH_DECLARE_EVENT(ParalysisStart)
|
|
AVH_DECLARE_EVENT(ParasiteGun)
|
|
AVH_DECLARE_EVENT(BlinkSuccess)
|
|
AVH_DECLARE_EVENT(DivineWind)
|
|
AVH_DECLARE_EVENT(BileBomb)
|
|
AVH_DECLARE_EVENT(AcidRocket)
|
|
AVH_DECLARE_EVENT(Stomp);
|
|
AVH_DECLARE_EVENT(Devour);
|
|
AVH_DECLARE_EVENT(InvalidAction)
|
|
AVH_DECLARE_EVENT(Particle)
|
|
AVH_DECLARE_EVENT(DistressBeacon)
|
|
AVH_DECLARE_EVENT(LevelUp)
|
|
|
|
// Alien abilities
|
|
AVH_DECLARE_EVENT(Leap);
|
|
AVH_DECLARE_EVENT(Charge);
|
|
//AVH_DECLARE_EVENT(HiveHit)
|
|
AVH_DECLARE_EVENT(EmptySound)
|
|
AVH_DECLARE_EVENT(NumericalInfo)
|
|
AVH_DECLARE_EVENT(WeaponAnimation)
|
|
AVH_DECLARE_EVENT(Ability);
|
|
|
|
//extern "C"
|
|
//{
|
|
//void EV_FireGlock1( struct event_args_s *args );
|
|
//void EV_FireGlock2( struct event_args_s *args );
|
|
//}
|
|
|
|
//
|
|
// Hook 'em on Initialize
|
|
//
|
|
void Game_HookEvents( void )
|
|
{
|
|
// gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
|
|
// gEngfuncs.pfnHookEvent( "events/glock2.sc", EV_FireGlock2 );
|
|
|
|
// Hook marine weapon events
|
|
gEngfuncs.pfnHookEvent( kKNEventName, EV_Knife );
|
|
gEngfuncs.pfnHookEvent( kMGEventName, EV_MachineGun );
|
|
gEngfuncs.pfnHookEvent( kHGEventName, EV_Pistol );
|
|
gEngfuncs.pfnHookEvent( kSGEventName, EV_SonicGun );
|
|
gEngfuncs.pfnHookEvent( kHMGEventName, EV_HeavyMachineGun );
|
|
gEngfuncs.pfnHookEvent( kGGEventName, EV_GrenadeGun );
|
|
gEngfuncs.pfnHookEvent( kGREventName, EV_Grenade );
|
|
|
|
// Alien weapon events
|
|
gEngfuncs.pfnHookEvent( kSpitGEventName, EV_SpitGun );
|
|
gEngfuncs.pfnHookEvent( kOffenseChamberEventName, EV_OffenseChamber);
|
|
gEngfuncs.pfnHookEvent( kClawsEventName, EV_Claws );
|
|
gEngfuncs.pfnHookEvent( kSwipeEventName, EV_Swipe );
|
|
//gEngfuncs.pfnHookEvent( kEnsnareShootEventName, EV_EnsnareShoot);
|
|
//gEngfuncs.pfnHookEvent( kEnsnareHitEventName, EV_EnsnareHit);
|
|
|
|
gEngfuncs.pfnHookEvent( kSporeShootEventName, EV_SporeShoot);
|
|
gEngfuncs.pfnHookEvent( kSporeCloudEventName, EV_SporeCloud);
|
|
gEngfuncs.pfnHookEvent( kUmbraShootEventName, EV_UmbraGun);
|
|
gEngfuncs.pfnHookEvent( kUmbraCloudEventName, EV_UmbraCloud);
|
|
|
|
gEngfuncs.pfnHookEvent( kSpikeShootEventName, EV_SpikeGun);
|
|
gEngfuncs.pfnHookEvent( kBiteEventName, EV_Bite);
|
|
gEngfuncs.pfnHookEvent( kBite2EventName, EV_Bite2);
|
|
//gEngfuncs.pfnHookEvent( kEggLayerShootEventName, EV_LayEgg);
|
|
gEngfuncs.pfnHookEvent( kBuildingGunEventName, EV_BuildGun);
|
|
gEngfuncs.pfnHookEvent( kHealingSprayEventName, EV_HealingSpray);
|
|
gEngfuncs.pfnHookEvent( kMetabolizeEventName, EV_Metabolize);
|
|
gEngfuncs.pfnHookEvent( kMetabolizeSuccessEventName, EV_MetabolizeSuccess);
|
|
gEngfuncs.pfnHookEvent( kWebSpinnerShootEventName, EV_SpinWeb);
|
|
// gEngfuncs.pfnHookEvent( kBabblerGunEventName, EV_Babbler);
|
|
gEngfuncs.pfnHookEvent( kPrimalScreamShootEventName, EV_PrimalScream);
|
|
gEngfuncs.pfnHookEvent( kStopPrimalScreamSoundEvent, EV_StopScream);
|
|
|
|
gEngfuncs.pfnHookEvent( kJetpackEvent, EV_Jetpack );
|
|
gEngfuncs.pfnHookEvent( kWelderEventName, EV_Welder );
|
|
gEngfuncs.pfnHookEvent( kWelderStartEventName, EV_WelderStart );
|
|
gEngfuncs.pfnHookEvent( kWelderEndEventName, EV_WelderEnd );
|
|
gEngfuncs.pfnHookEvent( kWelderConstEventName, EV_WelderConst );
|
|
//gEngfuncs.pfnHookEvent( kStartOverwatchEvent, EV_OverwatchStart );
|
|
//gEngfuncs.pfnHookEvent( kEndOverwatchEvent, EV_OverwatchEnd );
|
|
gEngfuncs.pfnHookEvent( kRegenerationEvent, EV_Regeneration );
|
|
gEngfuncs.pfnHookEvent( kStartCloakEvent, EV_StartCloak );
|
|
gEngfuncs.pfnHookEvent( kEndCloakEvent, EV_EndCloak );
|
|
//gEngfuncs.pfnHookEvent( kWallJumpEvent, EV_WallJump );
|
|
gEngfuncs.pfnHookEvent( kFlightEvent, EV_Flight );
|
|
gEngfuncs.pfnHookEvent( kTeleportEvent, EV_Teleport );
|
|
gEngfuncs.pfnHookEvent( kPhaseInEvent, EV_PhaseIn );
|
|
gEngfuncs.pfnHookEvent( kSiegeHitEvent, EV_SiegeHit );
|
|
gEngfuncs.pfnHookEvent( kSiegeViewHitEvent, EV_SiegeViewHit );
|
|
gEngfuncs.pfnHookEvent( kCommanderPointsAwardedEvent, EV_CommandPoints );
|
|
gEngfuncs.pfnHookEvent( kAlienSightOnEvent, EV_AlienSightOn);
|
|
gEngfuncs.pfnHookEvent( kAlienSightOffEvent, EV_AlienSightOff);
|
|
// gEngfuncs.pfnHookEvent( kParalysisShootEventName, EV_ParalysisGun);
|
|
// gEngfuncs.pfnHookEvent( kParalysisStartEventName, EV_ParalysisStart);
|
|
gEngfuncs.pfnHookEvent( kParasiteShootEventName, EV_ParasiteGun);
|
|
gEngfuncs.pfnHookEvent( kBlinkEffectSuccessEventName, EV_BlinkSuccess);
|
|
gEngfuncs.pfnHookEvent( kDivineWindShootEventName, EV_DivineWind);
|
|
gEngfuncs.pfnHookEvent( kBileBombShootEventName, EV_BileBomb);
|
|
gEngfuncs.pfnHookEvent( kAcidRocketShootEventName, EV_AcidRocket);
|
|
gEngfuncs.pfnHookEvent( kStompShootEventName, EV_Stomp);
|
|
gEngfuncs.pfnHookEvent( kDevourShootEventName, EV_Devour);
|
|
|
|
gEngfuncs.pfnHookEvent( kLeapEventName, EV_Leap);
|
|
gEngfuncs.pfnHookEvent( kChargeEventName, EV_Charge);
|
|
gEngfuncs.pfnHookEvent( kAbilityEventName, EV_Ability);
|
|
|
|
//gEngfuncs.pfnHookEvent( kHiveHitEvent, EV_HiveHit );
|
|
gEngfuncs.pfnHookEvent( kEmptySoundEvent, EV_EmptySound );
|
|
gEngfuncs.pfnHookEvent( kNumericalInfoEvent, EV_NumericalInfo );
|
|
gEngfuncs.pfnHookEvent( kInvalidActionEvent, EV_InvalidAction);
|
|
gEngfuncs.pfnHookEvent( kParticleEvent, EV_Particle);
|
|
gEngfuncs.pfnHookEvent( kDistressBeaconEvent, EV_DistressBeacon);
|
|
gEngfuncs.pfnHookEvent( kWeaponAnimationEvent, EV_WeaponAnimation);
|
|
gEngfuncs.pfnHookEvent( kLevelUpEvent, EV_LevelUp);
|
|
}
|
|
|
|
#define LOUD_GUN_VOLUME 1000
|
|
#define NORMAL_GUN_VOLUME 600
|
|
#define QUIET_GUN_VOLUME 200
|
|
|
|
#define BRIGHT_GUN_FLASH 512
|
|
#define NORMAL_GUN_FLASH 256
|
|
#define DIM_GUN_FLASH 128
|
|
|
|
#define BIG_EXPLOSION_VOLUME 2048
|
|
#define NORMAL_EXPLOSION_VOLUME 1024
|
|
#define SMALL_EXPLOSION_VOLUME 512
|
|
|
|
#define WEAPON_ACTIVITY_VOLUME 64
|
|
|
|
#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 )
|
|
#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 )
|
|
#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 )
|
|
#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 )
|
|
#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 )
|
|
#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 )
|
|
#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 )
|
|
#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 )
|
|
#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 )
|
|
#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 )
|
|
#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 )
|
|
#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 )
|
|
|
|
// <<< cgc >>>
|
|
// This is duplicated here, make sure it's up to date
|
|
//#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch
|
|
|
|
int& GetUpgradeState(int inIndex)
|
|
{
|
|
cl_entity_t* thePlayer = GetEntity(inIndex);
|
|
return thePlayer->curstate.iuser4;
|
|
}
|
|
|
|
// From Counter-strike
|
|
#define MAX_DEAD_PLAYER_MODELS 64
|
|
TEMPENTITY* g_DeadPlayerModels[MAX_DEAD_PLAYER_MODELS];
|
|
#define MAX_BODY_TIME 5
|
|
#define FTENT_BODYTRACE 0x00100000
|
|
#define FTENT_BODYGRAVITY 0x00200000
|
|
|
|
void RemoveAllDecals()
|
|
{
|
|
for ( int har = 0; har < (int)CVAR_GET_FLOAT( "r_decals" ); har++ )
|
|
gEngfuncs.pEfxAPI->R_DecalRemoveAll ( har );
|
|
|
|
//if ( g_pParticleMan )
|
|
// g_pParticleMan->ResetParticles();
|
|
|
|
if ( g_DeadPlayerModels == NULL )
|
|
return;
|
|
|
|
// Is the dead player model list already clean?
|
|
if ( g_DeadPlayerModels[0] == NULL )
|
|
return;
|
|
|
|
// Clear dead player model list
|
|
for ( int i = 0; i < MAX_DEAD_PLAYER_MODELS; i++ )
|
|
{
|
|
if ( g_DeadPlayerModels[i] )
|
|
{
|
|
g_DeadPlayerModels[i]->die = 0;
|
|
g_DeadPlayerModels[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// lowers body into ground
|
|
void RemoveBody(TEMPENTITY* te, float frametime, float current_time)
|
|
{
|
|
if ( current_time >= te->entity.curstate.fuser2 + MAX_BODY_TIME + CVAR_GET_FLOAT( "cl_corpsestay" ) )
|
|
te->entity.origin[2] -= frametime * 5;
|
|
}
|
|
|
|
// Play a sound? Through up some smoke?
|
|
void HitBody( TEMPENTITY *ent, struct pmtrace_s *ptr )
|
|
{
|
|
if ( ptr->plane.normal.z > 0 )
|
|
ent->flags |= FTENT_BODYGRAVITY;
|
|
}
|
|
|
|
// From Counter-strike
|
|
void CreateCorpse ( Vector vOrigin, Vector vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody )
|
|
{
|
|
int framecount = 255;
|
|
|
|
int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex ( pModel );
|
|
TEMPENTITY *pBody = gEngfuncs.pEfxAPI->R_TempModel( vOrigin, Vector( 0, 0, 0 ), vAngles, 100, gEngfuncs.pEventAPI->EV_FindModelIndex ( pModel ), 0 );
|
|
|
|
if ( pBody == NULL)
|
|
return;
|
|
|
|
pBody->flags |= FTENT_COLLIDEWORLD | FTENT_CLIENTCUSTOM | FTENT_SPRANIMATE | FTENT_BODYTRACE | FTENT_PERSIST;
|
|
pBody->frameMax = framecount;
|
|
|
|
pBody->entity.curstate.animtime = flAnimTime;
|
|
pBody->entity.curstate.framerate = 1;
|
|
pBody->entity.curstate.sequence = iSequence;
|
|
pBody->entity.curstate.frame = 0;
|
|
pBody->entity.curstate.body = iBody;
|
|
pBody->entity.curstate.renderamt = 255;
|
|
pBody->entity.curstate.fuser1 = gHUD.m_flTime + 1;
|
|
pBody->entity.curstate.fuser2 = gHUD.m_flTime + CVAR_GET_FLOAT ("cl_corpsestay"); // estimated end time of animation
|
|
|
|
// let entity sink 5 seconds then kill it after cl_corpsestay is over
|
|
pBody->die = gEngfuncs.GetClientTime() + pBody->entity.curstate.fuser2 + 5;
|
|
pBody->callback = RemoveBody;
|
|
pBody->hitcallback = HitBody;
|
|
pBody->bounceFactor = 0;
|
|
|
|
// Save body to list so we can remove after round ends
|
|
for ( int i = 0; i < 64; i ++ )
|
|
{
|
|
if ( g_DeadPlayerModels[ i ] == NULL )
|
|
{
|
|
g_DeadPlayerModels[ i ] = pBody;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayMeleeHitEffects(struct event_args_s* inArgs, int inRange, const string& inSoundName)
|
|
{
|
|
int thePlayer = inArgs->entindex;
|
|
|
|
vec3_t theForward, theRight, theUp;
|
|
gEngfuncs.pfnAngleVectors(inArgs->angles, theForward, theRight, theUp);
|
|
|
|
vec3_t theAimingDir;
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
theAimingDir[i] = theForward[i];// + theRight[i] + theUp[i];
|
|
}
|
|
VectorNormalize(theAimingDir);
|
|
|
|
// Do a trace within certain range, ignoring ourselves
|
|
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
|
|
|
|
gEngfuncs.pEventAPI->EV_PushPMStates();
|
|
|
|
gEngfuncs.pEventAPI->EV_SetSolidPlayers(-1);
|
|
|
|
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
|
|
|
Vector theStartPos;
|
|
//VectorMA(inArgs->origin, 17, theAimingDir, theStartPos);
|
|
VectorCopy(inArgs->origin, theStartPos);
|
|
//gTriDebugLocations.push_back(DebugPoint(theStartPos[0], theStartPos[1], theStartPos[2]));
|
|
//gTriDebugLocations.push_back(DebugPoint(theStartPos[0] + theAimingDir[0]*inRange, theStartPos[1]+ theAimingDir[1]*inRange, theStartPos[2] + theAimingDir[2]*inRange));
|
|
|
|
Vector theEndPos;
|
|
VectorMA(theStartPos, inRange, theAimingDir, theEndPos);
|
|
//gTriDebugLocations.push_back(DebugPoint(theEndPos[0], theEndPos[1], theEndPos[2]));
|
|
|
|
pmtrace_t tr;
|
|
bool theDone = false;
|
|
int theNumIterations = 0;
|
|
|
|
do
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace(theStartPos, theEndPos, PM_NORMAL, thePlayer, &tr);
|
|
|
|
// Did we hit something marked as enemy?
|
|
int theHit = gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr);
|
|
if(theHit == thePlayer)
|
|
{
|
|
// tr.endpos: -71.1894, 3274.23, -527.888
|
|
// theStartPos: -71.20, 3274.02, -517.89
|
|
// theAimingDir: -0.01169, -0.02157, .99969
|
|
// Infinite loop: this next line doesn't changea anything
|
|
VectorMA(tr.endpos, kHitOffsetAmount, theAimingDir, theStartPos);
|
|
}
|
|
else if(tr.fraction < 1.0f)
|
|
{
|
|
Vector theHitPos = tr.endpos;
|
|
|
|
// Play sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(thePlayer, theHitPos, CHAN_AUTO, inSoundName.c_str(), 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Play generic damage effect
|
|
//AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsMeleeDamage, theHitPos, &(tr.plane.normal));
|
|
|
|
theDone = true;
|
|
}
|
|
else
|
|
{
|
|
theDone = true;
|
|
}
|
|
|
|
// Prevent infinite loop
|
|
theNumIterations++;
|
|
|
|
if(theNumIterations > 20)
|
|
{
|
|
theDone = true;
|
|
}
|
|
|
|
} while(!theDone);
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
}
|
|
|
|
//
|
|
// Define them
|
|
//
|
|
void EV_Knife(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 1);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
theSoundToPlay = kKNFireSound1;
|
|
break;
|
|
case 1:
|
|
theSoundToPlay = kKNFireSound2;
|
|
break;
|
|
}
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// TODO: Now do a trace line and if we hit a wall, play the wall sound, if we hit a person, play a hit-flesh sound
|
|
// TODO: Add sparks where it hit
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
/*
|
|
float theHalfSpread = kKNXPunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
//void EV_Grenade(struct event_args_s* inArgs)
|
|
//{
|
|
// int idx = inArgs->entindex;
|
|
// vec3_t up, right, forward;
|
|
// gEngfuncs.pfnAngleVectors(inArgs->angles, forward, right, up);
|
|
//
|
|
// // Play attack sound
|
|
// char* theSoundToPlay = kKNFireSound1;
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//
|
|
// // Create a temporary entity that bounces and dies after a certain amount of time
|
|
// int theModelIndex;
|
|
// struct model_s* theModel = gEngfuncs.CL_LoadModel("models/w_grenade.mdl", &theModelIndex);
|
|
// ASSERT(theModel);
|
|
// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
// ASSERT(theTempEntity);
|
|
// if(theTempEntity)
|
|
// {
|
|
// vec3_t theStartPos, theEndPos, vecSrc;
|
|
// EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
// VectorMA(vecSrc, kGBarrelLength, forward, theStartPos);
|
|
//
|
|
// VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
// theTempEntity->die += kGrenDetonateTime;
|
|
// //theTempEntity->hitcallback = SpitHit;
|
|
// theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_PERSIST);
|
|
//
|
|
// vec3_t theSourceVelocity;
|
|
// VectorCopy(inArgs->velocity, theSourceVelocity);
|
|
//
|
|
// vec3_t theVelocity;
|
|
// ComputeGrenadeVelocity(forward, theSourceVelocity, theVelocity);
|
|
//
|
|
// VectorCopy(theVelocity, theTempEntity->entity.baseline.origin);
|
|
// VectorCopy(theVelocity, theTempEntity->entity.baseline.velocity);
|
|
// }
|
|
//
|
|
// // General x-punch axis
|
|
//// if (EV_IsLocal(idx))
|
|
//// {
|
|
//// gEngfuncs.pEventAPI->EV_WeaponAnimation(ANIM_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2);
|
|
//// }
|
|
//}
|
|
|
|
void EV_MachineGun(struct event_args_s* args)
|
|
{
|
|
// What to do about this static member?
|
|
static int tracerCount[ 32 ];
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = args->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = args->entindex;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
// Get upgrade
|
|
int theTracerFreq;
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(idx), NULL, &theTracerFreq);
|
|
|
|
// Vary flange effect more with higher upgrade
|
|
int theUpperBound = theUpgradeLevel*10;
|
|
int thePitch = 100 + (gEngfuncs.pfnRandomLong(0, theUpperBound) - theUpperBound);
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
if(theUpgradeLevel > 0)
|
|
{
|
|
EV_MuzzleFlash();
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(args->iparam2, 2);
|
|
}
|
|
|
|
// General ejecting ammo if any
|
|
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex(kMGEjectModel);
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
|
|
EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
|
|
|
|
// Only eject brass when upgraded
|
|
//if(theUpgradeLevel > 0)
|
|
//{
|
|
// VectorScale(ShellVelocity, theUpgradeLevel, ShellVelocity);
|
|
EV_EjectBrass(ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL);
|
|
//}
|
|
|
|
// Play one of basic attack sounds
|
|
float theVolume = args->fparam1;
|
|
float theAttenuation = .8f + .3*theUpgradeLevel;
|
|
|
|
char* theSoundToPlay = kMGFireSound1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, theSoundToPlay, theVolume, theAttenuation, 0, thePitch);
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
//EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, kMGRange, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1] );
|
|
EV_HLDM_FireBulletsPlayer( idx, forward, right, up, 1, vecSrc, vecAiming, kMGRange, BULLET_PLAYER_MP5, theTracerFreq, &tracerCount[idx-1], kMGSpread, args->iparam1);
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
|
|
// Multiply punch by upgrade level
|
|
//float theHalfSpread = (kMGXPunch/4.0f)*(theUpgradeLevel+1);
|
|
|
|
// Changed to ignore upgrade level
|
|
float theHalfSpread = (kMGXPunch/4.0f);
|
|
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void EV_Pistol(struct event_args_s* args)
|
|
{
|
|
// What to do about this static member?
|
|
static int tracerCount[ 32 ];
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = args->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = args->entindex;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
// Get upgrade
|
|
int theTracerFreq;
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(idx), NULL, &theTracerFreq);
|
|
|
|
// Vary flange effect more with higher upgrade
|
|
int theUpperBound = theUpgradeLevel*10;
|
|
int thePitch = 100 + (gEngfuncs.pfnRandomLong(0, theUpperBound) - theUpperBound);
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
if(theUpgradeLevel > 0)
|
|
{
|
|
EV_MuzzleFlash();
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(args->iparam2, 2);
|
|
}
|
|
|
|
// General ejecting ammo if any
|
|
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex(kHGEjectModel);
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
|
|
EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
|
|
|
|
// Only eject brass when upgraded
|
|
//if(theUpgradeLevel > 0)
|
|
//{
|
|
// VectorScale(ShellVelocity, theUpgradeLevel, ShellVelocity);
|
|
EV_EjectBrass(ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL);
|
|
//}
|
|
|
|
// Play one of basic attack sounds
|
|
float theVolume = args->fparam1;
|
|
float theAttenuation = .8f + .3*theUpgradeLevel;
|
|
|
|
char* theSoundToPlay = kHGFireSound1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, theSoundToPlay, theVolume, theAttenuation, 0, thePitch);
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
//EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, kHGRange, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1] );
|
|
EV_HLDM_FireBulletsPlayer( idx, forward, right, up, 1, vecSrc, vecAiming, kHGRange, BULLET_PLAYER_357, theTracerFreq, &tracerCount[idx-1], kHGSpread, args->iparam1);
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
// Multiply punch by upgrade level
|
|
//float theHalfSpread = (kHGXPunch/3.0f)*(theUpgradeLevel+1);
|
|
|
|
// Changed to ignore upgrade level
|
|
float theHalfSpread = (kHGXPunch/3.0f);
|
|
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_SonicGun(struct event_args_s* args)
|
|
{
|
|
// What to do about this static member?
|
|
static int tracerCount[ 32 ];
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = args->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = args->entindex;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
// Get upgrade
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(idx));
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
if(theUpgradeLevel > 0)
|
|
{
|
|
EV_MuzzleFlash();
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(args->iparam2, 2);
|
|
}
|
|
|
|
// General ejecting ammo if any
|
|
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex(kSGEjectModel);
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
|
|
EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
|
|
|
|
//if(theUpgradeLevel > 0)
|
|
//{
|
|
// VectorScale(ShellVelocity, theUpgradeLevel, ShellVelocity);
|
|
EV_EjectBrass(ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL);
|
|
//}
|
|
|
|
float theAttenuation = .8f + .2*theUpgradeLevel;
|
|
//float theVolume = min(.85f + .05*theUpgradeLevel, 1.0f);
|
|
float theVolume = args->fparam1;
|
|
|
|
// TODO: Synch up with propagated random seed?
|
|
// Play one of basic attack sounds
|
|
//if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
char* theSoundToPlay = kSGFireSound1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, theSoundToPlay, theVolume, theAttenuation, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
//if ( gEngfuncs.GetMaxClients() > 1 )
|
|
//{
|
|
vec3_t theBarrelOffset, theBarrelTip;
|
|
VectorScale(forward, 30, theBarrelOffset);
|
|
VectorAdd(vecSrc, theBarrelOffset, theBarrelTip);
|
|
|
|
// if(theUpgradeLevel > 0)
|
|
// {
|
|
// AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsShotgun, theBarrelTip);
|
|
// }
|
|
//EV_HLDM_FireBullets( idx, forward, right, up, kSGBulletsPerShot, vecSrc, vecAiming, kSGRange, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], VECTOR_CONE_20DEGREES.x, VECTOR_CONE_20DEGREES.y);
|
|
EV_HLDM_FireBulletsPlayer( idx, forward, right, up, BALANCE_VAR(kSGBulletsPerShot), vecSrc, vecAiming, kSGRange, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], kSGSpread, args->iparam1);
|
|
//}
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
//float theHalfSpread = (kSGXPunch/3.0f)*(theUpgradeLevel+1);
|
|
|
|
// Changed to ignore upgrade level
|
|
float theHalfSpread = (kSGXPunch/3.0f);
|
|
|
|
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_HeavyMachineGun(struct event_args_s* args)
|
|
{
|
|
// What to do about this static member?
|
|
static int tracerCount[ 32 ];
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = args->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = args->entindex;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
int theTracerLevel;
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(idx), NULL, &theTracerLevel);
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
if(theUpgradeLevel > 0)
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
EV_MuzzleFlash();
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(args->iparam2, 2);
|
|
}
|
|
|
|
// General ejecting ammo if any
|
|
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex(kHMGEjectModel);
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
|
|
EV_GetDefaultShellInfo(args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
|
|
|
|
//if(theUpgradeLevel > 0)
|
|
//{
|
|
// VectorScale(ShellVelocity, theUpgradeLevel, ShellVelocity);
|
|
EV_EjectBrass(ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL);
|
|
//}
|
|
|
|
// TODO: Synch up with propagated random seed?
|
|
// Play one of basic attack sounds
|
|
int theHighIndex = theUpgradeLevel;
|
|
//int theRandomLong = gEngfuncs.pfnRandomLong(0, theHighIndex);
|
|
//float theVolume = min(.6 + .2*theUpgradeLevel, 1.0f);
|
|
float theVolume = args->fparam1;
|
|
float theAttenuation = .8f + .2*theUpgradeLevel;
|
|
int thePitch = 100;
|
|
if(theUpgradeLevel > 0)
|
|
{
|
|
int theVariance = theUpgradeLevel*6;
|
|
thePitch += (gEngfuncs.pfnRandomLong( 0, theVariance))/(theVariance/2);
|
|
}
|
|
|
|
char* theSoundToPlay = kHMGFireSound1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, theSoundToPlay, theVolume, theAttenuation, 0, thePitch);
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
//EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, kHMGRange, BULLET_PLAYER_357, theTracerLevel, &tracerCount[idx-1], theSpreadX, theSpreadY);
|
|
EV_HLDM_FireBulletsPlayer( idx, forward, right, up, 1, vecSrc, vecAiming, kHMGRange, BULLET_PLAYER_MP5, theTracerLevel, &tracerCount[idx-1], kHMGSpread, args->iparam1);
|
|
|
|
// if(theUpgradeLevel > 1)
|
|
// {
|
|
// if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
// {
|
|
// vec3_t theBarrelOffset, theBarrelTip;
|
|
// VectorScale(forward, 100, theBarrelOffset);
|
|
// VectorAdd(vecSrc, theBarrelOffset, theBarrelTip);
|
|
//
|
|
// AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsHeavyMGSmoke, vecSrc);
|
|
// }
|
|
// }
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
//float theHalfSpread = (kHMGXPunch/4.0f)*(theUpgradeLevel+1);
|
|
|
|
// Changed to ignore upgrade level
|
|
float theHalfSpread = (kHMGXPunch/4.0f);
|
|
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void GrenadeHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
{
|
|
char* theSoundToPlay = kGRHitSound;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(ent->entity.index, ptr->endpos, CHAN_AUTO, theSoundToPlay, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//ASSERT(ptr);
|
|
//ASSERT(ent);
|
|
//ent->die = gEngfuncs.GetClientTime();
|
|
}
|
|
|
|
void EV_GrenadeGun(struct event_args_s* inArgs)
|
|
{
|
|
// What to do about this static member?
|
|
static int tracerCount[ 32 ];
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = inArgs->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(idx));
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
if(theUpgradeLevel > 0)
|
|
{
|
|
EV_MuzzleFlash();
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
// // General ejecting ammo if any
|
|
// int shell = gEngfuncs.pEventAPI->EV_FindModelIndex(kGGEjectModel);
|
|
// vec3_t ShellVelocity;
|
|
// vec3_t ShellOrigin;
|
|
//
|
|
// EV_GetDefaultShellInfo(inArgs, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
|
|
//
|
|
// //if(theUpgradeLevel > 0)
|
|
// //{
|
|
// // VectorScale(ShellVelocity, theUpgradeLevel, ShellVelocity);
|
|
// EV_EjectBrass(ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL);
|
|
// //}
|
|
|
|
char* theSoundToPlay = kGGFireSound1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, theSoundToPlay, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
EV_GetGunPosition( inArgs, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
//float theHalfSpread = (kGGXPunch/2.0f)*(theUpgradeLevel+1);
|
|
|
|
// Changed to ignore upgrade level
|
|
float theHalfSpread = (kGGXPunch/2.0f);
|
|
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
|
|
// Create temp entity for grenade (assumes grenade is created at inArgs->origin, with velocity inArgs->angles)
|
|
// ASSERT(inArgs);
|
|
//
|
|
// Vector theStartPos;
|
|
// VectorCopy(inArgs->origin, theStartPos);
|
|
//
|
|
// // Fire grenade
|
|
// int theModelIndex;
|
|
// struct model_s* theModel = gEngfuncs.CL_LoadModel(kGGAmmoModel, &theModelIndex);
|
|
// if(theModel)
|
|
// {
|
|
// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
// if(theTempEntity)
|
|
// {
|
|
// VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
// theTempEntity->die += kSpitLifetime;
|
|
// theTempEntity->hitcallback = GrenadeHit;
|
|
// theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_PERSIST | FTENT_GRAVITY| FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP);
|
|
// theTempEntity->entity.curstate.framerate = 30;
|
|
// theTempEntity->frameMax = 4;//theModel->numframes;
|
|
//
|
|
// // Read origin as origin, and angles as velocity (from AvHAlienTurret::Shoot())
|
|
// Vector theStartVelocity;
|
|
// VectorCopy(inArgs->angles, theStartVelocity);
|
|
//
|
|
// // Temp entities interpret baseline origin as velocity.
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
void EV_Grenade(struct event_args_s* inArgs)
|
|
{
|
|
// What to do about this static member?
|
|
static int tracerCount[ 32 ];
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = inArgs->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(idx));
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
char* theSoundToPlay = NULL;
|
|
|
|
switch(inArgs->iparam2)
|
|
{
|
|
case 4:
|
|
case 7:
|
|
theSoundToPlay = kGRFireSound1;
|
|
break;
|
|
case 3:
|
|
case 6:
|
|
theSoundToPlay = kGRPrimeSound;
|
|
break;
|
|
}
|
|
|
|
if(theSoundToPlay)
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, theSoundToPlay, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// EV_GetGunPosition( inArgs, vecSrc, origin );
|
|
// VectorCopy( forward, vecAiming );
|
|
//
|
|
// // Create grenade temp entity
|
|
// int theModelIndex;
|
|
// struct model_s* theModel = gEngfuncs.CL_LoadModel(kGRWModel, &theModelIndex);
|
|
// if(theModel)
|
|
// {
|
|
// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
// if(theTempEntity)
|
|
// {
|
|
// vec3_t theStartPos, theEndPos;
|
|
// EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
// VectorMA(vecSrc, kGRBarrelLength, forward, theStartPos);
|
|
//
|
|
// VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
// theTempEntity->die += BALANCE_VAR(kGrenDetonateTime);
|
|
// theTempEntity->hitcallback = GrenadeHit;
|
|
// theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_GRAVITY | FTENT_ROTATE | FTENT_PERSIST);
|
|
// theTempEntity->clientIndex = inArgs->entindex; // Entity to ignore collisions with
|
|
//
|
|
// theTempEntity->entity.baseline.angles[0] = rand()%360;
|
|
//
|
|
// //theTempEntity->entity.curstate.framerate = 30;
|
|
// //theTempEntity->frameMax = 4;//theModel->numframes;
|
|
//
|
|
// // Temp entities interpret baseline origin as velocity.
|
|
// Vector theBaseVelocity;
|
|
// VectorScale(inArgs->velocity, kGrenadeParentVelocityScalar, theBaseVelocity);
|
|
//
|
|
// Vector theStartVelocity;
|
|
// VectorMA(theBaseVelocity, kGrenadeVelocity, forward, theStartVelocity);
|
|
//
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
char *EV_HLDM_DamageDecal( physent_t *pe );
|
|
|
|
void CreateDecal(struct pmtrace_s* inTrace)
|
|
{
|
|
physent_t *pe;
|
|
pe = gEngfuncs.pEventAPI->EV_GetPhysent( inTrace->ent );
|
|
if(pe)
|
|
{
|
|
char* inDecalName = EV_HLDM_DamageDecal( pe );
|
|
|
|
// Only decal brush models such as the world etc.
|
|
if ( inDecalName && inDecalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) )
|
|
{
|
|
if ( CVAR_GET_FLOAT( "r_decals" ) )
|
|
{
|
|
gEngfuncs.pEfxAPI->R_DecalShoot(
|
|
gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( inDecalName) ),
|
|
gEngfuncs.pEventAPI->EV_IndexFromTrace( inTrace ), 0, inTrace->endpos, 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SpitHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
{
|
|
char* theSoundToPlay = kSpitHitSound1;
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
theSoundToPlay = kSpitHitSound2;
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(ent->entity.index, ptr->endpos, CHAN_AUTO, theSoundToPlay, .6f, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
if(ptr && ent)
|
|
{
|
|
ent->die = gEngfuncs.GetClientTime();
|
|
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSpitHit, ptr->endpos, &(ptr->plane.normal));
|
|
|
|
// Create splat here too
|
|
CreateDecal(ptr);
|
|
}
|
|
}
|
|
|
|
void EV_SpitGun(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = inArgs->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = kSpitGFireSound1;
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
theSoundToPlay = kSpitGFireSound2;
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Fire spit glob
|
|
int theModelIndex;
|
|
struct model_s* theModel = gEngfuncs.CL_LoadModel(kSpitGunSprite, &theModelIndex);
|
|
if(theModel)
|
|
{
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
if(theTempEntity)
|
|
{
|
|
vec3_t theStartPos, theEndPos;
|
|
EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
VectorMA(vecSrc, kSpitGBarrelLength, forward, theStartPos);
|
|
|
|
// Create tiny spittle where it leaves
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSpitShoot, theStartPos);
|
|
|
|
VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
theTempEntity->die += kSpitLifetime;
|
|
theTempEntity->hitcallback = SpitHit;
|
|
theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP/* | FTENT_PERSIST*/);
|
|
theTempEntity->clientIndex = inArgs->entindex; // Entity to ignore collisions with
|
|
theTempEntity->entity.curstate.framerate = 30;
|
|
theTempEntity->frameMax = 4;//theModel->numframes;
|
|
|
|
// Temp entities interpret baseline origin as velocity.
|
|
Vector theBaseVelocity;
|
|
VectorScale(inArgs->velocity, kSpitParentVelocityScalar, theBaseVelocity);
|
|
|
|
Vector theStartVelocity;
|
|
VectorMA(theBaseVelocity, kSpitVelocity, forward, theStartVelocity);
|
|
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
}
|
|
}
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
float theHalfSpread = kSpitGXPunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void SpikeHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
{
|
|
//EV_HLDM_DecalGunshot( &tr, iBulletType );
|
|
|
|
//int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kSpikeGunHitSprite);
|
|
//TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(ptr->endpos, vec3_origin, .6f, theSprite, kRenderTransAdd, kRenderFxNoDissipation, .5f, .4f, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
|
|
//if(theTempEntity)
|
|
//{
|
|
// theTempEntity->entity.curstate.framerate = 30;
|
|
//}
|
|
|
|
// Play spike ricochet sounds
|
|
char* theRandomSound = NULL;
|
|
|
|
switch (gEngfuncs.pfnRandomLong(0, 2))
|
|
{
|
|
case 0:
|
|
theRandomSound = "weapons/a_ric1.wav";
|
|
break;
|
|
case 1:
|
|
theRandomSound = "weapons/a_ric2.wav";
|
|
break;
|
|
case 2:
|
|
theRandomSound = "weapons/a_ric3.wav";
|
|
break;
|
|
}
|
|
|
|
const float kAlienRicochetVolume = .25f;
|
|
ASSERT(theRandomSound);
|
|
gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, theRandomSound, kAlienRicochetVolume, ATTN_NORM, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) );
|
|
|
|
// Create spike hit particle system
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSpikeHitEffect, ptr->endpos);
|
|
|
|
// Kill off temp ent
|
|
ent->die = -1;
|
|
}
|
|
|
|
void EV_OffenseChamber(struct event_args_s* inArgs)
|
|
{
|
|
//static int theTracerCount[ 32 ];
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
// Play one of basic attack sounds
|
|
float theVolume = inArgs->fparam1;
|
|
float theAttenuation = 1.2f;
|
|
|
|
char* theSoundToPlay = kAlienTurretFire1;
|
|
|
|
int theUpperBound = 30;
|
|
int thePitch = 100 + (gEngfuncs.pfnRandomLong(0, theUpperBound) - theUpperBound/2);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, theSoundToPlay, theVolume, theAttenuation, 0, thePitch);
|
|
|
|
// Read origin as origin, and angles as direction (from AvHAlienTurret::Shoot())
|
|
Vector theStartPos;
|
|
VectorCopy(inArgs->origin, theStartPos);
|
|
|
|
Vector theNetworkDirToEnemy;
|
|
VectorCopy(inArgs->angles, theNetworkDirToEnemy);
|
|
|
|
// Take into account network precision
|
|
Vector theDirToEnemy;
|
|
VectorScale(theNetworkDirToEnemy, 1/100.0f, theDirToEnemy);
|
|
|
|
Vector theDirToEnemyAngles;
|
|
VectorAngles(theDirToEnemy, theDirToEnemyAngles);
|
|
|
|
Vector theInitialVelocity;
|
|
VectorScale(theDirToEnemy, kOffenseChamberSpikeVelocity, theInitialVelocity);
|
|
|
|
// Create spike projectile
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempModel(theStartPos, theDirToEnemy, theDirToEnemyAngles, 100, gEngfuncs.pEventAPI->EV_FindModelIndex(kSpikeProjectileModel), 0);
|
|
if(theTempEntity)
|
|
{
|
|
//vec3_t theStartPos, theEndPos;
|
|
//EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
//VectorMA(vecSrc, kSpikeBarrelLength, forward, theStartPos);
|
|
|
|
VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
theTempEntity->hitcallback = SpikeHit;
|
|
theTempEntity->flags = (FTENT_COLLIDEALL | FTENT_PERSIST | FTENT_COLLIDEKILL);
|
|
theTempEntity->die += kSpikeLifetime;
|
|
theTempEntity->clientIndex = inArgs->iparam1; // Entity to ignore collisions with
|
|
|
|
//theTempEntity->entity.curstate.framerate = 30;
|
|
//theTempEntity->frameMax = 4;//theModel->numframes;
|
|
|
|
// Temp entities interpret baseline origin as velocity.
|
|
VectorCopy(theInitialVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theInitialVelocity, theTempEntity->entity.baseline.velocity);
|
|
|
|
// Set orientation
|
|
//VectorCopy(inArgs->angles, theTempEntity->entity.angles);
|
|
}
|
|
|
|
//
|
|
//
|
|
// ASSERT(inArgs);
|
|
//
|
|
// // Play attack animation and add muzzle flash
|
|
// int idx = inArgs->entindex;
|
|
//
|
|
// Vector theStartPos;
|
|
// VectorCopy(inArgs->origin, theStartPos);
|
|
//
|
|
// // Play attack sound
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(idx, theStartPos, CHAN_WEAPON, kAlienTurretFire1, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//
|
|
// // Fire spit glob
|
|
// int theModelIndex;
|
|
// struct model_s* theModel = gEngfuncs.CL_LoadModel(kAlienTurretSprite, &theModelIndex);
|
|
// if(theModel)
|
|
// {
|
|
// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
// if(theTempEntity)
|
|
// {
|
|
// // Create tiny spittle where it leaves
|
|
// AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSpitShoot, theStartPos);
|
|
//
|
|
// VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
// theTempEntity->die += kSpitLifetime;
|
|
// theTempEntity->hitcallback = SpitHit;
|
|
// theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP/* | FTENT_PERSIST*/);
|
|
// theTempEntity->entity.curstate.framerate = 30;
|
|
// theTempEntity->frameMax = 4;//theModel->numframes;
|
|
//
|
|
// // Read origin as origin, and angles as direction (from AvHAlienTurret::Shoot())
|
|
// Vector theDirToEnemy;
|
|
// VectorCopy(inArgs->angles, theDirToEnemy);
|
|
//
|
|
// Vector theStartVelocity;
|
|
// VectorScale(theDirToEnemy, kAlienTurretProjectileVelocity, theStartVelocity);
|
|
//
|
|
// // Temp entities interpret baseline origin as velocity.
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
void EV_Claws(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 2);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
theSoundToPlay = kClawsSound1;
|
|
break;
|
|
case 1:
|
|
theSoundToPlay = kClawsSound2;
|
|
break;
|
|
case 2:
|
|
theSoundToPlay = kClawsSound3;
|
|
break;
|
|
}
|
|
|
|
const int kBasePitch = 94;
|
|
const int kVariablePitchRange = 0xF;
|
|
|
|
int theRandomPitch = gEngfuncs.pfnRandomLong( 0, kVariablePitchRange );
|
|
int thePitch = kBasePitch + (inArgs->fparam1*kClawsAdrenPitchFactor) + theRandomPitch;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, thePitch);
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
|
|
/*
|
|
float theHalfSpread = (inArgs->fparam1*kClawsPunch)/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
*/
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
int theRandomLong = gEngfuncs.pfnRandomLong(0, 1);
|
|
if(theRandomLong == 0)
|
|
{
|
|
PlayMeleeHitEffects(inArgs, kClawsRange, kClawsHitSound1);
|
|
}
|
|
else
|
|
{
|
|
PlayMeleeHitEffects(inArgs, kClawsRange, kClawsHitSound2);
|
|
}
|
|
}
|
|
|
|
|
|
void EV_Swipe(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 3);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
theSoundToPlay = kSwipeSound1;
|
|
break;
|
|
case 1:
|
|
theSoundToPlay = kSwipeSound2;
|
|
break;
|
|
case 2:
|
|
theSoundToPlay = kSwipeSound3;
|
|
break;
|
|
case 3:
|
|
theSoundToPlay = kSwipeSound4;
|
|
break;
|
|
}
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
|
|
/*
|
|
float theHalfSpread = kSwipePunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
*/
|
|
}
|
|
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
PlayMeleeHitEffects(inArgs, kSwipeRange, kSwipeHitSound1);
|
|
}
|
|
else
|
|
{
|
|
PlayMeleeHitEffects(inArgs, kSwipeRange, kSwipeHitSound2);
|
|
}
|
|
}
|
|
|
|
//void EnsnareHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
//{
|
|
// ent->die = gEngfuncs.GetClientTime();
|
|
//}
|
|
//
|
|
//void EV_EnsnareShoot(struct event_args_s* inArgs)
|
|
//{
|
|
// int idx = inArgs->entindex;
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, kEnsnareFireSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//
|
|
// vec3_t up, right, forward;
|
|
// gEngfuncs.pfnAngleVectors(inArgs->angles, forward, right, up);
|
|
//
|
|
// // Fire spit glob
|
|
// int theModelIndex;
|
|
// struct model_s* theModel = gEngfuncs.CL_LoadModel(kEnsnareSprite, &theModelIndex);
|
|
// ASSERT(theModel);
|
|
// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
// if(theTempEntity)
|
|
// {
|
|
// vec3_t vecSrc, vecAiming;
|
|
// vec3_t theStartPos, theEndPos;
|
|
// EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
// VectorMA(vecSrc, kEnsnareBarrelLength, forward, theStartPos);
|
|
//
|
|
// // Create tiny ensnare bits where it leaves
|
|
// AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsEnsnareShoot, theStartPos);
|
|
//
|
|
// VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
// theTempEntity->die += 10.0f;
|
|
// theTempEntity->hitcallback = EnsnareHit;
|
|
// theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
|
|
// theTempEntity->entity.curstate.framerate = 30;
|
|
// theTempEntity->frameMax = 4;//theModel->numframes;
|
|
//
|
|
// // Temp entities interpret baseline origin as velocity.
|
|
// Vector theBaseVelocity;
|
|
// VectorScale(inArgs->velocity, kEnsnareParentVelocityScalar, theBaseVelocity);
|
|
//
|
|
// Vector theStartVelocity;
|
|
// VectorMA(theBaseVelocity, kEnsnareVelocity, forward, theStartVelocity);
|
|
//
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
// }
|
|
//}
|
|
//
|
|
//void EV_EnsnareHit(struct event_args_s* inArgs)
|
|
//{
|
|
// int idx = inArgs->entindex;
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, kEnsnareHitSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//
|
|
// AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsEnsnareHit, inArgs->origin);
|
|
//}
|
|
|
|
void ShootCloud(struct event_args_s* inArgs, const char* inSpriteName)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, kSporeFireSound, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
// Create temp cloud projectile
|
|
int theModelIndex;
|
|
struct model_s* theModel = gEngfuncs.CL_LoadModel(inSpriteName, &theModelIndex);
|
|
if(theModel)
|
|
{
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
if(theTempEntity)
|
|
{
|
|
vec3_t angles;
|
|
VectorCopy( inArgs->angles, angles );
|
|
|
|
//vec3_t velocity
|
|
//VectorCopy( inArgs->velocity, velocity );
|
|
|
|
vec3_t forward, right, up;
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
vec3_t theStartPos, theEndPos, vecSrc;
|
|
EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
VectorMA(vecSrc, kSporeBarrelLength, forward, theStartPos);
|
|
|
|
VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
//theTempEntity->die += kSpitLifetime;
|
|
//theTempEntity->hitcallback = SpitHit;
|
|
theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_COLLIDEKILL);
|
|
theTempEntity->entity.curstate.framerate = 20;
|
|
theTempEntity->frameMax = 17;//theModel->numframes;
|
|
|
|
// Temp entities interpret baseline origin as velocity.
|
|
Vector theStartVelocity(0, 0, 0);
|
|
VectorMA(theStartVelocity, kShootCloudVelocity, forward, theStartVelocity);
|
|
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_SporeShoot(struct event_args_s* inArgs)
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSporeShoot, inArgs->origin);
|
|
|
|
ShootCloud(inArgs, kClientSporeSprite);
|
|
}
|
|
|
|
void EV_SporeCloud(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_AUTO, kSporeCloudSound, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSporeCloud, inArgs->origin);
|
|
}
|
|
|
|
void EV_UmbraGun(struct event_args_s* inArgs)
|
|
{
|
|
ShootCloud(inArgs, kClientUmbraSprite);
|
|
|
|
// if (EV_IsLocal(inArgs->entindex))
|
|
// {
|
|
// gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
// }
|
|
}
|
|
|
|
void EV_UmbraCloud(struct event_args_s* inArgs)
|
|
{
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kUmbraFireSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsUmbraCloud, inArgs->origin);
|
|
}
|
|
|
|
void ParticleCallback( struct particle_s* particle, float frametime )
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0; i < 3; i++ )
|
|
{
|
|
particle->org[ i ] += particle->vel[ i ] * frametime;
|
|
}
|
|
}
|
|
|
|
|
|
void EV_Jetpack(struct event_args_s* inArgs)
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsJetpackEffect, inArgs->origin);
|
|
|
|
// Update jetpack sound every once in awhile
|
|
if(gEngfuncs.pfnRandomLong(0, 3) == 0)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_BODY, kJetpackSound, .5f, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
|
|
// Use this as index instead?
|
|
//args->entindex;
|
|
|
|
// // Create a dlight for jetpack
|
|
// int theIndexToUse = gJetpackLights.size();
|
|
// dlight_t* dl = gEngfuncs.pEfxAPI->CL_AllocDlight(theIndexToUse);
|
|
// VectorCopy (args->origin, dl->origin);
|
|
// dl->radius = 180;
|
|
// dl->color.r = 180;
|
|
// dl->color.g = 180;
|
|
// dl->color.b = 250;
|
|
//
|
|
// // don't die for forseeable future
|
|
// dl->die = gEngfuncs.GetClientTime() + kArbitraryLargeLightTime;
|
|
// //dl->die += kArbitraryLargeLightTime;
|
|
//
|
|
// gJetpackLights.push_back(LightType(args->entindex, dl));
|
|
//
|
|
// gEngfuncs.pEventAPI->EV_PlaySound( args->entindex, args->origin, CHAN_BODY, kJetpackSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Create temporary smoke trail!
|
|
//void ( *R_Sprite_Trail ) ( int type, float * start, float * end, int modelIndex, int count, float life, float size, float amplitude, int renderamt, float speed );
|
|
//int theSmokeModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/smoke.spr" );
|
|
//gEngfuncs.pEfxAPI->R_PlayerSprites(args->entindex, theSmokeModelIndex, 20, 100);
|
|
|
|
//gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, theSmokeModelIndex, (int)(n * flDamage * 0.3), 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, 255, 200 );
|
|
|
|
}
|
|
|
|
// Passing no param resets all sounds
|
|
void EndJetpackEffects(int inIndex)
|
|
{
|
|
for(DLightListType::iterator theIter = gJetpackLights.begin(); theIter != gJetpackLights.end(); theIter++)
|
|
{
|
|
if((theIter->mIndex == inIndex) || (inIndex == -1))
|
|
{
|
|
// Mark it for deletion by telling it to die a long time ago
|
|
if(theIter->mLight)
|
|
{
|
|
theIter->mLight->die = 0;
|
|
}
|
|
gJetpackLights.erase(theIter);
|
|
|
|
vec3_t theOrigin;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inIndex, theOrigin, CHAN_BODY, "common/null.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_EndJetpack(struct event_args_s* args)
|
|
{
|
|
// find dlight in list
|
|
//int theIndex = args->entindex;
|
|
//EndJetpackEffects(theIndex);
|
|
}
|
|
|
|
void DrawCircleOnGroundAtPoint(vec3_t inOrigin, int inNumSides, int inStartAngle, int inRadius, float inR, float inG, float inB, float inA, bool inUseRedInstead, float inInnerRadius)
|
|
{
|
|
static HSPRITE theGreenSprite = 0;
|
|
if(!theGreenSprite)
|
|
theGreenSprite = SPR_Load("sprites/green.spr");
|
|
|
|
static HSPRITE theRedSprite = 0;
|
|
if(!theRedSprite)
|
|
theRedSprite = SPR_Load("sprites/red.spr");
|
|
|
|
HSPRITE theSprite = theGreenSprite;
|
|
if(inUseRedInstead)
|
|
theSprite = theRedSprite;
|
|
|
|
if(gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(theSprite), 0))
|
|
{
|
|
gEngfuncs.pTriAPI->CullFace( TRI_NONE );
|
|
|
|
gEngfuncs.pTriAPI->RenderMode( kRenderGlow );
|
|
//gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
|
|
gEngfuncs.pTriAPI->Color4f(inR, inG, inB, inA);
|
|
|
|
gEngfuncs.pTriAPI->Begin( TRI_TRIANGLES );
|
|
float theAngleIncrement = (2*M_PI)/inNumSides;
|
|
float theStartAngle = (2*M_PI)*(inStartAngle/360.0f);
|
|
|
|
for(int i = 0; i < inNumSides; i++)
|
|
{
|
|
for(int j = 0; j < 3; j++)
|
|
{
|
|
float thePoint[3];
|
|
float theCurrentPointAngle = theStartAngle + i*theAngleIncrement;
|
|
thePoint[0] = inOrigin[0] + inRadius*cos(theCurrentPointAngle);
|
|
thePoint[1] = inOrigin[1] + inRadius*sin(theCurrentPointAngle);
|
|
thePoint[2] = inOrigin[2];
|
|
|
|
float theNextPoint[3];
|
|
float theNextPointAngle = theStartAngle + (i+1)*theAngleIncrement;
|
|
theNextPoint[0] = inOrigin[0] + inRadius*cos(theNextPointAngle);
|
|
theNextPoint[1] = inOrigin[1] + inRadius*sin(theNextPointAngle);
|
|
theNextPoint[2] = inOrigin[2];
|
|
|
|
//gEngfuncs.pTriAPI->Color4f(inR, inG, inB, 1.0f);
|
|
//gEngfuncs.pTriAPI->Brightness( 1 );
|
|
gEngfuncs.pTriAPI->TexCoord2f(0, 0);
|
|
gEngfuncs.pTriAPI->Vertex3f( inOrigin[0], inOrigin[1], inOrigin[2] );
|
|
|
|
//gEngfuncs.pTriAPI->Color4f(inR, inG, inB, inA);
|
|
//gEngfuncs.pTriAPI->Brightness( 1 );
|
|
gEngfuncs.pTriAPI->TexCoord2f(0, 1);
|
|
gEngfuncs.pTriAPI->Vertex3f( theNextPoint[0], theNextPoint[1], theNextPoint[2] );
|
|
|
|
//gEngfuncs.pTriAPI->Color4f(inR, inG, inB, inA);
|
|
//gEngfuncs.pTriAPI->Brightness( 1 );
|
|
gEngfuncs.pTriAPI->TexCoord2f(1, 1);
|
|
gEngfuncs.pTriAPI->Vertex3f( thePoint[0], thePoint[1], thePoint[2] );
|
|
|
|
}
|
|
}
|
|
gEngfuncs.pTriAPI->End();
|
|
gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
|
|
}
|
|
}
|
|
|
|
//void DrawOrderDirectionIndicator(const AvHOrder& inOrder)
|
|
//{
|
|
// static HSPRITE theSprite = 0;
|
|
// if(!theSprite)
|
|
// theSprite = SPR_Load("sprites/320questionmark.spr");
|
|
//
|
|
// int theCurrentFrame = 0;
|
|
//
|
|
// //
|
|
// vec3_t theScreenPos;
|
|
// vec3_t theWorldPos;
|
|
// inOrder.GetLocation(theWorldPos);
|
|
|
|
// gEngfuncs.pTriAPI->WorldToScreen((float*)theWorldPos, (float*)theScreenPos);
|
|
//
|
|
// int theBaseX = theScreenPos.x*ScreenWidth;
|
|
// int theBaseY = theScreenPos.y*ScreenHeight;
|
|
//
|
|
// int theSpriteWidth = SPR_Width(theSprite, theCurrentFrame);
|
|
// int theSpriteHeight = SPR_Height(theSprite, theCurrentFrame);
|
|
//
|
|
// int theX = min(max(theSpriteWidth, theBaseX), ScreenWidth - theSpriteWidth);
|
|
// int theY = min(max(theSpriteHeight, theBaseY), ScreenHeight - theSpriteHeight);
|
|
//
|
|
// SPR_Set(theSprite, 255, 255, 255);
|
|
// SPR_DrawHoles((int)0, theX, theY, NULL);
|
|
|
|
// gHUD.SetOrderPos(theWorldPos);
|
|
//}
|
|
|
|
//void DrawOrdersForPlayers(EntityListType& inPlayerList)
|
|
//{
|
|
// OrderListType theOrders = gHUD.GetOrderList();
|
|
//
|
|
// gHUD.ClearOrderPos();
|
|
//
|
|
// // Run through the order list type
|
|
// for(OrderListType::iterator theIter = theOrders.begin(); theIter != theOrders.end(); theIter++)
|
|
// {
|
|
// // For each one, if the order is for a player in the inPlayerList, draw it
|
|
// vec3_t theOrderLocation;
|
|
// theIter->GetLocation(theOrderLocation);
|
|
//
|
|
// if(theIter->GetOrderTargetType() == ORDERTARGETTYPE_TARGET)
|
|
// {
|
|
// int theTargetIndex = theIter->GetTargetIndex();
|
|
// cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(theTargetIndex);
|
|
// if(theEntity)
|
|
// {
|
|
// VectorCopy(theEntity->origin, theOrderLocation);
|
|
// }
|
|
// }
|
|
//
|
|
// // Draw dotted line or something from relevant player to dest?
|
|
// bool theDrawWaypoint = false;
|
|
// EntityListType thePlayerList = theIter->GetReceivers();
|
|
// for(EntityListType::iterator thePlayerIter = thePlayerList.begin(); thePlayerIter != thePlayerList.end(); thePlayerIter++)
|
|
// {
|
|
// cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(*thePlayerIter);
|
|
// if(theEntity)
|
|
// {
|
|
// EntityListType::iterator theSearchIter = std::find(inPlayerList.begin(), inPlayerList.end(), *thePlayerIter);
|
|
// if(theSearchIter != inPlayerList.end())
|
|
// {
|
|
// //gEngfuncs.pEfxAPI->R_ParticleLine((float*)theEntity->origin, (float*)theOrderLocation, 0, 255, 0, .05f);
|
|
// theDrawWaypoint = true;
|
|
// }
|
|
// }
|
|
// }
|
|
// if(theDrawWaypoint)
|
|
// {
|
|
// float r, g, b, a;
|
|
// theIter->GetOrderColor(r, g, b, a);
|
|
//
|
|
// // This doesn't really use the color yet
|
|
// DrawCircleOnGroundAtPoint(theOrderLocation, 11, 0, 20, r, g, b, a, false, 0.0f);
|
|
//
|
|
// // Draw HUD indicator at this position
|
|
// DrawOrderDirectionIndicator(*theIter);
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
//void DrawBlips(const pVector& inView)
|
|
//{
|
|
// // Get enemy blips from HUD and draw 'em
|
|
// AvHVisibleBlipList& theEnemyBlipList = gHUD.GetEnemyBlipList();
|
|
// theEnemyBlipList.Draw(inView);
|
|
//
|
|
// // Get friendly blips from HUD and draw 'em
|
|
// AvHVisibleBlipList& theFriendlyBlipList = gHUD.GetFriendlyBlipList();
|
|
// theFriendlyBlipList.Draw(inView);
|
|
//}
|
|
/*
|
|
void DrawDebugEffects()
|
|
{
|
|
for(DebugPointListType::iterator theIter = gTriDebugLocations.begin(); theIter != gTriDebugLocations.end(); theIter++)
|
|
{
|
|
vec3_t thePosition;
|
|
thePosition.x = theIter->x;
|
|
thePosition.y = theIter->y;
|
|
thePosition.z = theIter->z;
|
|
int theRadius = theIter->mSize;
|
|
DrawCircleOnGroundAtPoint(thePosition, 3, 0, theRadius, 1, 1, 0, .5f, false, 0.0f);
|
|
}
|
|
for(DebugPointListType::iterator theIter = gSquareDebugLocations.begin(); theIter != gSquareDebugLocations.end(); theIter++)
|
|
{
|
|
vec3_t thePosition;
|
|
thePosition.x = theIter->x;
|
|
thePosition.y = theIter->y;
|
|
thePosition.z = theIter->z;
|
|
int theRadius = theIter->mSize;
|
|
DrawCircleOnGroundAtPoint(thePosition, 4, 0, theRadius, 1, 1, 0, .5f, false, 0.0f);
|
|
}
|
|
gSquareDebugLocations.clear();
|
|
|
|
// Run through particle systems, drawing a box around each one
|
|
|
|
// for(DebugEntityListType::iterator theCubeIter = gCubeDebugEntities.begin(); theCubeIter != gCubeDebugEntities.end(); theCubeIter++)
|
|
// {
|
|
// cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(*theCubeIter);
|
|
// if(theEntity)
|
|
// {
|
|
// Vector theStartPos = theEntity->curstate.origin + theEntity->curstate.mins;
|
|
// Vector theEndPos = theEntity->curstate.origin + theEntity->curstate.maxs;
|
|
// //gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&(theStartPos), (float *)&(theEndPos), 5.0, 0, 255, .5f );
|
|
// float theMiddleX = (theStartPos.x + theEndPos.x)/2.0f;
|
|
// float theMiddleY = (theStartPos.y + theEndPos.y)/2.0f;
|
|
// Vector thePoint;
|
|
// thePoint.x = theMiddleX;
|
|
// thePoint.y = theMiddleY;
|
|
// thePoint.z = theStartPos.z;
|
|
// DrawCircleOnGroundAtPoint(thePoint, 4, 45, 64, .8f, .8f, .8f, .5f, false, 0.0f);
|
|
//
|
|
// thePoint.z = theEndPos.z;
|
|
// DrawCircleOnGroundAtPoint(thePoint, 4, 45, 64, .8f, .8f, .8f, .5f, false, 0.0f);
|
|
// }
|
|
// }
|
|
}*/
|
|
|
|
void DrawMarineLight(const pVector& inView, vec3_t& inStartPos, vec3_t& inEndPos)
|
|
{
|
|
gEngfuncs.pEfxAPI->R_RocketTrail(inStartPos, inEndPos, 1);
|
|
|
|
// // Draw triangle strip that faces camera
|
|
// const float kBeamAlpha = .7f;
|
|
// const float kBeamWidth = 10;
|
|
//
|
|
// pVector up(0, 0, 1);
|
|
// pVector right = inView ^ up;
|
|
// right.normalize();
|
|
// pVector nup = right ^ inView;
|
|
// //pVector nup = inView ^ right;
|
|
//
|
|
// // The particles should face you unless constrained (this is for rain and the like)
|
|
// if(this->mConstrainPitch)
|
|
// nup = up;
|
|
//
|
|
// //right *= size_scale/2.0f;
|
|
// //nup *= size_scale/2.0f;
|
|
//
|
|
// // Quad draws v0, v1, v2, v3
|
|
// //pVector V0 = -(right + nup);
|
|
//
|
|
// // Upper left
|
|
// pVector V0 = -(right + nup);
|
|
// //V0 = -(right - nup);
|
|
// V0 = nup - right;
|
|
//
|
|
// // Lower left
|
|
// pVector V1 = -(right + nup);
|
|
//
|
|
// // Lower right
|
|
// pVector V2 = right + nup;
|
|
// V2 = right - nup;
|
|
//
|
|
// // Upper right
|
|
// pVector V3 = right - nup;
|
|
// V3 = right + nup;
|
|
//
|
|
// // Tri draws v0, v4, v3
|
|
// //pVector V4 = nup;
|
|
// pVector V4 = -nup;
|
|
//
|
|
// // Load red sprite
|
|
// //if(gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(this->mSprite), theTextureOffsetToUse))
|
|
// //{
|
|
// gEngfuncs.pTriAPI->Begin( TRI_TRIANGLES );
|
|
//
|
|
// gEngfuncs.pTriAPI->Color4f(1.0f, 0.0f, 0.0f, kBeamAlpha);
|
|
//
|
|
// //gEngfuncs.pTriAPI->TexCoord2f(0,0);
|
|
// pVector ver = p + sV0;
|
|
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
|
|
//
|
|
// //gEngfuncs.pTriAPI->TexCoord2f(.5,1);
|
|
// ver = p + sV4;
|
|
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
|
|
//
|
|
// //gEngfuncs.pTriAPI->TexCoord2f(1,0);
|
|
// ver = p + sV3;
|
|
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
|
|
//
|
|
// gEngfuncs.pTriAPI->End();
|
|
// //}
|
|
}
|
|
|
|
void DrawMarineLights(const pVector& inView)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, false );
|
|
|
|
// Store off the old count
|
|
gEngfuncs.pEventAPI->EV_PushPMStates();
|
|
|
|
// Now add in all of the players.
|
|
gEngfuncs.pEventAPI->EV_SetSolidPlayers(-1);
|
|
|
|
physent_t* theEntity = NULL;
|
|
int theNumEnts = pmove->numphysent;
|
|
for (int i = 0; i < theNumEnts; i++)
|
|
{
|
|
theEntity = gEngfuncs.pEventAPI->EV_GetPhysent(i);
|
|
|
|
// If player is a marine
|
|
if(theEntity->iuser3 == AVH_USER3_MARINE_PLAYER)
|
|
{
|
|
// Get middle of head
|
|
//theEntity->model->
|
|
//model->attachment = model->origin;
|
|
|
|
// Get eyepiece attachment
|
|
cl_entity_t* theClientEntity = gEngfuncs.GetEntityByIndex(theEntity->info);
|
|
if(theClientEntity)
|
|
{
|
|
Vector theHeadPos = theClientEntity->attachment[2];
|
|
|
|
// Get look direction
|
|
Vector theForward, theRight, theUp;
|
|
|
|
gEngfuncs.pfnAngleVectors(theClientEntity->angles, theForward, theRight, theUp);
|
|
Vector theAiming;
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
theAiming[i] = theForward[i] + theRight[i] + theUp[i];
|
|
}
|
|
|
|
// Build this line
|
|
Vector theStartPos = theHeadPos;
|
|
Vector theEndPos;
|
|
VectorMA(theStartPos, 8000, theAiming, theEndPos);
|
|
|
|
// Perform trace, ignore glass (!), ignore ourself
|
|
gEngfuncs.pEventAPI->EV_SetTraceHull(2);
|
|
//int theFoundEntity = theEntity->info;
|
|
int theFoundEntity = -1;
|
|
pmtrace_t tr;
|
|
|
|
bool theDone = false;
|
|
do
|
|
{
|
|
// NOTE: ** When implementing this again, put in check for infinite loop condition! **
|
|
|
|
// Run a traceline along this line until it hits
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace(theStartPos, theEndPos, PM_GLASS_IGNORE, theFoundEntity, &tr);
|
|
|
|
//if((tr.fraction >= (1.0f - kFloatTolerance)) || (tr.fraction == 0.0f)/*|| (theNumIterations > 100)*//* || (tr.fraction < kFloatTolerance)*/)
|
|
//{
|
|
// theDone = true;
|
|
//}
|
|
//else
|
|
//{
|
|
// // Offset a bit so we don't hit again
|
|
// VectorMA(tr.endpos, kHitOffsetAmount, theForward, theStartPos);
|
|
//}
|
|
|
|
if(tr.startsolid)
|
|
{
|
|
VectorMA(tr.endpos, kHitOffsetAmount, theForward, theStartPos);
|
|
}
|
|
else
|
|
{
|
|
theDone = true;
|
|
}
|
|
|
|
} while(!theDone);
|
|
|
|
// Draw red additive light along this line
|
|
DrawMarineLight(inView, theStartPos, tr.endpos);
|
|
}
|
|
}
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
}
|
|
|
|
//void DrawRangeIndicator()
|
|
//{
|
|
// Vector theCenter;
|
|
// bool theIsValid;
|
|
// float theRadius;
|
|
//
|
|
// if(gHUD.GetRangeDrawingInfo(theCenter, theRadius, theIsValid))
|
|
// {
|
|
// const float theCircleWidth = 20.0f;
|
|
// float theInnerRadius = theRadius - theCircleWidth;
|
|
//
|
|
// static theAngle = 0;
|
|
// DrawCircleOnGroundAtPoint(theCenter, theRadius/200, theAngle++, theRadius, 1.0f, 1.0f, 1.0f, 1.0f, !theIsValid, theInnerRadius);
|
|
// }
|
|
//}
|
|
|
|
//void UpdateJetpackLights()
|
|
//{
|
|
// for(DLightListType::iterator theIter = gJetpackLights.begin(); theIter != gJetpackLights.end(); theIter++)
|
|
// {
|
|
// // Treat locally differently
|
|
// int theIndex = theIter->mIndex;
|
|
// vec3_t theOrigin;
|
|
//
|
|
// if(theIndex == 0)
|
|
// {
|
|
// VectorCopy(gPredictedPlayerOrigin, theOrigin);
|
|
// }
|
|
// else
|
|
// {
|
|
// cl_entity_t* thePlayer = gEngfuncs.GetEntityByIndex(theIndex);
|
|
// if(thePlayer)
|
|
// {
|
|
// // Get known position of entity
|
|
// VectorCopy(thePlayer->origin, theOrigin);
|
|
// }
|
|
// else
|
|
// {
|
|
// ASSERT(false);
|
|
// }
|
|
// }
|
|
//
|
|
// VectorCopy(theOrigin, theIter->mLight->origin);
|
|
//
|
|
// // Make sure it still won't die
|
|
// theIter->mLight->die = gEngfuncs.GetClientTime() + kArbitraryLargeLightTime;
|
|
//
|
|
// // Update jetpack sound every once in awhile
|
|
// if(gEngfuncs.pfnRandomLong(0, 70) == 0)
|
|
// {
|
|
// gEngfuncs.pEventAPI->EV_PlaySound( theIndex, theOrigin, CHAN_BODY, kJetpackSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
void EV_WelderGeneralEffects(struct event_args_s* inArgs, const Vector& thePos)
|
|
{
|
|
int theIndex = inArgs->entindex;
|
|
cl_entity_t* thePlayer = GetEntity(theIndex);
|
|
|
|
// Don't play flashing effects if player is photosensitive
|
|
if(CVAR_GET_FLOAT(kvDynamicLights))
|
|
{
|
|
// Make flashing lights
|
|
int theLightIndex = 20; /* TODO: What do to about this index? */
|
|
dlight_t* theLight = gEngfuncs.pEfxAPI->CL_AllocDlight(theLightIndex);
|
|
VectorCopy (thePlayer->origin, theLight->origin);
|
|
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(theIndex));
|
|
|
|
theLight->radius = 180 + theUpgradeLevel*15;
|
|
theLight->color.r = 220;
|
|
theLight->color.g = 220;
|
|
theLight->color.b = 255;
|
|
|
|
// Have it die before it fires again, so it flickers on and off
|
|
theLight->die = gEngfuncs.GetClientTime() + BALANCE_VAR(kWelderROF)/2.2f;
|
|
}
|
|
|
|
// TODO: Apply burn mark
|
|
//gEngfuncs.pEfxAPI->R_DecalShoot( gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( "{shot1" ) ),
|
|
// gEngfuncs.pEventAPI->EV_IndexFromTrace(&theTraceResult),
|
|
// 0,
|
|
// theTraceResult.endpos,
|
|
// 0 );
|
|
|
|
// emit heavy smoke
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsWelderSmoke, thePos);
|
|
}
|
|
}
|
|
|
|
void EV_WelderHitEffects(struct event_args_s* inArgs, const Vector& thePos)
|
|
{
|
|
int theIndex = inArgs->entindex;
|
|
cl_entity_t* thePlayer = GetEntity(theIndex);
|
|
|
|
// Fire sparks
|
|
//Vector theVector(inPev->origin);
|
|
//float theRandomFloat = RANDOM_FLOAT(0.5F, 1.0f);
|
|
//float theHeight = theRandomFloat*(inPev->absmax.z - inPev->absmin.z);
|
|
|
|
//gEngfuncs.pEfxAPI->R_SparkShower(theTraceResult.endpos);
|
|
//gEngfuncs.pEfxAPI->R_SparkShower(theTraceResult.endpos);
|
|
|
|
// Fire heavy smoke
|
|
//if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
//{
|
|
// AvHParticleSystemManager::Instance()->CreateParticleSystem(5, theTraceResult.endpos);
|
|
//}
|
|
|
|
// Generate still plasma
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsWelderBluePlasma, thePos);
|
|
}
|
|
|
|
// Generate plasma shower
|
|
if(gEngfuncs.pfnRandomLong(0, 8) == 0)
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsWelderBluePlasmaDrops, thePos);
|
|
}
|
|
|
|
// Generate spark shower
|
|
float theFloatVec[3];
|
|
thePos.CopyToArray(theFloatVec);
|
|
|
|
int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(AVH_USER3_MARINE_PLAYER, GetUpgradeState(theIndex));
|
|
for(int i = 0; i < theUpgradeLevel+1; i++)
|
|
{
|
|
gEngfuncs.pEfxAPI->R_SparkShower(theFloatVec);
|
|
}
|
|
}
|
|
|
|
void EV_Welder(struct event_args_s* inArgs)
|
|
{
|
|
// This event means the welder is on, but we don't know if we're hitting anything or are constructing
|
|
int theIndex = inArgs->entindex;
|
|
cl_entity_t* thePlayer = GetEntity(theIndex);
|
|
|
|
// Hot blue flame
|
|
|
|
// See if we're hitting something and playback smoke and sparks if so
|
|
// Trace to see where the sparks should emanate from
|
|
vec3_t vecSrc;
|
|
vec3_t origin;
|
|
vec3_t forward, right, up;
|
|
|
|
gEngfuncs.pfnAngleVectors(inArgs->angles, forward, right, up);
|
|
|
|
// Calculate theStartPos, taking into account the welder barrel length
|
|
vec3_t theStartPos, theEndPos;
|
|
EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
VectorMA(vecSrc, kWelderBarrelLength, forward, theStartPos);
|
|
|
|
// Calculate theEndPos, welder range along facing
|
|
theEndPos = theStartPos + forward * BALANCE_VAR(kWelderRange);
|
|
|
|
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
|
|
|
|
// Store off the old count
|
|
gEngfuncs.pEventAPI->EV_PushPMStates();
|
|
|
|
// Now add in all of the players.
|
|
//int theNumPlayers = gEngfuncs.GetMaxClients();
|
|
//gEngfuncs.pEventAPI->EV_SetSolidPlayers ( -1 );
|
|
|
|
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(theIndex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
// Don't hit ourselves, but how? Setting this to theIndex isn't right, we need the other kind of index, but how to get it?
|
|
// For now this function will cause the welder to hit the player using the welder when aiming down, sigh
|
|
int theEntityToIngore = -1;
|
|
|
|
struct pmtrace_s theTraceResult;
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace(theStartPos, theEndPos, PM_NORMAL, theEntityToIngore, &theTraceResult);
|
|
if(theTraceResult.fraction != 1.0f)
|
|
{
|
|
// Adjust the trace so it's offset a bit towards us so particles aren't clipped away
|
|
//Vector theResult = theTraceResult.endpos;//theStartPos + forward*(theTraceResult.fraction - 0.001);
|
|
Vector theResult = theStartPos + forward*((theTraceResult.fraction - 0.1f)*BALANCE_VAR(kWelderRange));
|
|
|
|
EV_WelderGeneralEffects(inArgs, theResult);
|
|
EV_WelderHitEffects(inArgs, theResult);
|
|
|
|
// Update status bar if possible
|
|
physent_t* thePhysEnt = gEngfuncs.pEventAPI->EV_GetPhysent( theTraceResult.ent );
|
|
//if(!thePhysEnt || !thePhysEnt->player)
|
|
if(thePhysEnt /*&& !thePhysEnt->player*/)
|
|
{
|
|
bool theIsBuilding;
|
|
bool theIsResearching;
|
|
float thePercentage;
|
|
AvHSHUGetBuildResearchState(thePhysEnt->iuser3, thePhysEnt->iuser4, thePhysEnt->fuser1, theIsBuilding, theIsResearching, thePercentage);
|
|
|
|
// if(thePhysEnt->iuser3 == AVH_USER3_WELD)
|
|
// {
|
|
// if((thePercentage < 1.0f) && (thePercentage != -1))
|
|
// {
|
|
// gHUD.SetProgressStatus(thePercentage);
|
|
// }
|
|
// else
|
|
// {
|
|
// gHUD.HideProgressStatus();
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
// Fire light smoke from muzzle
|
|
else //if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
// TODO: emit this from the actual end of the barrel
|
|
//AvHParticleSystemManager::Instance()->CreateParticleSystem(5, theStartPos + forward*10);
|
|
|
|
EV_WelderGeneralEffects(inArgs, theStartPos + (forward*(.3f*BALANCE_VAR(kWelderRange))));
|
|
|
|
// Stop playing hit sound
|
|
//gEngfuncs.pEventAPI->EV_StopSound( theIndex, CHAN_WEAPON, kWeldingHitSound);
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
}
|
|
|
|
//void ClientPlayRandomConstructionSound(struct event_args_s* inArgs)
|
|
//{
|
|
// int theRandomInteger = gEngfuncs.pfnRandomLong(1, 5);
|
|
// char theSoundName[128];
|
|
// sprintf(theSoundName, kMarineConstructionSounds, theRandomInteger);
|
|
//
|
|
// int thePitch = gEngfuncs.pfnRandomLong(100, 125);
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_BODY, theSoundName, 1, ATTN_NORM, SND_CHANGE_PITCH | SND_CHANGE_VOL, thePitch);
|
|
//}
|
|
|
|
// This event means the welder is constructing something, it's fired by the server
|
|
void EV_WelderConst(struct event_args_s* inArgs)
|
|
{
|
|
int theIndex = inArgs->entindex;
|
|
cl_entity_t* thePlayer = GetEntity(theIndex);
|
|
|
|
switch(inArgs->iparam1)
|
|
{
|
|
case 0://Start playing loop sound.
|
|
gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_BODY, kWeldingHitSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
break;
|
|
case 1://Stop playing loop sound.
|
|
gEngfuncs.pEventAPI->EV_StopSound( inArgs->entindex, CHAN_BODY, kWeldingHitSound);
|
|
gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_AUTO, kWeldingStopSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EV_WelderStart(struct event_args_s* inArgs)
|
|
{
|
|
int theIndex = inArgs->entindex;
|
|
cl_entity_t* thePlayer = GetEntity(theIndex);
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_WEAPON, kWeldingSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
|
|
void EV_WelderEnd(struct event_args_s* inArgs)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_StopSound( inArgs->entindex, CHAN_WEAPON, kWeldingSound);
|
|
|
|
// Hide the status, it will be shown below if possible
|
|
gHUD.HideProgressStatus();
|
|
}
|
|
|
|
//void EV_OverwatchStart(struct event_args_s* inArgs)
|
|
//{
|
|
// cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
// gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_VOICE, kOverwatchStartSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//}
|
|
//
|
|
//void EV_OverwatchEnd(struct event_args_s* inArgs)
|
|
//{
|
|
// cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
// gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_VOICE, kOverwatchEndSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//}
|
|
|
|
void EV_Regeneration(struct event_args_s* inArgs)
|
|
{
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
ASSERT(thePlayer);
|
|
|
|
float theVolume = inArgs->fparam1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, thePlayer->origin, CHAN_AUTO, kRegenerationSound, theVolume, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
|
|
void EV_StartCloak(struct event_args_s* inArgs)
|
|
{
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
ASSERT(thePlayer);
|
|
|
|
float theVolume = inArgs->fparam1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, thePlayer->origin, CHAN_AUTO, kStartCloakSound, theVolume, .4, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
|
|
void EV_EndCloak(struct event_args_s* inArgs)
|
|
{
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
ASSERT(thePlayer);
|
|
|
|
float theVolume = inArgs->fparam1;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, thePlayer->origin, CHAN_AUTO, kEndCloakSound, theVolume, .4, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
|
|
//void EV_WallJump(struct event_args_s* inArgs)
|
|
//{
|
|
// cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
// gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_VOICE, kWallJumpSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//}
|
|
|
|
void EV_Flight(struct event_args_s* inArgs)
|
|
{
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, thePlayer->origin, CHAN_AUTO, kEndCloakSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
//gEngfuncs.pEventAPI->EV_PlaySound( inArgs->entindex, thePlayer->origin, CHAN_AUTO, kStartCloakSound/*kWingFlapSound*/, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
|
|
void TeleportCallback( struct tempent_s *ent, float frametime, float currenttime)
|
|
{
|
|
}
|
|
|
|
void EV_Teleport(struct event_args_s* inArgs)
|
|
{
|
|
// Create a temp entity of this player and fade him out!
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
|
|
// // Kill earlier effect so the sound plays right?
|
|
// int idx = inArgs->entindex;
|
|
// gEngfuncs.pEventAPI->EV_KillEvents(idx, kTeleportEvent);
|
|
|
|
// TEMPENTITY* theTempEnt = gEngfuncs.pEfxAPI->CL_TentEntAllocCustom( (float*)inArgs->origin, thePlayer->model, 0, TeleportCallback);
|
|
// if(theTempEnt)
|
|
// {
|
|
// VectorCopy(inArgs->origin, theTempEnt->entity.origin);
|
|
// VectorCopy(inArgs->angles, theTempEnt->entity.angles);
|
|
//
|
|
// theTempEnt->flags |= FTENT_FADEOUT;
|
|
// theTempEnt->entity.baseline.renderamt = 255;
|
|
// theTempEnt->entity.curstate.renderfx = kRenderFxStrobeFaster;
|
|
// theTempEnt->fadeSpeed = 1.3f;
|
|
// theTempEnt->entity.curstate.movetype = MOVETYPE_NONE;
|
|
//
|
|
// theTempEnt->entity.curstate.modelindex = thePlayer->curstate.modelindex;
|
|
// theTempEnt->entity.curstate.frame = thePlayer->curstate.frame;
|
|
// theTempEnt->entity.curstate.colormap = thePlayer->curstate.colormap;
|
|
// theTempEnt->entity.curstate.skin = thePlayer->curstate.skin;
|
|
// theTempEnt->entity.curstate.framerate = thePlayer->curstate.framerate;
|
|
// theTempEnt->entity.curstate.body = thePlayer->curstate.body;
|
|
// theTempEnt->entity.curstate.weaponmodel = thePlayer->curstate.weaponmodel;
|
|
// theTempEnt->entity.curstate.sequence = thePlayer->curstate.sequence;
|
|
// theTempEnt->entity.curstate.gaitsequence = thePlayer->curstate.gaitsequence;
|
|
// theTempEnt->entity.curstate.usehull = thePlayer->curstate.usehull;
|
|
// theTempEnt->entity.curstate.playerclass = thePlayer->curstate.playerclass;
|
|
// theTempEnt->entity.curstate.animtime = thePlayer->curstate.animtime;
|
|
//
|
|
// memcpy(&theTempEnt->entity.curstate.controller[0], &thePlayer->curstate.controller[0], 4 * sizeof( byte ));
|
|
// memcpy(&theTempEnt->entity.curstate.blending[0], &thePlayer->curstate.blending[0], 2 * sizeof( byte ));
|
|
|
|
if(CVAR_GET_FLOAT(kvDynamicLights))
|
|
{
|
|
dlight_t* theDLight = gEngfuncs.pEfxAPI->CL_AllocDlight(1);
|
|
VectorCopy(inArgs->origin, theDLight->origin);
|
|
theDLight->radius = 200;
|
|
theDLight->color.r = 180;
|
|
theDLight->color.g = 180;
|
|
theDLight->color.b = 250;
|
|
|
|
// don't die for forseeable future
|
|
theDLight->die = gEngfuncs.GetClientTime() + .25f;
|
|
}
|
|
|
|
// Draw cool particle system
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsTeleport, inArgs->origin);
|
|
// }
|
|
}
|
|
|
|
void EV_PhaseIn(struct event_args_s* inArgs)
|
|
{
|
|
// Create a temp entity of this player and fade him out!
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kPhaseInSound, 1, ATTN_NORM, 0, thePitch);
|
|
|
|
if(CVAR_GET_FLOAT(kvDynamicLights))
|
|
{
|
|
dlight_t* theDLight = gEngfuncs.pEfxAPI->CL_AllocDlight(1);
|
|
VectorCopy(inArgs->origin, theDLight->origin);
|
|
theDLight->radius = 200;
|
|
theDLight->color.r = 180;
|
|
theDLight->color.g = 180;
|
|
theDLight->color.b = 250;
|
|
|
|
// don't die for forseeable future
|
|
theDLight->die = gEngfuncs.GetClientTime() + 1.0f;
|
|
}
|
|
|
|
// Draw cool particle system
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsPhaseIn, inArgs->origin);
|
|
}
|
|
|
|
void EV_SiegeHit(struct event_args_s* inArgs)
|
|
{
|
|
char* theSoundToPlay = kSiegeHitSound1;
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 1)
|
|
{
|
|
theSoundToPlay = kSiegeHitSound2;
|
|
}
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_BODY, theSoundToPlay, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
gEngfuncs.pEfxAPI->R_BlobExplosion(inArgs->origin);
|
|
}
|
|
|
|
void EV_SiegeViewHit(struct event_args_s* inArgs)
|
|
{
|
|
const float kPunchRange = 5.0f;
|
|
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat(-kPunchRange, kPunchRange));
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat(-kPunchRange, kPunchRange));
|
|
V_PunchAxis(2, gEngfuncs.pfnRandomFloat(-kPunchRange, kPunchRange));
|
|
}
|
|
|
|
void EV_CommandPoints(struct event_args_s* inArgs)
|
|
{
|
|
if(CVAR_GET_FLOAT(kvDynamicLights))
|
|
{
|
|
dlight_t* theDLight = gEngfuncs.pEfxAPI->CL_AllocDlight(1);
|
|
VectorCopy(inArgs->origin, theDLight->origin);
|
|
theDLight->radius = 60;
|
|
theDLight->color.r = 100;
|
|
theDLight->color.g = 250;
|
|
theDLight->color.b = 100;
|
|
|
|
// don't die for forseeable future
|
|
theDLight->die = gEngfuncs.GetClientTime() + 1.0f;
|
|
}
|
|
}
|
|
|
|
void EV_AlienSightOn(struct event_args_s* inArgs)
|
|
{
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kAlienSightOnSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
}
|
|
|
|
void EV_AlienSightOff(struct event_args_s* inArgs)
|
|
{
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kAlienSightOffSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
}
|
|
|
|
void EV_ParasiteGun(struct event_args_s* inArgs)
|
|
{
|
|
// Sharp falloff, so it's only heard at very close and by the firer
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kParasiteFireSound, .4f*inArgs->fparam1, .2, 0, thePitch);
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void EV_BlinkSuccess(struct event_args_s* inArgs)
|
|
{
|
|
// Create particle at origin, but also at angles (interpret as dest)
|
|
//AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsBlinkEffect, inArgs->origin);
|
|
//AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsBlinkEffect, inArgs->angles);
|
|
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kBlinkSuccessSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
//gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->angles, CHAN_WEAPON, kBlinkSuccessSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
}
|
|
|
|
void EV_DivineWind(struct event_args_s* inArgs)
|
|
{
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
|
|
float theSilenceVolumeFactor = AvHPlayerUpgrade::GetSilenceVolumeLevel((AvHUser3)thePlayer->curstate.iuser3, thePlayer->curstate.iuser4);
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kDivineWindFireSound, theSilenceVolumeFactor, ATTN_IDLE, 0, thePitch);
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void BileBombHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(ent->entity.index, ptr->endpos, CHAN_AUTO, kBileBombHitSound, 1, ATTN_IDLE, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsBilebomb, ptr->endpos, &(ptr->plane.normal));
|
|
}
|
|
|
|
void EV_BileBomb(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = inArgs->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kBileBombFireSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
|
|
vec3_t theBombAngles;
|
|
VectorAngles(forward, theBombAngles);
|
|
|
|
theBombAngles.y -= 90;
|
|
|
|
// Fire bomb
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempModel(inArgs->origin, forward, theBombAngles, 100, gEngfuncs.pEventAPI->EV_FindModelIndex(kBileBombProjectileModel), 0);
|
|
if(theTempEntity)
|
|
{
|
|
theTempEntity->hitcallback = BileBombHit;
|
|
theTempEntity->flags = (FTENT_GRAVITY | FTENT_COLLIDEALL | FTENT_COLLIDEKILL | FTENT_PERSIST);
|
|
theTempEntity->die += 5;
|
|
theTempEntity->entity.curstate.framerate = 30;
|
|
//theTempEntity->frameMax = 4;//theModel->numframes;
|
|
theTempEntity->clientIndex = inArgs->entindex; // Entity to ignore collisions with
|
|
|
|
Vector theAiming = forward;// + up;
|
|
VectorNormalize(theAiming);
|
|
|
|
Vector theStartVelocity;
|
|
VectorMA(Vector(0, 0, 0), kBileBombVelocity, theAiming, theStartVelocity);
|
|
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
}
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
float theHalfSpread = kBileBombPunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
}
|
|
|
|
void AcidRocketHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
{
|
|
char* theSoundToPlay = kAcidRocketHitSound;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(ent->entity.index, ptr->endpos, CHAN_AUTO, theSoundToPlay, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsAcidHitEffect, ptr->endpos, &(ptr->plane.normal));
|
|
}
|
|
|
|
void EV_AcidRocket(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
// Figure out which weapon description to assocate this weapon with
|
|
int theWeaponIndex = inArgs->iparam1;
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
int thePitch = gEngfuncs.pfnRandomLong(75, 150);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_AUTO, kAcidRocketFireSound, inArgs->fparam1, ATTN_IDLE, 0, thePitch);
|
|
|
|
vec3_t theRocketAngles;
|
|
VectorAngles(forward, theRocketAngles);
|
|
|
|
vec3_t theGunPosition;
|
|
EV_GetGunPosition(inArgs, theGunPosition, inArgs->origin);
|
|
|
|
Vector theRocketOrigin;
|
|
VectorMA(theGunPosition, kAcidRocketBarrelLength, forward, theRocketOrigin);
|
|
|
|
// Projectile is rotated a bit
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempModel(theRocketOrigin, forward, theRocketAngles, 100, gEngfuncs.pEventAPI->EV_FindModelIndex(kAcidRocketProjectileModel), 0);
|
|
if(theTempEntity)
|
|
{
|
|
theTempEntity->hitcallback = AcidRocketHit;
|
|
theTempEntity->flags = (FTENT_COLLIDEALL | FTENT_COLLIDEKILL | FTENT_PERSIST);
|
|
theTempEntity->entity.curstate.framerate = 30;
|
|
theTempEntity->frameMax = 4;//theModel->numframes;
|
|
|
|
// Temp entities interpret baseline origin as velocity.
|
|
Vector theBaseVelocity;
|
|
VectorScale(inArgs->velocity, kAcidRocketParentVelocityScalar, theBaseVelocity);
|
|
|
|
Vector theStartVelocity;
|
|
VectorMA(theBaseVelocity, kAcidRocketVelocity, forward, theStartVelocity);
|
|
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
}
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
float theHalfSpread = kAcidRocketPunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void UpdateStomp(TEMPENTITY* inEntity, float frametime, float inCurrentTime)
|
|
{
|
|
float theTimeScalar = (inCurrentTime - inEntity->entity.curstate.fuser1)/(inEntity->entity.curstate.fuser2/inEntity->entity.curstate.fuser1);
|
|
theTimeScalar = max(min(theTimeScalar, 1.0f), 0.0f);
|
|
|
|
// Fade it out according to lifetime
|
|
int theAlpha = (1.0f - theTimeScalar)*kStompModelRenderAmount;
|
|
inEntity->entity.curstate.renderamt = theAlpha;
|
|
|
|
// Don't create at end of trail
|
|
if(theTimeScalar < .7f)
|
|
{
|
|
// Every once in a awhile, create a smoke puff
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsStompSmoke, inEntity->entity.origin);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_Stomp(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
Vector theStartPos;
|
|
VectorCopy(inArgs->origin, theStartPos);
|
|
|
|
// Not sure why this is necessary, AvHStomp::GetStompOrigin() should take care of it
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
if(theLocalPlayer)
|
|
{
|
|
float theZOffset = theLocalPlayer->curstate.mins.z;
|
|
theStartPos.z += theZOffset;
|
|
}
|
|
}
|
|
|
|
// Initial velocity store in angles, to make sure event and server entity match up
|
|
Vector theStartVelocity;
|
|
VectorCopy(inArgs->angles, theStartVelocity);
|
|
|
|
char* theSoundToPlay = kStompFireSound;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, theStartPos, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
vec3_t up, right, forward, vecSrc;//, origin;
|
|
|
|
// VectorCopy( inArgs->origin, origin );
|
|
gEngfuncs.pfnAngleVectors(inArgs->angles, forward, right, up);
|
|
|
|
// Create stomp projectile that flies forward, going through objects and stunning anyone it touches
|
|
|
|
vec3_t theStompAngles;
|
|
VectorAngles(forward, theStompAngles);
|
|
|
|
// Always draw level
|
|
theStompAngles.x = 0;
|
|
|
|
// Projectile artwork is oriented down the wrong axis
|
|
theStompAngles.y -= 180;
|
|
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempModel(theStartPos, forward, theStompAngles, 100, gEngfuncs.pEventAPI->EV_FindModelIndex(kStompProjectileModel), 0);
|
|
if(theTempEntity)
|
|
{
|
|
// vec3_t theStartPos, theEndPos;
|
|
// EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
// VectorMA(vecSrc, kStompBarrelLength, forward, theStartPos);
|
|
|
|
VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
//theTempEntity->hitcallback = StompHit;
|
|
theTempEntity->flags = (FTENT_PERSIST | FTENT_CLIENTCUSTOM/*| FTENT_SMOKETRAIL | FTENT_FADEOUT*/);
|
|
theTempEntity->callback = UpdateStomp;
|
|
|
|
// Set time created and time to expire so we can blend it in UpdateStomp
|
|
theTempEntity->entity.curstate.fuser1 = gHUD.m_flTime;
|
|
theTempEntity->entity.curstate.fuser2 = gHUD.m_flTime + kStompProjectileLifetime; // estimated end time of animation
|
|
|
|
theTempEntity->die = gEngfuncs.GetClientTime() + kStompProjectileLifetime;
|
|
theTempEntity->bounceFactor = 0;
|
|
|
|
theTempEntity->entity.curstate.rendermode = kRenderTransAdd;
|
|
theTempEntity->entity.curstate.renderamt = kStompModelRenderAmount;
|
|
|
|
//theTempEntity->entity.curstate.framerate = 30;
|
|
//theTempEntity->frameMax = 4;//theModel->numframes;
|
|
|
|
// Temp entities interpret baseline origin as velocity.
|
|
|
|
// Zero out vertical component as it's a ground stomp
|
|
forward[2] = 0.0f;
|
|
|
|
// Send shockwave in direction player is looking, but always make it go kStompProjectilVelocity
|
|
VectorNormalize(forward);
|
|
|
|
Vector theStartVelocity;
|
|
VectorScale(forward, kStompProjectileVelocity, theStartVelocity);
|
|
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
|
|
// Set orientation
|
|
//VectorCopy(inArgs->angles, theTempEntity->entity.angles);
|
|
}
|
|
|
|
// Create stomp effect at Onos
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsStompEffect, theStartPos);
|
|
}
|
|
|
|
void EV_Devour(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
char* theSoundToPlay = kDevourFireSound;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void EV_Leap(struct event_args_s* inArgs)
|
|
{
|
|
char* theSoundToPlay = kLeapSound;
|
|
|
|
|
|
if (EV_IsSpec(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
if (!EV_IsLocal(inArgs->entindex)) {
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
}
|
|
}
|
|
|
|
void EV_Charge(struct event_args_s* inArgs)
|
|
{
|
|
char* theSoundToPlay = kChargeSound;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
//We're sending a leap event.
|
|
void EV_Ability(struct event_args_s* inArgs)
|
|
{
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
gHUD.SetAlienAbility((AvHMessageID)inArgs->iparam1);
|
|
}
|
|
|
|
|
|
|
|
//physent_t* GetEntity(int inPhysIndex)
|
|
//{
|
|
// return gEngfuncs.pEventAPI->EV_GetPhysent( inPhysIndex );
|
|
//}
|
|
|
|
|
|
void EV_Select(struct event_args_s* args)
|
|
{
|
|
gSelectionHelper.ProcessPendingSelections();
|
|
}
|
|
|
|
|
|
void EV_Bite(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 1);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
theSoundToPlay = kBiteSound;
|
|
break;
|
|
//case 1:
|
|
// theSoundToPlay = kBiteSound2;
|
|
// break;
|
|
}
|
|
|
|
|
|
const int kBasePitch = 80;
|
|
const int kVariablePitchRange = 0x0;
|
|
|
|
const int kBiteAdrenPitchFactor = 30;
|
|
|
|
int theRandomPitch = gEngfuncs.pfnRandomLong( 0, kVariablePitchRange );
|
|
int thePitch = kBasePitch + (inArgs->fparam1*kBiteAdrenPitchFactor) + theRandomPitch;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, thePitch);
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
float theHalfSpread = kBitePunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
PlayMeleeHitEffects(inArgs, BALANCE_VAR(kBiteRange), kBiteHitSound1);
|
|
}
|
|
else
|
|
{
|
|
PlayMeleeHitEffects(inArgs, BALANCE_VAR(kBiteRange), kBiteHitSound2);
|
|
}
|
|
}
|
|
|
|
|
|
void EV_Bite2(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 1);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
theSoundToPlay = kBite2Sound;
|
|
break;
|
|
//case 1:
|
|
// theSoundToPlay = kBiteSound2;
|
|
// break;
|
|
}
|
|
|
|
|
|
const int kBasePitch = 80;
|
|
const int kVariablePitchRange = 0x0;
|
|
|
|
const int kBiteAdrenPitchFactor = 30;
|
|
|
|
int theRandomPitch = gEngfuncs.pfnRandomLong( 0, kVariablePitchRange );
|
|
int thePitch = kBasePitch + (inArgs->fparam1*kBiteAdrenPitchFactor) + theRandomPitch;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, thePitch);
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
// gEngfuncs.pEventAPI->EV_WeaponAnimation(ANIM_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2);
|
|
|
|
float theHalfSpread = kBitePunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
if(gEngfuncs.pfnRandomLong(0, 1) == 0)
|
|
{
|
|
PlayMeleeHitEffects(inArgs, BALANCE_VAR(kBiteRange), kBiteHitSound1);
|
|
}
|
|
else
|
|
{
|
|
PlayMeleeHitEffects(inArgs, BALANCE_VAR(kBiteRange), kBiteHitSound2);
|
|
}
|
|
}
|
|
|
|
|
|
void EV_BuildGun(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 1);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
theSoundToPlay = kBuildingGunSound1;
|
|
break;
|
|
case 1:
|
|
theSoundToPlay = kBuildingGunSound2;
|
|
break;
|
|
}
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// General x-punch axis
|
|
if (EV_IsLocal(idx))
|
|
{
|
|
// gEngfuncs.pEventAPI->EV_WeaponAnimation(ANIM_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2);
|
|
|
|
float theHalfSpread = kBuildingGunPunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
V_PunchAxis(1, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_HealingSpray(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
// Play attack sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, kHealingSpraySound, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Load model
|
|
//int theModelIndex;
|
|
//struct model_s* theModel = gEngfuncs.CL_LoadModel(kWebProjectileSprite, &theModelIndex);
|
|
//if(theModel)
|
|
//{
|
|
// Create some spray effect
|
|
//gEngfuncs.pEfxAPI->R_Sprite_Spray(inArgs->origin, forward, theModelIndex, 15, 100, 2);
|
|
//vec3_t theEndPoint;
|
|
//VectorMA(inArgs->origin, kHealingSprayRange, forward, theEndPoint);
|
|
//gEngfuncs.pEfxAPI->R_BeamLightning(inArgs->origin, theEndPoint, theModelIndex, .5f, 10, 1.0f, 1.0f, 1.0f);
|
|
//}
|
|
|
|
|
|
vec3_t theStartPos;
|
|
EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
VectorMA(vecSrc, kHealingSprayBarrelLength, forward, theStartPos);
|
|
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsBacteriaSpray, theStartPos);
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void EV_Metabolize(struct event_args_s* inArgs)
|
|
{
|
|
char* theSoundToPlay = "";
|
|
|
|
int theRandomSound = gEngfuncs.pfnRandomLong(0, 2);
|
|
switch(theRandomSound)
|
|
{
|
|
case 0:
|
|
theSoundToPlay = kMetabolizeFireSound1;
|
|
break;
|
|
case 1:
|
|
theSoundToPlay = kMetabolizeFireSound2;
|
|
break;
|
|
case 2:
|
|
theSoundToPlay = kMetabolizeFireSound3;
|
|
break;
|
|
}
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, theSoundToPlay, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, kMetabolizeFireSound, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void EV_MetabolizeSuccess(struct event_args_s* inArgs)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, kMetabolizeSuccessSound, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void WebHit(struct tempent_s* ent, struct pmtrace_s* ptr)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(ent->entity.index, ptr->endpos, CHAN_AUTO, kWebStrandHitSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//gEngfuncs.pEventAPI->EV_PlaySound(ent->entity.index, ptr->endpos, CHAN_AUTO, kWebSpinSound1, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
if(ptr && ent)
|
|
{
|
|
ent->die = gEngfuncs.GetClientTime();
|
|
|
|
//AvHParticleSystemManager::Instance()->CreateParticleSystem(kpsSpitHit, ptr->endpos, &(ptr->plane.normal));
|
|
|
|
// Create splat here too
|
|
CreateDecal(ptr);
|
|
}
|
|
}
|
|
|
|
|
|
void EV_SpinWeb(struct event_args_s* inArgs)
|
|
{
|
|
ASSERT(inArgs);
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
|
|
// Play attack sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, kWebSpinSound1, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Fire spit glob
|
|
int theModelIndex;
|
|
struct model_s* theModel = gEngfuncs.CL_LoadModel(kWebProjectileSprite, &theModelIndex);
|
|
if(theModel)
|
|
{
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(gPredictedPlayerOrigin, theModel);
|
|
if(theTempEntity)
|
|
{
|
|
vec3_t theStartPos, theEndPos;
|
|
EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
VectorMA(vecSrc, kSpitGBarrelLength, forward, theStartPos);
|
|
|
|
VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
//theTempEntity->die += kSpitLifetime;
|
|
theTempEntity->hitcallback = WebHit;
|
|
theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP/* | FTENT_PERSIST*/);
|
|
theTempEntity->clientIndex = inArgs->entindex; // Entity to ignore collisions with
|
|
theTempEntity->entity.curstate.framerate = 30;
|
|
theTempEntity->frameMax = 4;//theModel->numframes;
|
|
|
|
// Temp entities interpret baseline origin as velocity.
|
|
Vector theBaseVelocity;
|
|
VectorScale(inArgs->velocity, kWebProjectileParentVelocityScalar, theBaseVelocity);
|
|
|
|
Vector theStartVelocity;
|
|
VectorMA(theBaseVelocity, kWebProjectileVelocity, forward, theStartVelocity);
|
|
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
}
|
|
}
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
float theHalfSpread = kWebGXPunch/2.0f;
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
//void EV_Babbler(struct event_args_s* inArgs)
|
|
//{
|
|
// ASSERT(inArgs);
|
|
//
|
|
// // Play attack animation and add muzzle flash
|
|
// int idx = inArgs->entindex;
|
|
//
|
|
// // Play attack sound
|
|
// gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_WEAPON, kBabblerGunSound, inArgs->fparam1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
//
|
|
// if ( EV_IsLocal( idx ) )
|
|
// {
|
|
// float theHalfSpread = kBabblerXPunch/2.0f;
|
|
// if(theHalfSpread > 0.0f)
|
|
// {
|
|
// V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
// }
|
|
//
|
|
// gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
// }
|
|
//}
|
|
|
|
|
|
|
|
void EV_PrimalScream(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
// Play attack sound
|
|
|
|
// You can hear this waaay far off
|
|
float theFalloffFactor = .5f;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, inArgs->origin, CHAN_VOICE, kPrimalScreamSound, 1.0f, theFalloffFactor, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
if (EV_IsLocal(inArgs->entindex))
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
void EV_StopScream(struct event_args_s* inArgs)
|
|
{
|
|
int idx = inArgs->entindex;
|
|
|
|
gEngfuncs.pEventAPI->EV_StopSound(idx, CHAN_VOICE, kPrimalScreamSound);
|
|
}
|
|
|
|
|
|
void EV_SpikeGun(struct event_args_s* inArgs)
|
|
{
|
|
//static int theTracerCount[ 32 ];
|
|
|
|
// Play attack animation and add muzzle flash
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t up, right, forward;
|
|
|
|
idx = inArgs->entindex;
|
|
VectorCopy( inArgs->origin, origin );
|
|
VectorCopy( inArgs->angles, angles );
|
|
VectorCopy( inArgs->velocity, velocity );
|
|
|
|
//AngleVectors( angles, forward, right, up );
|
|
gEngfuncs.pfnAngleVectors(angles, forward, right, up);
|
|
|
|
// if ( EV_IsLocal( idx ) )
|
|
// {
|
|
// gEngfuncs.pEventAPI->EV_WeaponAnimation(5 + + gEngfuncs.pfnRandomLong(0,2), 2);
|
|
// }
|
|
|
|
// Play one of basic attack sounds
|
|
float theVolume = inArgs->fparam1;
|
|
float theAttenuation = 1.2f;
|
|
|
|
char* theSoundToPlay = kSpikeFireSound;
|
|
|
|
int theUpperBound = 30;
|
|
int thePitch = 100 + (gEngfuncs.pfnRandomLong(0, theUpperBound) - theUpperBound/2);
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, theSoundToPlay, theVolume, theAttenuation, 0, thePitch);
|
|
|
|
EV_GetGunPosition( inArgs, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
// Create ricochet and spike hit decals
|
|
EV_HLDM_FireBulletsPlayer( idx, forward, right, up, 1, vecSrc, vecAiming, kSpikeRange, BULLET_MONSTER_9MM, 0, NULL, kSpikeSpread, inArgs->iparam1);
|
|
|
|
// // Create two spike projectiles, flying forward until they hit something
|
|
// //for(int i = 0; i < 2; i++)
|
|
// //{
|
|
// vec3_t theEntStartPos = gPredictedPlayerOrigin;
|
|
//
|
|
// //TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TempEntAlloc(theEntStartPos, theModel);
|
|
// vec3_t theSpikeAngles;
|
|
// VectorAngles(forward, theSpikeAngles);
|
|
//
|
|
// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempModel(gPredictedPlayerOrigin, forward, theSpikeAngles, 100, gEngfuncs.pEventAPI->EV_FindModelIndex(kSpikeProjectileModel), 0);
|
|
// if(theTempEntity)
|
|
// {
|
|
// vec3_t theStartPos, theEndPos;
|
|
// EV_GetGunPosition(inArgs, vecSrc, inArgs->origin);
|
|
// VectorMA(vecSrc, kSpikeBarrelLength, forward, theStartPos);
|
|
//
|
|
// VectorCopy(theStartPos, theTempEntity->entity.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.prevstate.origin);
|
|
// VectorCopy(theStartPos, theTempEntity->entity.curstate.origin);
|
|
// theTempEntity->hitcallback = SpikeHit;
|
|
// theTempEntity->flags |= (FTENT_COLLIDEALL | FTENT_COLLIDEKILL/* | FTENT_PERSIST*/);
|
|
// //theTempEntity->entity.curstate.framerate = 30;
|
|
// //theTempEntity->frameMax = 4;//theModel->numframes;
|
|
//
|
|
// // Temp entities interpret baseline origin as velocity.
|
|
// Vector theStartVelocity;
|
|
// VectorScale(forward, kSpikeVelocity, theStartVelocity);
|
|
//
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.origin);
|
|
// VectorCopy(theStartVelocity, theTempEntity->entity.baseline.velocity);
|
|
//
|
|
// // Set orientation
|
|
// //VectorCopy(inArgs->angles, theTempEntity->entity.angles);
|
|
// }
|
|
// //}
|
|
|
|
////EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, kMGRange, BULLET_PLAYER_MP5, theTracerFreq, &tracerCount[idx-1] );
|
|
//EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, kSpikeRange, BULLET_MONSTER_9MM, 0, NULL /* &theTracerCount[0]*/, 0.0f, 0.0f);
|
|
|
|
// General x-punch axis
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
// Multiply punch by upgrade level
|
|
float theHalfSpread = (kSpikePunch/2.0f);
|
|
if(theHalfSpread > 0.0f)
|
|
{
|
|
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -theHalfSpread, theHalfSpread ) );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(inArgs->iparam2, 2);
|
|
}
|
|
}
|
|
|
|
//void EV_HiveHit(struct event_args_s* inArgs)
|
|
//{
|
|
// // when a hive comes under attack, let all the minions know it
|
|
//
|
|
// // iparam1 is the hurt sound to play
|
|
//
|
|
//
|
|
//
|
|
// const float kPunchRange = 3.0f;
|
|
//
|
|
// V_PunchAxis(0, gEngfuncs.pfnRandomFloat(-kPunchRange, kPunchRange));
|
|
// V_PunchAxis(1, gEngfuncs.pfnRandomFloat(-kPunchRange, kPunchRange));
|
|
// V_PunchAxis(2, gEngfuncs.pfnRandomFloat(-kPunchRange, kPunchRange));
|
|
//}
|
|
|
|
void EV_EmptySound(struct event_args_s* inArgs)
|
|
{
|
|
int thePitch = 100;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, kEmptySound, .8f, ATTN_NORM, 0, thePitch);
|
|
}
|
|
|
|
void EV_NumericalInfo(struct event_args_s* inArgs)
|
|
{
|
|
// Can't send easily send events to one team only, so only draw them for the right team
|
|
cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
if(theLocalPlayer)
|
|
{
|
|
int theTeamNumber = inArgs->iparam2;
|
|
if((theLocalPlayer->curstate.team == theTeamNumber) || (theTeamNumber == 0))
|
|
{
|
|
float theNumber = inArgs->fparam1;
|
|
int theEventType = inArgs->iparam1;
|
|
gHUD.AddNumericalInfoMessage(inArgs->origin, theNumber, theEventType);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_InvalidAction(struct event_args_s* inArgs)
|
|
{
|
|
int thePitch = 100;
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_WEAPON, kInvalidSound, .8f, ATTN_NORM, 0, thePitch);
|
|
}
|
|
|
|
void EV_Particle(struct event_args_s* inArgs)
|
|
{
|
|
// Read template
|
|
uint32 theTemplateIndex = inArgs->iparam1;
|
|
|
|
// Lookup template
|
|
const AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(theTemplateIndex);
|
|
if(theTemplate)
|
|
{
|
|
string theTemplateName = theTemplate->GetName();
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystem(theTemplateName, inArgs->origin);
|
|
}
|
|
}
|
|
|
|
void EV_DistressBeacon(struct event_args_s* inArgs)
|
|
{
|
|
// Play distress beacon sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_BODY, kDistressBeaconSound, 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Read time before distress beacon will end
|
|
int theDuration = inArgs->iparam1;
|
|
|
|
// Create blinking light that will die in that time
|
|
if(CVAR_GET_FLOAT(kvDynamicLights))
|
|
{
|
|
dlight_t* theLight = gEngfuncs.pEfxAPI->CL_AllocDlight(21);
|
|
VectorCopy(inArgs->origin, theLight->origin);
|
|
theLight->radius = 250;
|
|
theLight->color.r = 250;
|
|
theLight->color.g = 180;
|
|
theLight->color.b = 180;
|
|
|
|
// don't die for forseeable future
|
|
theLight->die = gEngfuncs.GetClientTime() + theDuration;
|
|
}
|
|
}
|
|
|
|
void EV_WeaponAnimation(struct event_args_s* inArgs)
|
|
{
|
|
// General x-punch axis
|
|
if(EV_IsLocal(inArgs->entindex))
|
|
{
|
|
int theAnimation = max(inArgs->iparam2, 0);
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(theAnimation, 2);
|
|
}
|
|
}
|
|
|
|
|
|
void EV_LevelUp(struct event_args_s* inArgs)
|
|
{
|
|
// General x-punch axis
|
|
if(EV_IsLocal(inArgs->entindex))
|
|
{
|
|
}
|
|
|
|
|
|
cl_entity_t* thePlayer = GetEntity(inArgs->entindex);
|
|
// Play sound
|
|
int theIsMarine = inArgs->iparam1;
|
|
const char* theSound = theIsMarine ? kLevelUpMarineSound : kLevelUpAlienSound;
|
|
|
|
float theSilenceVolumeFactor = theIsMarine ? 1.0 : AvHPlayerUpgrade::GetSilenceVolumeLevel((AvHUser3)thePlayer->curstate.iuser3, thePlayer->curstate.iuser4);
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(inArgs->entindex, inArgs->origin, CHAN_VOICE, theSound, theSilenceVolumeFactor, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ));
|
|
|
|
// Play nice particle effect?
|
|
}
|