forked from vera/halflife-thewastes-sdk
319 lines
8.4 KiB
C++
319 lines
8.4 KiB
C++
/***
|
|
*
|
|
* Copyright (C) 2002 The Wastes Project, All Rights Reserved.
|
|
*
|
|
* This product contains software technology from Valve Software, LLC,
|
|
* Copyright © 1996-2001, Valve LLC, All rights reserved.
|
|
*
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
* The Wastes Project. All other use, distribution, or modification is prohibited
|
|
* without written permission from The Wastes Project.
|
|
*
|
|
***/
|
|
//
|
|
// studioevent.cpp -> Model Event code
|
|
//
|
|
|
|
#include <memory.h>
|
|
|
|
#include "hud.h"
|
|
#include "cl_util.h"
|
|
#include "const.h"
|
|
#include "entity_types.h"
|
|
#include "studio_event.h" // def. of mstudioevent_t
|
|
#include "r_efx.h"
|
|
#include "event_api.h"
|
|
#include "pm_defs.h"
|
|
#include "pmtrace.h"
|
|
#include "twm.h"
|
|
#include "twmmanager.h"
|
|
|
|
extern "C"
|
|
{
|
|
#if 0
|
|
// THE ORIGINAL HUD_StudioEvent declaration is
|
|
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
|
|
// But we want to modify the cl_entity_s* parameter. Since C doesnt have the concept of const,
|
|
// and to the best of my knowledge the HL code is still c, i Figured i'd remove it... if we
|
|
// have problems with studio events dont hesitate to point at this.
|
|
// Gage - July 02, 2002
|
|
#else
|
|
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, struct cl_entity_s *entity );
|
|
#endif
|
|
}
|
|
|
|
void HUD_GetCurrentAmmoInfo(int &cur_ammo,int &max_ammo);
|
|
|
|
extern int cam_thirdperson;
|
|
extern vec3_t v_origin,v_angles;
|
|
|
|
/*
|
|
=========================
|
|
STUDIO_SmokePuff
|
|
|
|
=========================
|
|
*/
|
|
void STUDIO_SmokePuff(float *vecSrc,float scale,cl_entity_t *entity)
|
|
{
|
|
// create the puff
|
|
TEMPENTITY *pTent = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc,
|
|
Vector(0,0,5),
|
|
scale,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/smoke1.spr"),
|
|
kRenderTransAlpha,
|
|
0,
|
|
25,
|
|
5,
|
|
FTENT_SPRANIMATE);
|
|
|
|
// state settings
|
|
if(pTent != NULL)
|
|
{
|
|
pTent->clientIndex = entity->index;
|
|
|
|
//pTent->entity.curstate.rendercolor = Color;
|
|
pTent->entity.curstate.framerate = 10;
|
|
pTent->entity.curstate.renderamt = 128;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=========================
|
|
STUDIO_EjectModel
|
|
|
|
=========================
|
|
*/
|
|
void STUDIO_EjectModel(int iEventId,const char *szEventOptions,struct cl_entity_s *entity,int count)
|
|
{
|
|
char szShellname[64];
|
|
int shell_index;
|
|
int attachment_num,velocity_type,sound_type,quality_check;
|
|
float scaleR,scaleU;
|
|
vec3_t shell_velocity;
|
|
vec3_t shell_origin;
|
|
vec3_t angles,forward,right,up;
|
|
vec3_t endpos;
|
|
|
|
// Read options from event parameters
|
|
sscanf(szEventOptions,"%i,%i,%i,%i,%s",&attachment_num,&velocity_type,&sound_type,&quality_check,szShellname);
|
|
|
|
// Finalize shellcase parameter (set high or low quality)
|
|
if(quality_check)
|
|
sprintf(szShellname,"%s%s",szShellname,CVAR_GET_FLOAT("cl_shellcase_quality") ? "_hi.mdl" : "_lo.mdl");
|
|
|
|
#if 0
|
|
gEngfuncs.pfnCenterPrint(szShellname);
|
|
#endif
|
|
|
|
// set up shell properties
|
|
shell_index = gEngfuncs.pEventAPI->EV_FindModelIndex(szShellname);
|
|
|
|
if(shell_index == 0)
|
|
gEngfuncs.Con_DPrintf("STUDIO_EjectModel: invalid model %s\n",szShellname);
|
|
|
|
// Get needed angles
|
|
VectorCopy(entity->angles,angles);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
for(int i = 0;i < count;i++)
|
|
{
|
|
|
|
switch(velocity_type)
|
|
{
|
|
case 1:
|
|
// Pistols, Small arms ejection
|
|
scaleR = gEngfuncs.pfnRandomFloat( 50, 70 );
|
|
scaleU = gEngfuncs.pfnRandomFloat( 100, 150 );
|
|
|
|
VectorClear(shell_origin);
|
|
break;
|
|
case 2:
|
|
// No velocity, magazine dropping
|
|
scaleR = gEngfuncs.pfnRandomFloat(0.0,0.0);
|
|
scaleU = gEngfuncs.pfnRandomFloat(0.0,0.0);
|
|
|
|
// Randomize the location a bit,
|
|
// so events that call multiple times
|
|
// (such as ruger reload) have shellcases
|
|
// going everywhere
|
|
VectorClear(shell_origin);
|
|
|
|
shell_origin[0] = gEngfuncs.pfnRandomFloat(-1.0f,6.0f);
|
|
shell_origin[1] = gEngfuncs.pfnRandomFloat(-1.0f,6.0f);
|
|
shell_origin[2] = gEngfuncs.pfnRandomFloat(-1.0f,6.0f);
|
|
break;
|
|
}
|
|
|
|
for(int i = 0;i< 3;i++)
|
|
{
|
|
shell_velocity[i] = right[i] * scaleR + up[i] * scaleU + forward[i] * 25;
|
|
|
|
// go by ent origin, not attachment
|
|
if(attachment_num == -1)
|
|
{
|
|
shell_origin[i] += entity->origin[i];
|
|
|
|
// Spawn a bit lower
|
|
if(i == 2)
|
|
shell_origin[i] -= 16;
|
|
}
|
|
else
|
|
shell_origin[i] += entity->attachment[attachment_num][i];
|
|
}
|
|
|
|
// Eject the shell
|
|
VectorClear( endpos );
|
|
endpos[1] = angles[1];
|
|
|
|
// sound type, we do a
|
|
// switch in the unlikely event
|
|
// that these macros change on us
|
|
switch(sound_type)
|
|
{
|
|
case 0: sound_type = TE_BOUNCE_NULL; break;
|
|
case 1: sound_type = TE_BOUNCE_SHELL; break;
|
|
case 2: sound_type = TE_BOUNCE_SHOTSHELL; break;
|
|
}
|
|
|
|
gEngfuncs.pEfxAPI->R_TempModel(shell_origin,shell_velocity,endpos,CVAR_GET_FLOAT("cl_shellcase_lifetime"),shell_index,sound_type);
|
|
|
|
}
|
|
}
|
|
|
|
void STUDIO_TwmMuzzleFlash(int iEventId,const char *szEventOptions,struct cl_entity_s *entity)
|
|
{
|
|
CTwmModel *pTwm;
|
|
twm_clientinfo_t *clientinfo = NULL;
|
|
int attachment_num;
|
|
float fadetime;
|
|
|
|
// sanity check
|
|
if(g_iNumMuzzleflashModels > 64)
|
|
{
|
|
gEngfuncs.Con_Printf("STUDIO_TwmMuzzleFlash: too many muzzle flashes!\n");
|
|
return;
|
|
}
|
|
|
|
g_iNumMuzzleflashModels++;
|
|
|
|
// TODO: use szEventOptions for this stuff
|
|
pTwm = g_TwmManager.GetModelByName("models/muz_test.twm");
|
|
attachment_num = 0;
|
|
fadetime = 2.5f;
|
|
|
|
// end of array
|
|
clientinfo = &g_MuzzleflashModels[g_iNumMuzzleflashModels - 1];
|
|
|
|
// We go through the current muzzleflash
|
|
// array, if this entity has a
|
|
// muzzleflash for it, put in our new data
|
|
for(int i = 0;i < g_iNumMuzzleflashModels;i++)
|
|
{
|
|
twm_clientinfo_t *cur_info = &g_MuzzleflashModels[i];
|
|
|
|
if(cur_info->attached_ent == entity)
|
|
{
|
|
clientinfo = &g_MuzzleflashModels[i];
|
|
g_iNumMuzzleflashModels--; // reset value
|
|
break;
|
|
}
|
|
}
|
|
|
|
clientinfo->twm_info = &pTwm->twminfo;
|
|
clientinfo->attached_ent = entity;
|
|
clientinfo->attachment_num = attachment_num;
|
|
|
|
clientinfo->fadetime = fadetime;
|
|
|
|
// triAPI information
|
|
clientinfo->render_mode = kRenderTransAdd;
|
|
clientinfo->sprite_frame = 0; // TODO: make a random frame
|
|
clientinfo->brightness = gEngfuncs.pfnRandomFloat(0.8f,1.0f);
|
|
|
|
// RGBA
|
|
clientinfo->color[0] = 1.0f;
|
|
clientinfo->color[1] = 1.0f;
|
|
clientinfo->color[2] = 1.0f;
|
|
clientinfo->color[3] = gEngfuncs.pfnRandomFloat(0.5f,1.0f);
|
|
}
|
|
|
|
/*
|
|
=========================
|
|
HUD_StudioEvent
|
|
|
|
The entity's studio model description indicated an event was
|
|
fired during this frame, handle the event by it's tag ( e.g., muzzleflash, sound )
|
|
=========================
|
|
*/
|
|
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, struct cl_entity_s *entity )
|
|
{
|
|
switch( event->event )
|
|
{
|
|
|
|
/*******************
|
|
* muzzle flashes *
|
|
*******************/
|
|
case 5001:
|
|
// STUDIO_TwmMuzzleFlash(event->event,event->options,entity);
|
|
gEngfuncs.pEfxAPI->R_MuzzleFlash((float *)&entity->attachment[0], atoi( event->options) );
|
|
break;
|
|
case 5011:
|
|
// STUDIO_TwmMuzzleFlash(event->event,event->options,entity);
|
|
gEngfuncs.pEfxAPI->R_MuzzleFlash((float *)&entity->attachment[1], atoi( event->options) );
|
|
break;
|
|
case 5021:
|
|
// STUDIO_TwmMuzzleFlash(event->event,event->options,entity);
|
|
gEngfuncs.pEfxAPI->R_MuzzleFlash((float *)&entity->attachment[2], atoi( event->options) );
|
|
break;
|
|
case 5031:
|
|
// STUDIO_TwmMuzzleFlash(event->event,event->options,entity);
|
|
gEngfuncs.pEfxAPI->R_MuzzleFlash((float *)&entity->attachment[3], atoi( event->options) );
|
|
break;
|
|
|
|
/*******************
|
|
* smoke puffs *
|
|
*******************/
|
|
case 5041:
|
|
STUDIO_SmokePuff((float *)&entity->attachment[1],0.5f,entity);
|
|
break;
|
|
|
|
/*******************
|
|
* sparks *
|
|
*******************/
|
|
case 5002:
|
|
gEngfuncs.pEfxAPI->R_SparkEffect((float *)&entity->attachment[0], atoi( event->options), -100, 100 );
|
|
break;
|
|
|
|
/*******************
|
|
* sound *
|
|
*******************/
|
|
case 5004:
|
|
gEngfuncs.pfnPlaySoundByNameAtLocation((char*)event->options,1.0,(float*)&entity->attachment[0]);
|
|
break;
|
|
|
|
/*******************
|
|
* skin change *
|
|
*******************/
|
|
case 5005:
|
|
entity->curstate.skin = atoi(event->options);
|
|
break;
|
|
|
|
/*******************
|
|
* model ejection *
|
|
*******************/
|
|
case 5006:
|
|
STUDIO_EjectModel(event->event,event->options,entity,1);
|
|
break;
|
|
// Ruger reload
|
|
case 5007:
|
|
STUDIO_EjectModel(event->event,event->options,entity,5 - gHUD.m_Ammo.GetCurWeapon()->iClip);
|
|
break;
|
|
// Sawed off reload
|
|
case 5008:
|
|
STUDIO_EjectModel(event->event,event->options,entity,2 - gHUD.m_Ammo.GetCurWeapon()->iClip);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|