client effect reorganization and akimbo support (demo in socom), pmove slight reorganization
This commit is contained in:
parent
6ba566a616
commit
0c9b8537e4
17 changed files with 827 additions and 650 deletions
|
@ -42,9 +42,6 @@ ClientGame_PreDraw(void)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
Player_HandleWeaponModel(base_player pp, float thirdperson);
|
||||
|
||||
// Happens right before the CSQC_RenderScene call seen in Nuclide's client/draw.qc.
|
||||
// PostDraw further down is too late.
|
||||
// NOT A NUCLIDE EVENT - called by the end of ViewModel_ApplyBob (viewmodel.qc) so that
|
||||
|
@ -54,10 +51,10 @@ Custom_LatePreDraw(void)
|
|||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
Player_DrawViewModelCustom(pl);
|
||||
TS_View_DrawCustom(pl);
|
||||
|
||||
int thirdperson = (autocvar_cl_thirdperson == TRUE || pl.entnum != player_localentnum);
|
||||
Player_DrawViewModelExtraEffects(pl, thirdperson);
|
||||
TS_View_DrawExtraEffects(pl, thirdperson);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,12 @@ class CTSShellEject{
|
|||
|
||||
void(void) CTSShellEject;
|
||||
static void(void) precache;
|
||||
|
||||
static CTSShellEject(int arg_iShellEjectType) generate;
|
||||
static CTSShellEject(int arg_iShellEjectType) generateForViewmodel;
|
||||
static void(int arg_iShellEjectType, int arg_akimboChoice) generateForViewModelAkimbo;
|
||||
static CTSShellEject(int arg_iShellEjectType, int arg_attachment1, int arg_attachment2) generateForViewModel_attachments;
|
||||
|
||||
static CTSShellEject(int arg_iShellEjectType, vector arg_vOrigin, vector arg_vDir) generate2;
|
||||
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
|
|
@ -51,15 +51,21 @@ CTSShellEject::generate(int arg_iShellEjectType){
|
|||
//setmodel(eShell, "models/shell.mdl");
|
||||
shellejectdata_t* mySED = ary_shellEjectData[eShell.iShellEjectType];
|
||||
setmodel(eShell, (*mySED).sModelPath);
|
||||
//setmodel(eShell, "models/powerup.mdl");
|
||||
|
||||
|
||||
eShell.solid = SOLID_BBOX;
|
||||
eShell.movetype = MOVETYPE_BOUNCE;
|
||||
eShell.drawmask = MASK_ENGINE;
|
||||
eShell.angles = [pSeat->m_eViewModel.angles[0], pSeat->m_eViewModel.angles[1], 0];
|
||||
|
||||
//player pl = (player) pSeat->m_ePlayer;
|
||||
//printfline("What?? (%.2f %.2f %.2f), (%.2f %.2f %.2f)", pSeat->m_vecPredictedVelocity.x, pSeat->m_vecPredictedVelocity.y, pSeat->m_vecPredictedVelocity.z, pl.velocity.x, pl.velocity.y, pl.velocity.z);
|
||||
|
||||
eShell.velocity = pSeat->m_vecPredictedVelocity;
|
||||
|
||||
makevectors(pSeat->m_eViewModel.angles);
|
||||
eShell.velocity += (v_forward * 0);
|
||||
eShell.velocity += (v_forward * 20);
|
||||
eShell.velocity += (v_right * 80);
|
||||
eShell.velocity += (v_up * 100);
|
||||
|
||||
|
@ -78,8 +84,29 @@ CTSShellEject::generate(int arg_iShellEjectType){
|
|||
// The practical constructor, manually call this after spawning.
|
||||
// NOTE: assumes pSeat->m_eViewModel is valid for involving in determining
|
||||
// origin, angles, velocity
|
||||
void
|
||||
CTSShellEject::generateForViewModelAkimbo(int arg_iShellEjectType, int arg_akimboChoice)
|
||||
{
|
||||
|
||||
// this means, a singular weapon, not akimbo. Important distinction for
|
||||
// attachment points to pick
|
||||
if(arg_akimboChoice == BITS_AKIMBOCHOICE_NONE){
|
||||
CTSShellEject::generateForViewModel_attachments(arg_iShellEjectType, 0, 3);
|
||||
}
|
||||
if(arg_akimboChoice & BITS_AKIMBOCHOICE_LEFT){
|
||||
CTSShellEject::generateForViewModel_attachments(arg_iShellEjectType, 2, 3);
|
||||
}
|
||||
if(arg_akimboChoice & BITS_AKIMBOCHOICE_RIGHT){
|
||||
CTSShellEject::generateForViewModel_attachments(arg_iShellEjectType, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// with the attachments to be used to help get a better idea of forwards/backwards/sideways
|
||||
// for the current weapon, create a shell.
|
||||
CTSShellEject
|
||||
CTSShellEject::generateForViewmodel(int arg_iShellEjectType)
|
||||
CTSShellEject::generateForViewModel_attachments(int arg_iShellEjectType, int arg_attachment1, int arg_attachment2)
|
||||
{
|
||||
// give me an origin!
|
||||
CTSShellEject eShell = CTSShellEject::generate(arg_iShellEjectType);
|
||||
|
@ -123,8 +150,8 @@ CTSShellEject::generateForViewmodel(int arg_iShellEjectType)
|
|||
vector angGun;
|
||||
|
||||
|
||||
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 0i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 3i);
|
||||
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + arg_attachment1);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + arg_attachment2);
|
||||
dirGun = normalize(gunpos_tempEnd - gunpos);
|
||||
angGun = vectoangles(dirGun);
|
||||
makevectors(angGun);
|
||||
|
@ -136,6 +163,14 @@ CTSShellEject::generateForViewmodel(int arg_iShellEjectType)
|
|||
// ALSO, TODO: Check for being akimbo and per weapon. oh dear... we need a paramter for what
|
||||
// weapon, left or right to use then (LEFT always a default, even if non-akimbo is ok too),
|
||||
// see weapons for that AKIMBOCHOICE thing
|
||||
/*
|
||||
player pl = (player) pSeat->m_ePlayer;
|
||||
if(arg_iShellEjectType == SHELLEJECT_ID::SHOTGUN_BLUE){
|
||||
vOrigin = gunpos + pl.velocity*input_timelength;
|
||||
}else{
|
||||
vOrigin = gunpos;
|
||||
}
|
||||
*/
|
||||
vOrigin = gunpos;
|
||||
vOrigin += v_forward * -3.5;
|
||||
vOrigin += v_up * -0.02;
|
||||
|
@ -144,9 +179,28 @@ CTSShellEject::generateForViewmodel(int arg_iShellEjectType)
|
|||
|
||||
setorigin(eShell, vOrigin);
|
||||
|
||||
/*
|
||||
// TEST. Any difference between the vecPredictedOrigin and current origin at this point of the call?
|
||||
player pl = (player) pSeat->m_ePlayer;
|
||||
vector vDelta;
|
||||
vDelta = pSeat->m_vecPredictedOrigin - pl.origin;
|
||||
if(vlen(vDelta) > 0.001){
|
||||
printfline("Difference? %.2f %.2f %.2f", vDelta.x, vDelta.y, vDelta.z);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
player pl = (player) pSeat->m_ePlayer;
|
||||
float vel = vlen(pl.velocity);
|
||||
float vel2 = vlen(pl.basevelocity);
|
||||
if(vel > 0.001 || vel2 > 0.001){
|
||||
printfline("vel: %.2f basevel: %.2f", vel, vel2);
|
||||
}
|
||||
*/
|
||||
|
||||
return eShell;
|
||||
}
|
||||
|
||||
|
||||
// TODO. For playermodels as seen in thirdperson (local one) or looking at other players
|
||||
// that called for shell ejecting.
|
||||
CTSShellEject
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
void Player_DrawViewModelCustom(player pl);
|
||||
void Player_DrawViewModelExtraEffects(player pl, int thirdperson);
|
|
@ -164,8 +164,6 @@ Player_DestroyWeaponModel(entity pp)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//TAGGG - NOTE! In case it ever matters, parameter "base_player pl" renamed to "base_player pp".
|
||||
// Doubt it ever should, no idea if FTE would complain about a discrepency between prototype and
|
||||
// implementation parameter names if that ever happened.
|
||||
|
@ -184,479 +182,3 @@ Player_PreDraw(base_player pp, int thirdperson)
|
|||
}
|
||||
|
||||
|
||||
|
||||
// NEW, helper method, not called by Nuclide
|
||||
// Does the same Nuclide script to draw the normal viewmodel at viewzooms between 0.5
|
||||
// and 1.0, Nuclide skips drawing it on any zoom below 1.0 unlike original TS.
|
||||
// Also, handles drawing the akimbo muzzle flash.
|
||||
void
|
||||
Player_DrawViewModelCustom(player pl){
|
||||
|
||||
// Same forbidding conditions from Nuclide's src/client/view.qc
|
||||
if (pl.health <= 0) {
|
||||
return;
|
||||
}
|
||||
if (cvar("r_drawviewmodel") == 0 || autocvar_cl_thirdperson == TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Nuclide does not draw the viewmodel at any zoom other than 1.0 (unmodified).
|
||||
// So, this draws the viewmodel the othertimes TS did, in lower zoom choices.
|
||||
// At viewzoom 0.5 and above, the scope graphic is not drawn so it is safe to
|
||||
// do this.
|
||||
if(pl.viewzoom >= 0.5){
|
||||
entity m_eViewModel = pSeat->m_eViewModel;
|
||||
entity m_eMuzzleflash = pSeat->m_eMuzzleflash;
|
||||
entity m_eMuzzleflashAkimbo = pSeatLocal->m_eMuzzleflashAkimbo;
|
||||
|
||||
// (only re-do the default Nuclide viewmodel + normal muzzleflash script if we have reason
|
||||
// to believe Nuclide didn't, i.e., a zoom under 1.0)
|
||||
if(pl.viewzoom < 1.0){
|
||||
// CLONE OF NUCLIDE SCRIPT
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if (m_eMuzzleflash.alpha > 0.0f) {
|
||||
makevectors(getproperty(VF_ANGLES));
|
||||
m_eMuzzleflash.origin = gettaginfo(m_eViewModel, m_eMuzzleflash.skin);
|
||||
m_eMuzzleflash.angles = m_eViewModel.angles;
|
||||
m_eMuzzleflash.angles[2] += (random() * 10) - 5;
|
||||
|
||||
/*dynamiclight_add(pSeat->m_vecPredictedOrigin + (v_forward * 32), 400 * m_eMuzzleflash.alpha, [1,0.45,0]);*/
|
||||
|
||||
setorigin(m_eMuzzleflash, m_eMuzzleflash.origin);
|
||||
addentity(m_eMuzzleflash);
|
||||
}
|
||||
setorigin(m_eViewModel, m_eViewModel.origin);
|
||||
addentity(m_eViewModel);
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// Regardless of being 1.0 or not (Nuclide certainly isn't doing this),
|
||||
// handle the other muzzleflash too
|
||||
if (m_eMuzzleflashAkimbo.alpha > 0.0f) {
|
||||
makevectors(getproperty(VF_ANGLES));
|
||||
m_eMuzzleflashAkimbo.origin = gettaginfo(m_eViewModel, m_eMuzzleflashAkimbo.skin);
|
||||
m_eMuzzleflashAkimbo.angles = m_eViewModel.angles;
|
||||
m_eMuzzleflashAkimbo.angles[2] += (random() * 10) - 5;
|
||||
|
||||
/*dynamiclight_add(pSeat->m_vecPredictedOrigin + (v_forward * 32), 400 * m_eMuzzleflashAkimbo.alpha, [1,0.45,0]);*/
|
||||
|
||||
setorigin(m_eMuzzleflashAkimbo, m_eMuzzleflashAkimbo.origin);
|
||||
addentity(m_eMuzzleflashAkimbo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// another helper method
|
||||
// Draw the lasersight, and flashlight effects
|
||||
void
|
||||
Player_DrawViewModelExtraEffects(player pl, int thirdperson)
|
||||
{
|
||||
//int thirdperson = (autocvar_cl_thirdperson == TRUE || this.entnum != player_localentnum);
|
||||
//base_player pp = (base_player)this;
|
||||
|
||||
BOOL canRenderFlashlight = FALSE;
|
||||
BOOL canRenderLaserSight = FALSE;
|
||||
|
||||
//player pl = (player)pp;
|
||||
//we're going to use the buyopts of our current weapon + the one actually turned on, yah?
|
||||
|
||||
// DEBUG: printouts about the other player.
|
||||
// Start a server with over 1 max players allowed in one window,
|
||||
// connect to it in another window. Boom, read printouts.
|
||||
/*
|
||||
if(entnum != player_localentnum){
|
||||
// so other player's "pl.weaponEquippedID" are not sent over to our clientside copies of them... I guess?
|
||||
// At least that's not confusing.
|
||||
printfline("It is I, the other player! What do I have? %i weapon count: %i", pl.weaponEquippedID, pl.ary_myWeapons_softMax);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if(pl.inventoryEquippedIndex != -1){
|
||||
|
||||
weapondynamic_t dynaRef = pl.ary_myWeapons[pl.inventoryEquippedIndex];
|
||||
|
||||
if(dynaRef.weaponTypeID == WEAPONDATA_TYPEID_GUN || dynaRef.weaponTypeID == WEAPONDATA_TYPEID_IRONSIGHT){
|
||||
weapondata_basic_t* basePRef = pl.getEquippedWeaponData();
|
||||
weapondata_basic_t baseRef = *basePRef;
|
||||
|
||||
|
||||
// We must have the flashlight bit on, AND support it on our weapon, AND it be a possibility according to weapon data.
|
||||
int legalBuyOpts_on = (dynaRef.iBitsUpgrade_on & (dynaRef.iBitsUpgrade & baseRef.iBitsUpgrade));
|
||||
|
||||
if(legalBuyOpts_on & BITS_WEAPONOPT_FLASHLIGHT){
|
||||
canRenderFlashlight = TRUE;
|
||||
}
|
||||
if(legalBuyOpts_on & BITS_WEAPONOPT_LASERSIGHT){
|
||||
canRenderLaserSight = TRUE;
|
||||
}
|
||||
}///END OF _GUN or _IRONSIGHT type checks
|
||||
}//END OF weaponEquippedID check
|
||||
|
||||
|
||||
|
||||
vector posView;
|
||||
vector angView;
|
||||
|
||||
//for glock it is 40.
|
||||
//vector gunpos = gettaginfo(pSeat->eViewModel, 33);
|
||||
|
||||
float daDrawAlphahz = 1.0;
|
||||
const vector lasColor = [1.0, 0, 0];
|
||||
const vector fsize = [2,2];
|
||||
const vector fsizeDot = [18,18];
|
||||
const vector fsizeFlashlightMuzzleGlow = [3, 3];
|
||||
|
||||
vector flashPos;
|
||||
vector gunpos;
|
||||
vector gunpos2 = [0,0,0];
|
||||
vector gunpos_tempEnd;
|
||||
|
||||
|
||||
vector dirGun = [0,0,0];
|
||||
vector dirGun2 = [0,0,0];
|
||||
vector angGun = [0,0,0];
|
||||
vector angGun2 = [0,0,0];
|
||||
|
||||
//TAGGG - IMPORTANT NOTE!!!
|
||||
// BEWARE "view_angles", it is a client global (what a confusing term), meaning it pertains only to THIS
|
||||
// client (local player), no matter what player is being rendered by this call.
|
||||
// wait... shouldn't we do the third-person check for the flash-light check above too?
|
||||
|
||||
BOOL canDrawAkimboLaser = FALSE;
|
||||
pl.recentLaserHitPosSet = TRUE;
|
||||
|
||||
|
||||
|
||||
// TAGGG - QUESTION: Is it better to use the bool "thirdperson"
|
||||
// (see check below involving cl_thirdperson)
|
||||
// OR a raw "pl.entnum != player_localentnum" check?
|
||||
// The former is a more concrete check for, "Am I the local player
|
||||
// looking in 1st person, yes or no?".
|
||||
// The latter will still treat the player being the local player the
|
||||
// same as firstperson, even if the local player is forcing themselves
|
||||
// to be viewed in third person.
|
||||
// I am inclined to think the former is the better choice, but
|
||||
// valve/src/client/flashlight.qc uses the latter way. Why?
|
||||
|
||||
// thirdperson
|
||||
// True IF (autocvar_cl_thirdperson == TRUE || this.entnum != player_localentnum)
|
||||
// False IF (autocvar_cl_thirdperson == FALSE && this.entnum == player_localentnum)
|
||||
if(!thirdperson){
|
||||
|
||||
//TAGGG - Old way!
|
||||
//posView = getproperty(VF_ORIGIN) + [0,0,-8];
|
||||
//angView = getproperty(VF_CL_VIEWANGLES);
|
||||
|
||||
posView = pSeat->m_vecPredictedOrigin + [0,0,-8];
|
||||
angView = view_angles;
|
||||
|
||||
// CHECK: is "getproperty(VF_CL_VIEWANGLES)" always the same as "view_angles"?
|
||||
|
||||
if(!pl.weaponEquippedAkimbo){
|
||||
// first-person and this is the local player?
|
||||
// We can get more specific info from the visible viewmodel, do so!
|
||||
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 0i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 3i);
|
||||
// should shell casings come from a bit behind the firing point here when needed?
|
||||
//gunpos += v_right * 0.8; //why is this 'up'??
|
||||
// not this one maybe... what the hell is this direction at all.
|
||||
//gunpos += v_forward * -1.8;
|
||||
|
||||
dirGun = normalize(gunpos_tempEnd - gunpos);
|
||||
angGun = vectoangles(dirGun);
|
||||
|
||||
|
||||
}else{
|
||||
canDrawAkimboLaser = TRUE;
|
||||
|
||||
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 0i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 1i);
|
||||
dirGun = normalize(gunpos_tempEnd - gunpos);
|
||||
angGun = vectoangles(dirGun);
|
||||
|
||||
gunpos2 = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 2i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 3i);
|
||||
dirGun2 = normalize(gunpos_tempEnd - gunpos2);
|
||||
angGun2 = vectoangles(dirGun2);
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
posView = pl.origin + pl.view_ofs;
|
||||
angView = [pl.pitch, pl.angles[1], pl.angles[2]];
|
||||
gunpos = posView;
|
||||
angGun = angView;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(canRenderLaserSight && pl.entnum == player_localentnum){
|
||||
// The lasersight displays a number of distance to show how long the laser goes.
|
||||
//makevectors(view_angles);
|
||||
makevectors(angView);
|
||||
traceline(posView, posView + v_forward * 2048*4, MOVE_HITMODEL, pl);
|
||||
pl.recentLaserDistanceDisplay = (int)(vlen(trace_endpos - posView) / 40 );
|
||||
}
|
||||
|
||||
|
||||
// DEBUG!!!
|
||||
//canRenderLaserSight = TRUE;
|
||||
//canRenderFlashlight = TRUE;
|
||||
|
||||
if(canRenderFlashlight){
|
||||
//TAGGG - FLASHLIGHT STUFF HERE..
|
||||
// oh wait a comment above already said that
|
||||
// HOWEVER... in TS flashlights have a range limit. Up to so far they have max brightness,
|
||||
// then it lowers with a bit of range, then it's nothing.
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
int flashlightRangeMax = 1070;
|
||||
float flashlightBrightnessFactor = 1.0;
|
||||
float rangeDimPriorStart = 170; //rangeMax minus this is where I start dimming.
|
||||
|
||||
makevectors(angView);
|
||||
|
||||
traceline(posView, posView + (v_forward * flashlightRangeMax), MOVE_NORMAL, pl);
|
||||
int traceDist = trace_fraction * flashlightRangeMax;
|
||||
|
||||
//printfline("%.2f %d",, trace_fraction, trace_inopen);
|
||||
|
||||
//TODO - not here but elsewhere, draw the muzzle flashlight effect, some sprite on that gun attachment where am uzzleflash would go should do it.
|
||||
// ALSO, go ahead and use this line trace to tell the lasersight how far the laser went.
|
||||
// And just draw the lasersight (and dot if necessary), IF this render is for the local player.
|
||||
// If not the local player, a slightly larger red dot (actual sprite) goes at the point the
|
||||
// player is looking, likely not influenced by animations / view-model stuff.
|
||||
|
||||
|
||||
if(trace_fraction == 1.0){
|
||||
//uh-oh.
|
||||
flashlightBrightnessFactor = 0;
|
||||
}if(traceDist >= flashlightRangeMax - rangeDimPriorStart){
|
||||
//the flashlight gets dimmer the further it is at this point.
|
||||
// rangeDimPriorStart from the end: max bright still.
|
||||
// very end: 0% bright.
|
||||
flashlightBrightnessFactor = (-flashlightRangeMax * (trace_fraction + -1)) / rangeDimPriorStart;
|
||||
}
|
||||
|
||||
if(flashlightBrightnessFactor > 0){
|
||||
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
|
||||
dynamiclight_add(trace_endpos + (v_forward * -2), 128 * flashlightBrightnessFactor, [1,1,1]);
|
||||
} else {
|
||||
float p = dynamiclight_add(posView, 512 * flashlightBrightnessFactor, [1,1,1], 0, "textures/flashlight");
|
||||
dynamiclight_set(p, LFIELD_ANGLES, angView);
|
||||
dynamiclight_set(p, LFIELD_FLAGS, 3);
|
||||
}
|
||||
}//END OF brightness check
|
||||
|
||||
|
||||
}//END OF "flashlight is on" criteria
|
||||
|
||||
|
||||
if(canRenderLaserSight || canRenderFlashlight){
|
||||
// TRY IT SOMEHOW? RF_DEPTHHACK
|
||||
//pSeat->m_eViewModel.renderflags = RF_DEPTHHACK;
|
||||
//if (alpha <= 0.0f) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
makevectors(angGun);
|
||||
|
||||
//rotatevectorsbyangle( [-0.42, 0.75, 0] );
|
||||
//rotatevectorsbyangle( [-0.52, 0.85, 0] );
|
||||
rotatevectorsbyangle( [-0.45, 0.27, 0] );
|
||||
|
||||
|
||||
flashPos = gunpos + v_up * -0.08 + v_right * 0.06;
|
||||
|
||||
|
||||
vector shortForwardEnd = gunpos;
|
||||
shortForwardEnd += v_forward * -1;
|
||||
shortForwardEnd += v_up * (0.22); //why is this 'up'??
|
||||
shortForwardEnd += v_right * (0.35); //why is this 'up'??
|
||||
|
||||
//makevectors(m_vecAngle); really now
|
||||
//makevectors(input_angles); //maybe this if we need to do this.
|
||||
|
||||
// v_up * 2. or.. 1.6, for size [3,3] at least.
|
||||
// for size [5,5], we need v_up*3, v_right*2. I DONT KNOW.
|
||||
// for size [2, 2], we want v_up*5, v_right*5. Go figure that one out.
|
||||
|
||||
// Keep in mind, the global vectors (v_up, etc.) are set to the orientation of the recently received
|
||||
// viewmodel attachment (gettaginfo above). Don't 'makevectors' at all to simply rely on that.
|
||||
// ...unfortunately the orientation we get back is not great either. oh well.
|
||||
|
||||
// NEW TEST. Can we even get a straight line from the player's center to the gunpos?
|
||||
|
||||
traceline(posView, shortForwardEnd, FALSE, pl);
|
||||
if(trace_fraction >= 1.0){
|
||||
//woohoo!
|
||||
|
||||
traceline(shortForwardEnd, shortForwardEnd + v_forward * 1024, MOVE_HITMODEL, pl);
|
||||
|
||||
// other places care about this.
|
||||
if (pl.entnum == player_localentnum) {
|
||||
pl.recentLaserHitPos = trace_endpos;
|
||||
}
|
||||
|
||||
if(canRenderLaserSight){
|
||||
|
||||
// In original TS, the 'laster' does not render for the local player if they are
|
||||
// in thirdperson to see their own playermodel. I... don't really understand that,
|
||||
// feels like a mistake. The lasers from other players are visible.
|
||||
|
||||
// TAGGG - TODO - SUPER LOW PRIORITY
|
||||
// Lasers only for not in 3rd person and local player.
|
||||
// Could work for the third-person model or other players if there were a way to determine
|
||||
// the muzzle-end point for player models. Unsure if that is possible.
|
||||
// To see it in third-person anyway, just change the "!thirdperson" condition below
|
||||
// to "TRUE"; always do it. There is no separate place that does only first-person lasers
|
||||
// to worry about being redundant with.
|
||||
// Note the laser will try to face the direction the player model is, which may not
|
||||
// necessarily be where the player is looking, although that same issue would come up
|
||||
// with firing anyway; you would look like you're firing sideways anyway, this would be
|
||||
// just as "off".
|
||||
if (!thirdperson) {
|
||||
//makevectors(view_angles); //??? it seems we do not need this perhaps...
|
||||
// IN SHORT, we're riding the prior "makevectors(angGun);".
|
||||
R_BeginPolygon("sprites/laserbeam.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(gunpos + v_right * fsize[0] - v_up * fsize[1], [1,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(gunpos - v_right * fsize[0] - v_up * fsize[1], [0,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], [0,0], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], [1,0], lasColor, daDrawAlphahz);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
// Draw the laser sprite effect at where the laser is hitting, but ONLY for every other player
|
||||
// except this one. That's because, for the local player, we already are drawing the laserdot
|
||||
// projected onto the screen in the HUD logic.
|
||||
|
||||
if (pl.entnum != player_localentnum) {
|
||||
makevectors(angView);
|
||||
|
||||
trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/laserdot.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] - v_up * fsizeDot[1], [1,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] - v_up * fsizeDot[1], [0,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] + v_up * fsizeDot[1], [0,0], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] + v_up * fsizeDot[1], [1,0], lasColor, 0.80f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
}//END OF canRenderLaserSight
|
||||
|
||||
|
||||
// glow effect on top of the gun muzzle while the flashlight is on?
|
||||
if(canRenderFlashlight){
|
||||
if(!thirdperson){
|
||||
makevectors(angView);
|
||||
|
||||
//trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/glow02.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [1,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [0,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [0,0], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [1,0], [1,1,1], 0.45f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
}//END OF trace pre-check
|
||||
|
||||
|
||||
// This requires the current weapon to be akimbo, player is in first person,
|
||||
// and the local player is being rendered.
|
||||
if(canDrawAkimboLaser){
|
||||
// test for the 2nd gun's laser too then.
|
||||
// makevectors(theDir);
|
||||
makevectors(angGun2);
|
||||
rotatevectorsbyangle( [-0.45, 0.27, 0] );
|
||||
|
||||
//gunpos2 += v_forward * -18;
|
||||
|
||||
flashPos = gunpos2 + v_up * -0.08 + v_right * 0.06;
|
||||
|
||||
shortForwardEnd = gunpos2;
|
||||
shortForwardEnd += v_forward * -1;
|
||||
shortForwardEnd += v_up * (0.22); //why is this 'up'??
|
||||
shortForwardEnd += -v_right * (0.35); //why is this 'up'??
|
||||
|
||||
|
||||
traceline(posView, shortForwardEnd, FALSE, pl);
|
||||
if(trace_fraction >= 1.0){
|
||||
|
||||
traceline(shortForwardEnd, shortForwardEnd + v_forward * 1024, MOVE_HITMODEL, pl);
|
||||
|
||||
// other places care about this.
|
||||
if (pl.entnum == player_localentnum) {
|
||||
pl.recentLaserHitPos2 = trace_endpos;
|
||||
}
|
||||
|
||||
if(canRenderLaserSight){
|
||||
if (!thirdperson) {
|
||||
// ONLY render the polygon
|
||||
// makevectors(view_angles); //??? it seems we do not need this perhaps...
|
||||
// IN SHORT, we're riding the prior "makevectors(angGun2);".
|
||||
|
||||
R_BeginPolygon("sprites/laserbeam.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(gunpos2 + v_right * fsize[0] - v_up * fsize[1], [1,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(gunpos2 - v_right * fsize[0] - v_up * fsize[1], [0,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], [0,0], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], [1,0], lasColor, daDrawAlphahz);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
|
||||
if (pl.entnum != player_localentnum) {
|
||||
//makevectors(view_angles);
|
||||
makevectors(angView);
|
||||
|
||||
trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/laserdot.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] - v_up * fsizeDot[1], [1,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] - v_up * fsizeDot[1], [0,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] + v_up * fsizeDot[1], [0,0], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] + v_up * fsizeDot[1], [1,0], lasColor, 0.80f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(canRenderFlashlight){
|
||||
if(!thirdperson){
|
||||
//makevectors(view_angles);
|
||||
makevectors(angView);
|
||||
|
||||
//trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/glow02.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [1,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [0,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [0,0], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [1,0], [1,1,1], 0.45f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
|
||||
}//END OF trace pre-check
|
||||
}//END OF akimbo check
|
||||
|
||||
/*
|
||||
if (m_iBeams == 0) {
|
||||
alpha -= clframetime * 3;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}else{
|
||||
pl.recentLaserHitPosSet = FALSE;
|
||||
}//END OF canRenderLaserSight || canRenderFlashlight
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ entity/ts_shelleject.h
|
|||
|
||||
clientinfo.h
|
||||
seatlocal.h
|
||||
player.h
|
||||
|
||||
precache.h
|
||||
ui.h
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
|
||||
void View_UpdateWeapon(entity vm, entity mflash);
|
||||
|
||||
void View_ShowMuzzleflash(int index);
|
||||
void View_ShowMuzzleflashAkimbo(int index);
|
||||
|
||||
void TS_View_SetViewModelFromStats(void);
|
||||
void TS_View_RoutineCheck(void);
|
||||
void TS_View_ChangeViewModelPost(void);
|
||||
void TS_View_ResetViewModel(void);
|
||||
|
||||
void TS_View_DrawCustom(player pl);
|
||||
void TS_View_DrawExtraEffects(player pl, int thirdperson);
|
||||
void TS_View_ShowMuzzleflash(int index, int akimboChoice);
|
||||
|
||||
void TS_View_HandleZoom(void);
|
||||
|
|
|
@ -74,44 +74,6 @@ View_UpdateWeapon(entity vm, entity mflash)
|
|||
}
|
||||
|
||||
|
||||
//TAGGG - NEW. Similar to Nuclide's provided "View_SetMuzzleflash", but also acts
|
||||
// as though the first frame were an event by doing the same lines as a 5000-ish
|
||||
// event. This is because TS weapons don't have events for the muzzle flash
|
||||
// unlike HL ones, must be hardcoded to show up.
|
||||
// Figuring out what muzzle flash for what weapon will come another time.
|
||||
// For now using the same HL set, but TS comes with some muzzle-flash looking sprites.
|
||||
// ALSO - for now, always assuming attachment #0.
|
||||
// For the model event in case that changes, see Nuclide's src/client/modelevent.qc,
|
||||
// Event_ProcessModel.
|
||||
void
|
||||
View_ShowMuzzleflash(int index)
|
||||
{
|
||||
pSeat->m_eMuzzleflash.modelindex = (float)index;
|
||||
// Event_ProcessModel: force it.
|
||||
pSeat->m_eMuzzleflash.alpha = 1.0f;
|
||||
pSeat->m_eMuzzleflash.scale = 0.25;
|
||||
// attachment #0 is m_iVMBones + 0. Add for #1 to #3, I think.
|
||||
// No idea if any weapons play with attachments, #0 should always
|
||||
// be the end of the weapon for flashes
|
||||
pSeat->m_eMuzzleflash.skin = pSeat->m_iVMBones + 0;
|
||||
}
|
||||
|
||||
void
|
||||
View_ShowMuzzleflashAkimbo(int index)
|
||||
{
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.modelindex = (float)index;
|
||||
// Event_ProcessModel: force it.
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.alpha = 1.0f;
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.scale = 0.25;
|
||||
// akimbo attachments are in pairs:
|
||||
// 0 on one weapon, 1 further out along that weapon's direction,
|
||||
// 2 on the other weapon, 3 further along the other weapon's direction.
|
||||
// ALSO: on akimbo weapons, attachments 0 and 1 are for the right weapon,
|
||||
// 1 and 2 for the left.
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.skin = pSeat->m_iVMBones + 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
TS_View_SetViewModelFromStats(void)
|
||||
|
@ -299,6 +261,530 @@ TS_View_ResetViewModel(void)
|
|||
|
||||
|
||||
|
||||
// NEW, helper method, not called by Nuclide
|
||||
// Does the same Nuclide script to draw the normal viewmodel at viewzooms between 0.5
|
||||
// and 1.0, Nuclide skips drawing it on any zoom below 1.0 unlike original TS.
|
||||
// Also, handles drawing the akimbo muzzle flash.
|
||||
// Do not call from View_UpdateWeapon. Calling from LatePreDraw (new TS pseudo-event)
|
||||
// is best.
|
||||
// Also this is "Draw" as in render, not equip a weapon
|
||||
void
|
||||
TS_View_DrawCustom(player pl){
|
||||
|
||||
// Same forbidding conditions from Nuclide's src/client/view.qc
|
||||
if (pl.health <= 0) {
|
||||
return;
|
||||
}
|
||||
if (cvar("r_drawviewmodel") == 0 || autocvar_cl_thirdperson == TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Nuclide does not draw the viewmodel at any zoom other than 1.0 (unmodified).
|
||||
// So, this draws the viewmodel the othertimes TS did, in lower zoom choices.
|
||||
// At viewzoom 0.5 and above, the scope graphic is not drawn so it is safe to
|
||||
// do this.
|
||||
if(pl.viewzoom >= 0.5){
|
||||
entity m_eViewModel = pSeat->m_eViewModel;
|
||||
entity m_eMuzzleflash = pSeat->m_eMuzzleflash;
|
||||
entity m_eMuzzleflashAkimbo = pSeatLocal->m_eMuzzleflashAkimbo;
|
||||
|
||||
// (only re-do the default Nuclide viewmodel + normal muzzleflash script if we have reason
|
||||
// to believe Nuclide didn't, i.e., a zoom under 1.0)
|
||||
if(pl.viewzoom < 1.0){
|
||||
// CLONE OF NUCLIDE SCRIPT
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if (m_eMuzzleflash.alpha > 0.0f) {
|
||||
makevectors(getproperty(VF_ANGLES));
|
||||
m_eMuzzleflash.origin = gettaginfo(m_eViewModel, m_eMuzzleflash.skin);
|
||||
m_eMuzzleflash.angles = m_eViewModel.angles;
|
||||
m_eMuzzleflash.angles[2] += (random() * 10) - 5;
|
||||
|
||||
/*dynamiclight_add(pSeat->m_vecPredictedOrigin + (v_forward * 32), 400 * m_eMuzzleflash.alpha, [1,0.45,0]);*/
|
||||
|
||||
setorigin(m_eMuzzleflash, m_eMuzzleflash.origin);
|
||||
addentity(m_eMuzzleflash);
|
||||
}
|
||||
setorigin(m_eViewModel, m_eViewModel.origin);
|
||||
addentity(m_eViewModel);
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// Regardless of being 1.0 or not (Nuclide certainly isn't doing this),
|
||||
// handle the other muzzleflash too
|
||||
if (m_eMuzzleflashAkimbo.alpha > 0.0f) {
|
||||
makevectors(getproperty(VF_ANGLES));
|
||||
m_eMuzzleflashAkimbo.origin = gettaginfo(m_eViewModel, m_eMuzzleflashAkimbo.skin);
|
||||
m_eMuzzleflashAkimbo.angles = m_eViewModel.angles;
|
||||
m_eMuzzleflashAkimbo.angles[2] += (random() * 10) - 5;
|
||||
|
||||
/*dynamiclight_add(pSeat->m_vecPredictedOrigin + (v_forward * 32), 400 * m_eMuzzleflashAkimbo.alpha, [1,0.45,0]);*/
|
||||
|
||||
setorigin(m_eMuzzleflashAkimbo, m_eMuzzleflashAkimbo.origin);
|
||||
addentity(m_eMuzzleflashAkimbo);
|
||||
}
|
||||
}
|
||||
|
||||
if(pl.bShellEjectScheduled){
|
||||
pl.bShellEjectScheduled = FALSE;
|
||||
|
||||
// TODO - how about a first-person check? Doesn't make sense if in thirdperson.
|
||||
// Although that might've been needed earlier unless this event-thing works fine for being
|
||||
// a playermodel too. Players other than the local one being rendered and needing to drop
|
||||
// shells, that sounds like a whole other story
|
||||
if(pl.iShellEjectType != SHELLEJECT_ID::NONE){
|
||||
CTSShellEject::generateForViewModelAkimbo(pl.iShellEjectType, pl.iShellEjectAkimboChoice);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// another helper method
|
||||
// Draw the lasersight, and flashlight effects
|
||||
void
|
||||
TS_View_DrawExtraEffects(player pl, int thirdperson)
|
||||
{
|
||||
//int thirdperson = (autocvar_cl_thirdperson == TRUE || this.entnum != player_localentnum);
|
||||
//base_player pp = (base_player)this;
|
||||
|
||||
BOOL canRenderFlashlight = FALSE;
|
||||
BOOL canRenderLaserSight = FALSE;
|
||||
|
||||
//player pl = (player)pp;
|
||||
//we're going to use the buyopts of our current weapon + the one actually turned on, yah?
|
||||
|
||||
// DEBUG: printouts about the other player.
|
||||
// Start a server with over 1 max players allowed in one window,
|
||||
// connect to it in another window. Boom, read printouts.
|
||||
/*
|
||||
if(entnum != player_localentnum){
|
||||
// so other player's "pl.weaponEquippedID" are not sent over to our clientside copies of them... I guess?
|
||||
// At least that's not confusing.
|
||||
printfline("It is I, the other player! What do I have? %i weapon count: %i", pl.weaponEquippedID, pl.ary_myWeapons_softMax);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if(pl.inventoryEquippedIndex != -1){
|
||||
|
||||
weapondynamic_t dynaRef = pl.ary_myWeapons[pl.inventoryEquippedIndex];
|
||||
|
||||
if(dynaRef.weaponTypeID == WEAPONDATA_TYPEID_GUN || dynaRef.weaponTypeID == WEAPONDATA_TYPEID_IRONSIGHT){
|
||||
weapondata_basic_t* basePRef = pl.getEquippedWeaponData();
|
||||
weapondata_basic_t baseRef = *basePRef;
|
||||
|
||||
|
||||
// We must have the flashlight bit on, AND support it on our weapon, AND it be a possibility according to weapon data.
|
||||
int legalBuyOpts_on = (dynaRef.iBitsUpgrade_on & (dynaRef.iBitsUpgrade & baseRef.iBitsUpgrade));
|
||||
|
||||
if(legalBuyOpts_on & BITS_WEAPONOPT_FLASHLIGHT){
|
||||
canRenderFlashlight = TRUE;
|
||||
}
|
||||
if(legalBuyOpts_on & BITS_WEAPONOPT_LASERSIGHT){
|
||||
canRenderLaserSight = TRUE;
|
||||
}
|
||||
}///END OF _GUN or _IRONSIGHT type checks
|
||||
}//END OF weaponEquippedID check
|
||||
|
||||
|
||||
|
||||
vector posView;
|
||||
vector angView;
|
||||
|
||||
//for glock it is 40.
|
||||
//vector gunpos = gettaginfo(pSeat->eViewModel, 33);
|
||||
|
||||
float daDrawAlphahz = 1.0;
|
||||
const vector lasColor = [1.0, 0, 0];
|
||||
const vector fsize = [2,2];
|
||||
const vector fsizeDot = [18,18];
|
||||
const vector fsizeFlashlightMuzzleGlow = [3, 3];
|
||||
|
||||
vector flashPos;
|
||||
vector gunpos;
|
||||
vector gunpos2 = [0,0,0];
|
||||
vector gunpos_tempEnd;
|
||||
|
||||
|
||||
vector dirGun = [0,0,0];
|
||||
vector dirGun2 = [0,0,0];
|
||||
vector angGun = [0,0,0];
|
||||
vector angGun2 = [0,0,0];
|
||||
|
||||
//TAGGG - IMPORTANT NOTE!!!
|
||||
// BEWARE "view_angles", it is a client global (what a confusing term), meaning it pertains only to THIS
|
||||
// client (local player), no matter what player is being rendered by this call.
|
||||
// wait... shouldn't we do the third-person check for the flash-light check above too?
|
||||
|
||||
BOOL canDrawAkimboLaser = FALSE;
|
||||
pl.recentLaserHitPosSet = TRUE;
|
||||
|
||||
|
||||
|
||||
// TAGGG - QUESTION: Is it better to use the bool "thirdperson"
|
||||
// (see check below involving cl_thirdperson)
|
||||
// OR a raw "pl.entnum != player_localentnum" check?
|
||||
// The former is a more concrete check for, "Am I the local player
|
||||
// looking in 1st person, yes or no?".
|
||||
// The latter will still treat the player being the local player the
|
||||
// same as firstperson, even if the local player is forcing themselves
|
||||
// to be viewed in third person.
|
||||
// I am inclined to think the former is the better choice, but
|
||||
// valve/src/client/flashlight.qc uses the latter way. Why?
|
||||
|
||||
// thirdperson
|
||||
// True IF (autocvar_cl_thirdperson == TRUE || this.entnum != player_localentnum)
|
||||
// False IF (autocvar_cl_thirdperson == FALSE && this.entnum == player_localentnum)
|
||||
if(!thirdperson){
|
||||
|
||||
//TAGGG - Old way!
|
||||
//posView = getproperty(VF_ORIGIN) + [0,0,-8];
|
||||
//angView = getproperty(VF_CL_VIEWANGLES);
|
||||
|
||||
posView = pSeat->m_vecPredictedOrigin + [0,0,-8];
|
||||
angView = view_angles;
|
||||
|
||||
// CHECK: is "getproperty(VF_CL_VIEWANGLES)" always the same as "view_angles"?
|
||||
|
||||
if(!pl.weaponEquippedAkimbo){
|
||||
// first-person and this is the local player?
|
||||
// We can get more specific info from the visible viewmodel, do so!
|
||||
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 0i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 3i);
|
||||
// should shell casings come from a bit behind the firing point here when needed?
|
||||
//gunpos += v_right * 0.8; //why is this 'up'??
|
||||
// not this one maybe... what the hell is this direction at all.
|
||||
//gunpos += v_forward * -1.8;
|
||||
|
||||
dirGun = normalize(gunpos_tempEnd - gunpos);
|
||||
angGun = vectoangles(dirGun);
|
||||
|
||||
|
||||
}else{
|
||||
canDrawAkimboLaser = TRUE;
|
||||
|
||||
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 0i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 1i);
|
||||
dirGun = normalize(gunpos_tempEnd - gunpos);
|
||||
angGun = vectoangles(dirGun);
|
||||
|
||||
gunpos2 = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 2i);
|
||||
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 3i);
|
||||
dirGun2 = normalize(gunpos_tempEnd - gunpos2);
|
||||
angGun2 = vectoangles(dirGun2);
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
posView = pl.origin + pl.view_ofs;
|
||||
angView = [pl.pitch, pl.angles[1], pl.angles[2]];
|
||||
gunpos = posView;
|
||||
angGun = angView;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(canRenderLaserSight && pl.entnum == player_localentnum){
|
||||
// The lasersight displays a number of distance to show how long the laser goes.
|
||||
//makevectors(view_angles);
|
||||
makevectors(angView);
|
||||
traceline(posView, posView + v_forward * 2048*4, MOVE_HITMODEL, pl);
|
||||
pl.recentLaserDistanceDisplay = (int)(vlen(trace_endpos - posView) / 40 );
|
||||
}
|
||||
|
||||
|
||||
// DEBUG!!!
|
||||
//canRenderLaserSight = TRUE;
|
||||
//canRenderFlashlight = TRUE;
|
||||
|
||||
if(canRenderFlashlight){
|
||||
//TAGGG - FLASHLIGHT STUFF HERE..
|
||||
// oh wait a comment above already said that
|
||||
// HOWEVER... in TS flashlights have a range limit. Up to so far they have max brightness,
|
||||
// then it lowers with a bit of range, then it's nothing.
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
int flashlightRangeMax = 1070;
|
||||
float flashlightBrightnessFactor = 1.0;
|
||||
float rangeDimPriorStart = 170; //rangeMax minus this is where I start dimming.
|
||||
|
||||
makevectors(angView);
|
||||
|
||||
traceline(posView, posView + (v_forward * flashlightRangeMax), MOVE_NORMAL, pl);
|
||||
int traceDist = trace_fraction * flashlightRangeMax;
|
||||
|
||||
//printfline("%.2f %d",, trace_fraction, trace_inopen);
|
||||
|
||||
//TODO - not here but elsewhere, draw the muzzle flashlight effect, some sprite on that gun attachment where am uzzleflash would go should do it.
|
||||
// ALSO, go ahead and use this line trace to tell the lasersight how far the laser went.
|
||||
// And just draw the lasersight (and dot if necessary), IF this render is for the local player.
|
||||
// If not the local player, a slightly larger red dot (actual sprite) goes at the point the
|
||||
// player is looking, likely not influenced by animations / view-model stuff.
|
||||
|
||||
|
||||
if(trace_fraction == 1.0){
|
||||
//uh-oh.
|
||||
flashlightBrightnessFactor = 0;
|
||||
}if(traceDist >= flashlightRangeMax - rangeDimPriorStart){
|
||||
//the flashlight gets dimmer the further it is at this point.
|
||||
// rangeDimPriorStart from the end: max bright still.
|
||||
// very end: 0% bright.
|
||||
flashlightBrightnessFactor = (-flashlightRangeMax * (trace_fraction + -1)) / rangeDimPriorStart;
|
||||
}
|
||||
|
||||
if(flashlightBrightnessFactor > 0){
|
||||
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
|
||||
dynamiclight_add(trace_endpos + (v_forward * -2), 128 * flashlightBrightnessFactor, [1,1,1]);
|
||||
} else {
|
||||
float p = dynamiclight_add(posView, 512 * flashlightBrightnessFactor, [1,1,1], 0, "textures/flashlight");
|
||||
dynamiclight_set(p, LFIELD_ANGLES, angView);
|
||||
dynamiclight_set(p, LFIELD_FLAGS, 3);
|
||||
}
|
||||
}//END OF brightness check
|
||||
|
||||
|
||||
}//END OF "flashlight is on" criteria
|
||||
|
||||
|
||||
if(canRenderLaserSight || canRenderFlashlight){
|
||||
// TRY IT SOMEHOW? RF_DEPTHHACK
|
||||
//pSeat->m_eViewModel.renderflags = RF_DEPTHHACK;
|
||||
//if (alpha <= 0.0f) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
makevectors(angGun);
|
||||
|
||||
//rotatevectorsbyangle( [-0.42, 0.75, 0] );
|
||||
//rotatevectorsbyangle( [-0.52, 0.85, 0] );
|
||||
rotatevectorsbyangle( [-0.45, 0.27, 0] );
|
||||
|
||||
|
||||
flashPos = gunpos + v_up * -0.08 + v_right * 0.06;
|
||||
|
||||
|
||||
vector shortForwardEnd = gunpos;
|
||||
shortForwardEnd += v_forward * -1;
|
||||
shortForwardEnd += v_up * (0.22); //why is this 'up'??
|
||||
shortForwardEnd += v_right * (0.35); //why is this 'up'??
|
||||
|
||||
//makevectors(m_vecAngle); really now
|
||||
//makevectors(input_angles); //maybe this if we need to do this.
|
||||
|
||||
// v_up * 2. or.. 1.6, for size [3,3] at least.
|
||||
// for size [5,5], we need v_up*3, v_right*2. I DONT KNOW.
|
||||
// for size [2, 2], we want v_up*5, v_right*5. Go figure that one out.
|
||||
|
||||
// Keep in mind, the global vectors (v_up, etc.) are set to the orientation of the recently received
|
||||
// viewmodel attachment (gettaginfo above). Don't 'makevectors' at all to simply rely on that.
|
||||
// ...unfortunately the orientation we get back is not great either. oh well.
|
||||
|
||||
// NEW TEST. Can we even get a straight line from the player's center to the gunpos?
|
||||
|
||||
traceline(posView, shortForwardEnd, FALSE, pl);
|
||||
if(trace_fraction >= 1.0){
|
||||
//woohoo!
|
||||
|
||||
traceline(shortForwardEnd, shortForwardEnd + v_forward * 1024, MOVE_HITMODEL, pl);
|
||||
|
||||
// other places care about this.
|
||||
if (pl.entnum == player_localentnum) {
|
||||
pl.recentLaserHitPos = trace_endpos;
|
||||
}
|
||||
|
||||
if(canRenderLaserSight){
|
||||
|
||||
// In original TS, the 'laster' does not render for the local player if they are
|
||||
// in thirdperson to see their own playermodel. I... don't really understand that,
|
||||
// feels like a mistake. The lasers from other players are visible.
|
||||
|
||||
// TAGGG - TODO - SUPER LOW PRIORITY
|
||||
// Lasers only for not in 3rd person and local player.
|
||||
// Could work for the third-person model or other players if there were a way to determine
|
||||
// the muzzle-end point for player models. Unsure if that is possible.
|
||||
// To see it in third-person anyway, just change the "!thirdperson" condition below
|
||||
// to "TRUE"; always do it. There is no separate place that does only first-person lasers
|
||||
// to worry about being redundant with.
|
||||
// Note the laser will try to face the direction the player model is, which may not
|
||||
// necessarily be where the player is looking, although that same issue would come up
|
||||
// with firing anyway; you would look like you're firing sideways anyway, this would be
|
||||
// just as "off".
|
||||
if (!thirdperson) {
|
||||
//makevectors(view_angles); //??? it seems we do not need this perhaps...
|
||||
// IN SHORT, we're riding the prior "makevectors(angGun);".
|
||||
R_BeginPolygon("sprites/laserbeam.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(gunpos + v_right * fsize[0] - v_up * fsize[1], [1,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(gunpos - v_right * fsize[0] - v_up * fsize[1], [0,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], [0,0], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], [1,0], lasColor, daDrawAlphahz);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
// Draw the laser sprite effect at where the laser is hitting, but ONLY for every other player
|
||||
// except this one. That's because, for the local player, we already are drawing the laserdot
|
||||
// projected onto the screen in the HUD logic.
|
||||
|
||||
if (pl.entnum != player_localentnum) {
|
||||
makevectors(angView);
|
||||
|
||||
trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/laserdot.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] - v_up * fsizeDot[1], [1,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] - v_up * fsizeDot[1], [0,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] + v_up * fsizeDot[1], [0,0], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] + v_up * fsizeDot[1], [1,0], lasColor, 0.80f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
}//END OF canRenderLaserSight
|
||||
|
||||
|
||||
// glow effect on top of the gun muzzle while the flashlight is on?
|
||||
if(canRenderFlashlight){
|
||||
if(!thirdperson){
|
||||
makevectors(angView);
|
||||
|
||||
//trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/glow02.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [1,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [0,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [0,0], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [1,0], [1,1,1], 0.45f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
}//END OF trace pre-check
|
||||
|
||||
|
||||
// This requires the current weapon to be akimbo, player is in first person,
|
||||
// and the local player is being rendered.
|
||||
if(canDrawAkimboLaser){
|
||||
// test for the 2nd gun's laser too then.
|
||||
// makevectors(theDir);
|
||||
makevectors(angGun2);
|
||||
rotatevectorsbyangle( [-0.45, 0.27, 0] );
|
||||
|
||||
//gunpos2 += v_forward * -18;
|
||||
|
||||
flashPos = gunpos2 + v_up * -0.08 + v_right * 0.06;
|
||||
|
||||
shortForwardEnd = gunpos2;
|
||||
shortForwardEnd += v_forward * -1;
|
||||
shortForwardEnd += v_up * (0.22); //why is this 'up'??
|
||||
shortForwardEnd += -v_right * (0.35); //why is this 'up'??
|
||||
|
||||
|
||||
traceline(posView, shortForwardEnd, FALSE, pl);
|
||||
if(trace_fraction >= 1.0){
|
||||
|
||||
traceline(shortForwardEnd, shortForwardEnd + v_forward * 1024, MOVE_HITMODEL, pl);
|
||||
|
||||
// other places care about this.
|
||||
if (pl.entnum == player_localentnum) {
|
||||
pl.recentLaserHitPos2 = trace_endpos;
|
||||
}
|
||||
|
||||
if(canRenderLaserSight){
|
||||
if (!thirdperson) {
|
||||
// ONLY render the polygon
|
||||
// makevectors(view_angles); //??? it seems we do not need this perhaps...
|
||||
// IN SHORT, we're riding the prior "makevectors(angGun2);".
|
||||
|
||||
R_BeginPolygon("sprites/laserbeam.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(gunpos2 + v_right * fsize[0] - v_up * fsize[1], [1,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(gunpos2 - v_right * fsize[0] - v_up * fsize[1], [0,1], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], [0,0], lasColor, daDrawAlphahz);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], [1,0], lasColor, daDrawAlphahz);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
if (pl.entnum != player_localentnum) {
|
||||
//makevectors(view_angles);
|
||||
makevectors(angView);
|
||||
|
||||
trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/laserdot.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] - v_up * fsizeDot[1], [1,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] - v_up * fsizeDot[1], [0,1], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos - v_right * fsizeDot[0] + v_up * fsizeDot[1], [0,0], lasColor, 0.80f);
|
||||
R_PolygonVertex(trace_endpos + v_right * fsizeDot[0] + v_up * fsizeDot[1], [1,0], lasColor, 0.80f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(canRenderFlashlight){
|
||||
if(!thirdperson){
|
||||
//makevectors(view_angles);
|
||||
makevectors(angView);
|
||||
|
||||
//trace_endpos += trace_plane_normal * fsizeDot[0]/6;
|
||||
R_BeginPolygon("sprites/glow02.spr_0.tga", 1, 0);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [1,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] - v_up * fsizeFlashlightMuzzleGlow[1], [0,1], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos - v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [0,0], [1,1,1], 0.45f);
|
||||
R_PolygonVertex(flashPos + v_right * fsizeFlashlightMuzzleGlow[0] + v_up * fsizeFlashlightMuzzleGlow[1], [1,0], [1,1,1], 0.45f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
|
||||
}//END OF trace pre-check
|
||||
}//END OF akimbo check
|
||||
|
||||
/*
|
||||
if (m_iBeams == 0) {
|
||||
alpha -= clframetime * 3;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}else{
|
||||
pl.recentLaserHitPosSet = FALSE;
|
||||
}//END OF canRenderLaserSight || canRenderFlashlight
|
||||
|
||||
}
|
||||
|
||||
|
||||
//TAGGG - NEW. Similar to Nuclide's provided "View_SetMuzzleflash", but also acts
|
||||
// as though the first frame were an event by doing the same lines as a 5000-ish
|
||||
// event. This is because TS weapons don't have events for the muzzle flash
|
||||
// unlike HL ones, must be hardcoded to show up.
|
||||
// Figuring out what muzzle flash for what weapon will come another time.
|
||||
// For now using the same HL set, but TS comes with some muzzle-flash looking sprites.
|
||||
// ALSO - for now, always assuming attachment #0.
|
||||
// For the model event in case that changes, see Nuclide's src/client/modelevent.qc,
|
||||
// Event_ProcessModel.
|
||||
void
|
||||
TS_View_ShowMuzzleflash(int index, int akimboChoice)
|
||||
{
|
||||
// use the akimbo choice to tell which one to show, or both
|
||||
// (NONE means this is a singular weapon)
|
||||
if(akimboChoice == BITS_AKIMBOCHOICE_NONE || (akimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
|
||||
pSeat->m_eMuzzleflash.modelindex = (float)index;
|
||||
// Event_ProcessModel: force it.
|
||||
pSeat->m_eMuzzleflash.alpha = 1.0f;
|
||||
pSeat->m_eMuzzleflash.scale = 0.25;
|
||||
// attachment #0 is m_iVMBones + 0. Add for #1 to #3, I think.
|
||||
// No idea if any weapons play with attachments, #0 should always
|
||||
// be the end of the weapon for flashes
|
||||
pSeat->m_eMuzzleflash.skin = pSeat->m_iVMBones + 0;
|
||||
}
|
||||
if(akimboChoice & BITS_AKIMBOCHOICE_LEFT){
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.modelindex = (float)index;
|
||||
// Event_ProcessModel: force it.
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.alpha = 1.0f;
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.scale = 0.25;
|
||||
// akimbo attachments are in pairs:
|
||||
// 0 on one weapon, 1 further out along that weapon's direction,
|
||||
// 2 on the other weapon, 3 further along the other weapon's direction.
|
||||
// ALSO: on akimbo weapons, attachments 0 and 1 are for the right weapon,
|
||||
// 1 and 2 for the left.
|
||||
pSeatLocal->m_eMuzzleflashAkimbo.skin = pSeat->m_iVMBones + 2;
|
||||
}
|
||||
}
|
||||
|
||||
//TAGGG - loaned from The Wastes.
|
||||
void TS_View_HandleZoom(void)
|
||||
{
|
||||
|
|
|
@ -66,38 +66,13 @@ Viewmodel_CalcBob(void)
|
|||
|
||||
int inputLen = vlen(input_movevalues);
|
||||
|
||||
// do we care about "self.maxspeed" ??
|
||||
// do we care about "self.maxspeed" ?
|
||||
|
||||
// Instead of some new bTouchingGround, using the presence of flag FL_ONGROUND.
|
||||
// If the player waterlevel >= 2, the "FL_ONGROUND" flag never occurs,
|
||||
// regardless of touching the floor in the area.
|
||||
// In original TS, being on the floor underwater DOES still do the camera/viewbob.
|
||||
// No idea how to get around this, beyond traces against the ground like pmove
|
||||
// does.
|
||||
|
||||
BOOL bOnGround = FALSE;
|
||||
|
||||
if(pl.waterlevel < 2){
|
||||
// Easy, trsy pl.flags having FL_ONGROUND.
|
||||
bOnGround = ((pl.flags & FL_ONGROUND) != 0);
|
||||
}else{
|
||||
// Underwater enough? Need to do a re-trace, FL_ONGROUND is forced off by
|
||||
// pmove.
|
||||
// Open for better ideas, or maybe this is a massive "who cares" situation.
|
||||
|
||||
tracebox(pl.origin, pl.mins, pl.maxs, pl.origin - [0,0,0.25], FALSE, pl);
|
||||
|
||||
if (!trace_startsolid) {
|
||||
if ((trace_fraction < 1) && (trace_plane_normal[2] > 0.7)) {
|
||||
bOnGround = TRUE;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!bOnGround){
|
||||
// could check for FL_ONGROUND, but it is never set when the player is touching the ground
|
||||
// while underwater, even though orginal TS viewbob counts that too.
|
||||
// TODO: may as well turn this into a separate bitflag too then.
|
||||
if(!pl.bOnGround){
|
||||
float timeTol;
|
||||
vector vSource = pl.origin;
|
||||
|
||||
|
|
|
@ -157,9 +157,24 @@ class player:base_player
|
|||
|
||||
// same as below for muzzleflash.
|
||||
int iMuzzleFlashType;
|
||||
// and akimbo support
|
||||
int iMuzzleFlashAkimboChoice;
|
||||
|
||||
|
||||
// During a shell-eject event, what member of aryShellEjectData do I use for the model
|
||||
// and hitsound script file to use? Set on setting the event
|
||||
// and hitsound script file to use? Set on setting up the event so that it is only
|
||||
// called once, clientside weapons can be strange.
|
||||
// Must be stored as a var to be preserved for the event (which does not take any params,
|
||||
// and is called very shortly after being set in a separate stream of execution).
|
||||
int iShellEjectType;
|
||||
// And, for which weapon? Default is LEFT (attachment #0)
|
||||
int iShellEjectAkimboChoice;
|
||||
// Not involved in setting up the shell-eject event. Rather, it is set BY the shell-eject
|
||||
// event to ensure this only happens once per fire animation.
|
||||
// When seen TRUE in TS_View_DrawCustom, the shell ejection actually happens for the
|
||||
// most accurate position.
|
||||
BOOL bShellEjectScheduled;
|
||||
|
||||
|
||||
// WEAPON KICKBACK STUFF.
|
||||
// Way it works is a little different from the average (Half-Life and Counterstrike).
|
||||
|
@ -350,14 +365,16 @@ class player:base_player
|
|||
// at what time do I throw the grenade after starting the throw/toss anim?
|
||||
float grenadeSpawnTime;
|
||||
float grenadeHeldDuration;
|
||||
PREDICTED_FLOAT(grenadeToss); //set to FALSE if it's a typical throw instead.
|
||||
PREDICTED_FLOAT(bGrenadeToss); //set to FALSE if it's a typical throw instead.
|
||||
|
||||
|
||||
// shared
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//for pmove to set
|
||||
BOOL viewAboveWater;
|
||||
// for custom pmove to set
|
||||
// TODO: these should probably be gflags constants as bitflags instead
|
||||
BOOL bOnGround;
|
||||
BOOL bViewAboveWater;
|
||||
|
||||
//TODO - could this just be an entity flag just as well? Unfortunately I don't know for
|
||||
// sure what flags are guaranteed open / nonconflicting with anything else.
|
||||
|
|
|
@ -203,7 +203,7 @@ player::ReceiveEntity(float new, float fl)
|
|||
nextAkimboAttackPreference = readbyte();
|
||||
akimboDualFireToleranceTime = readfloat();
|
||||
grenadeFireIndex = readbyte() - 1;
|
||||
grenadeToss = readbyte();
|
||||
bGrenadeToss = readbyte();
|
||||
|
||||
|
||||
armor = readbyte();
|
||||
|
@ -381,7 +381,7 @@ player::PredictPreFrame(void)
|
|||
SAVE_STATE(nextAkimboAttackPreference);
|
||||
SAVE_STATE(akimboDualFireToleranceTime);
|
||||
SAVE_STATE(grenadeFireIndex);
|
||||
SAVE_STATE(grenadeToss);
|
||||
SAVE_STATE(bGrenadeToss);
|
||||
|
||||
SAVE_STATE(shotgunReloadIndex);
|
||||
|
||||
|
@ -480,7 +480,7 @@ player::PredictPostFrame(void)
|
|||
ROLL_BACK(nextAkimboAttackPreference);
|
||||
ROLL_BACK(akimboDualFireToleranceTime);
|
||||
ROLL_BACK(grenadeFireIndex);
|
||||
ROLL_BACK(grenadeToss);
|
||||
ROLL_BACK(bGrenadeToss);
|
||||
|
||||
ROLL_BACK(shotgunReloadIndex);
|
||||
|
||||
|
@ -670,7 +670,7 @@ player::EvaluateEntity(void)
|
|||
SAVE_STATE(nextAkimboAttackPreference);
|
||||
SAVE_STATE(akimboDualFireToleranceTime);
|
||||
SAVE_STATE(grenadeFireIndex);
|
||||
SAVE_STATE(grenadeToss);
|
||||
SAVE_STATE(bGrenadeToss);
|
||||
|
||||
|
||||
SAVE_STATE(shotgunReloadIndex);
|
||||
|
@ -825,7 +825,7 @@ player::SendEntity(entity ePEnt, float fChanged)
|
|||
WriteByte(MSG_ENTITY, nextAkimboAttackPreference);
|
||||
WriteFloat(MSG_ENTITY, akimboDualFireToleranceTime);
|
||||
WriteByte(MSG_ENTITY, grenadeFireIndex + 1);
|
||||
WriteByte(MSG_ENTITY, grenadeToss);
|
||||
WriteByte(MSG_ENTITY, bGrenadeToss);
|
||||
|
||||
WriteByte(MSG_ENTITY, armor );
|
||||
WriteByte(MSG_ENTITY, iTotalSlots );
|
||||
|
@ -1123,7 +1123,7 @@ player::reset(BOOL resetInventory){
|
|||
grenadeFireIndex = -1;
|
||||
grenadeHeldDuration = -1;
|
||||
grenadeSpawnTime = -1;
|
||||
grenadeToss = FALSE;
|
||||
bGrenadeToss = FALSE;
|
||||
|
||||
isReloading = FALSE;
|
||||
isChangingIronsight = FALSE;
|
||||
|
|
|
@ -269,6 +269,14 @@ player::Physics_WaterJump(void)
|
|||
float
|
||||
player::Physics_MaxSpeed(void)
|
||||
{
|
||||
|
||||
// Consider noclip. Otherwise, moving downward is considerably slower for no
|
||||
// apparent reason (FL_CROUCHING input detected further down).
|
||||
if(this.movetype == MOVETYPE_NOCLIP){
|
||||
return serverkeyfloat("phy_maxspeed");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
float parentResult = base_player::Physics_MaxSpeed();
|
||||
return parentResult;
|
||||
|
@ -283,7 +291,9 @@ player::Physics_MaxSpeed(void)
|
|||
|
||||
//TAGGG - CRITICAL TODO. Check for prone, that gets set to 30% of normal speed and only
|
||||
// allows for sideways movement, ignore input_movevalues[#] whatever is the forward one. probably 0.
|
||||
if ( this.flags & FL_CROUCHING ) {
|
||||
// TODO: does this slow down lateral movement while trying to go downard underwater? Does it even
|
||||
// signal for that at all? This might be a non-issue.
|
||||
if((this.flags & FL_CROUCHING) ){
|
||||
targetSpeed = serverkeyfloat("phy_maxspeed") * 1.0 * 0.33;
|
||||
} else {
|
||||
targetSpeed = serverkeyfloat("phy_maxspeed") * 1.0;
|
||||
|
@ -292,6 +302,10 @@ player::Physics_MaxSpeed(void)
|
|||
|
||||
if(time <= this.fMoveBlockDelay){
|
||||
// don't move much until this has passed. Further slowdowns need not apply.
|
||||
// !
|
||||
// "fMoveBlockCapSpeed" must be set by a weapon before it is involved.
|
||||
// Is that the best way to handle this? Being a field in all weapon data would
|
||||
// not make sense though, not much uses this
|
||||
targetSpeed = min(targetSpeed, this.fMoveBlockCapSpeed);
|
||||
return targetSpeed;
|
||||
}
|
||||
|
@ -314,6 +328,23 @@ player::Physics_InputPreMove(void)
|
|||
{
|
||||
base_player::Physics_InputPreMove();
|
||||
|
||||
// IDEA: is changing the speed by inputmove value adjusting better than changing
|
||||
// the max speed for prediction wonkiness (the camera looks to jump around on slowing down
|
||||
// since a recent karate attack)?
|
||||
// from Nuclide's player_move.qc (holding use-key slowdown):
|
||||
//if (input_buttons & INPUT_BUTTON5) {
|
||||
// input_movevalues *= 0.25;
|
||||
//}
|
||||
|
||||
// also, reduce the up/down noclip movement a bit, no need to be that quite that fast in
|
||||
// most cases
|
||||
if (input_buttons & INPUT_BUTTON2) {
|
||||
input_movevalues[2] *= 0.7;
|
||||
}
|
||||
if (input_buttons & INPUT_BUTTON8) {
|
||||
input_movevalues[2] *= 0.7;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -345,42 +376,87 @@ player::Physics_Run(void)
|
|||
// Copied from PMoveCustom_Categorize / PMove_Categorize, whatever we're calling it,
|
||||
// from Nuclide.
|
||||
// Any changes to what PMoveCustom_Categorize already changes would be redundant,
|
||||
// this is only to do a finer check for a new var, 'viewAboveWater', a more accurate
|
||||
// this is only to do a finer check for a new var, 'bViewAboveWater', a more accurate
|
||||
// check than 'pl.waterlevel < 3'.
|
||||
// Or maybe this will be deemed pointless and scrapped anyway, that isn't too bad and
|
||||
// it's what nearly any goldsource mod did, probably quake-based in general.
|
||||
int contents;
|
||||
|
||||
contents = PMoveCustom_Contents(this.origin + this.mins + [0,0,1]);
|
||||
|
||||
if (contents & CONTENTBIT_WATER) {
|
||||
contents = CONTENT_WATER;
|
||||
} else if (contents & CONTENTBIT_SLIME) {
|
||||
contents = CONTENT_SLIME;
|
||||
} else if (contents & CONTENTBIT_LAVA) {
|
||||
contents = CONTENT_LAVA;
|
||||
}
|
||||
|
||||
|
||||
//player pl = (player)self;
|
||||
this.viewAboveWater = TRUE;
|
||||
|
||||
// how far underwater are we?
|
||||
if (contents < CONTENT_SOLID && !(this.flags & FL_ONLADDER)) {
|
||||
//this.watertype = contents;
|
||||
// But first some common sense checks with the existing determined pl.waterlevel.
|
||||
// 0: not touching water at all
|
||||
// 1: at least the bottom of the bounding box, not past the halfway point up
|
||||
// 2: between the halfway point up and very close to the top
|
||||
// 3: close to the very top or completely submerged
|
||||
//... so we only need to be more specifc with the trace below if pl.waterlevel is 2
|
||||
if(this.waterlevel < 2){
|
||||
// definitely so (not in water at all also counts)
|
||||
this.bViewAboveWater = TRUE;
|
||||
}else if (this.waterlevel == 3){
|
||||
// submerged so no
|
||||
this.bViewAboveWater = FALSE;
|
||||
}else{
|
||||
// == 2? Check
|
||||
int contents;
|
||||
|
||||
// Let's do this check sperately instead of below.
|
||||
// Little margin of error (-5 in .z) to see if the viewmodel is probably above/below water.
|
||||
if(PMoveCustom_Contents(this.origin + this.view_ofs - '0 0 5') & CONTENTBITS_FLUID){
|
||||
this.viewAboveWater = FALSE;
|
||||
contents = PMoveCustom_Contents(this.origin + this.mins + [0,0,1]);
|
||||
|
||||
if (contents & CONTENTBIT_WATER) {
|
||||
contents = CONTENT_WATER;
|
||||
} else if (contents & CONTENTBIT_SLIME) {
|
||||
contents = CONTENT_SLIME;
|
||||
} else if (contents & CONTENTBIT_LAVA) {
|
||||
contents = CONTENT_LAVA;
|
||||
}
|
||||
|
||||
} else {
|
||||
//this.watertype = CONTENT_EMPTY;
|
||||
///this.waterlevel = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
this.bViewAboveWater = TRUE;
|
||||
|
||||
// how far underwater are we?
|
||||
if (contents < CONTENT_SOLID && !(this.flags & FL_ONLADDER)) {
|
||||
//this.watertype = contents;
|
||||
|
||||
// Let's do this check sperately instead of below.
|
||||
// Little margin of error (-5 in .z) to see if the viewmodel is probably above/below water.
|
||||
vector vTest = this.origin + this.view_ofs - [0, 0, 5];
|
||||
if(PMoveCustom_Contents(vTest) & CONTENTBITS_FLUID){
|
||||
this.bViewAboveWater = FALSE;
|
||||
}
|
||||
|
||||
} else {
|
||||
//this.watertype = CONTENT_EMPTY;
|
||||
///this.waterlevel = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
}// bViewAboveWater check
|
||||
|
||||
}
|
||||
|
||||
|
||||
// If the player waterlevel >= 2, the "FL_ONGROUND" flag never occurs,
|
||||
// regardless of touching the floor while underwater (as seen in Nuclide pmove).
|
||||
// In original TS, being on the floor underwater DOES still do the camera/viewbob.
|
||||
// No idea how to get around this, beyond traces against the ground like pmove
|
||||
// does.
|
||||
// Open for better ideas, or maybe this is a massive "who cares" situation.
|
||||
|
||||
if(this.waterlevel < 2){
|
||||
// Easy, trsy pl.flags having FL_ONGROUND.
|
||||
this.bOnGround = ((this.flags & FL_ONGROUND) != 0);
|
||||
}else{
|
||||
// Underwater enough? Need to do a re-trace, FL_ONGROUND is forced off by
|
||||
// pmove.
|
||||
|
||||
// until proven otherwise
|
||||
this.bOnGround = FALSE;
|
||||
vector vTest2 = this.origin - [0,0,0.25];
|
||||
tracebox(this.origin, this.mins, this.maxs, vTest2, FALSE, this);
|
||||
|
||||
if (!trace_startsolid) {
|
||||
if ((trace_fraction < 1) && (trace_plane_normal[2] > 0.7)) {
|
||||
this.bOnGround = TRUE;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}// Physics_Run
|
||||
|
||||
|
||||
|
|
|
@ -234,8 +234,8 @@ if (pl.inputSecondaryTapFrameCount == 0)\
|
|||
// OLD UNDERWATER CHECK. Using a new var for more accuracy.
|
||||
//#define WEAPON_UNDERWATER_CHECK pl.waterlevel >= 3
|
||||
//#define WEAPON_UNDERWATER_CHECK_NOT pl.waterlevel < 3
|
||||
#define WEAPON_UNDERWATER_CHECK !pl.viewAboveWater
|
||||
#define WEAPON_UNDERWATER_CHECK_NOT pl.viewAboveWater
|
||||
#define WEAPON_UNDERWATER_CHECK !pl.bViewAboveWater
|
||||
#define WEAPON_UNDERWATER_CHECK_NOT pl.bViewAboveWater
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -860,8 +860,11 @@ void weapon_throwable_onDrawHUD(player pl, weapondata_throwable_t* basePRef, wea
|
|||
void weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t arg_thisWeapon);
|
||||
|
||||
void weapon_ShowMuzzleFlash(int arg_muzzleFlashType);
|
||||
void weapon_ShowMuzzleFlashAkimbo(int arg_muzzleFlashType, int arg_akimboChoice);
|
||||
void weapon_EjectShell(int arg_shellEjectType);
|
||||
void weapon_EjectShellAkimbo(int arg_shellEjectType, int arg_akimboChoice);
|
||||
void weapon_ClientEffects(int arg_muzzleFlashType, int arg_shellEjectType);
|
||||
void weapon_ClientEffectsAkimbo(int arg_muzzleFlashType, int arg_shellEjectType, int arg_akimboChoice);
|
||||
|
||||
void weapon_precache(weapondata_basic_t* basePRef);
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ weapon_t g_weapons[WEAPON_ID::LAST_ID];
|
|||
|
||||
|
||||
void
|
||||
weaponconfig_data_init(weaponconfig_data_t* arg_this){
|
||||
weaponconfig_data_init(weaponconfig_data_t* arg_this)
|
||||
{
|
||||
arg_this->ary_myWeapons_softMax = 0;
|
||||
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
|
||||
arg_this->ary_ammoTotal[i] = 0;
|
||||
|
@ -30,7 +31,8 @@ weaponconfig_data_init(weaponconfig_data_t* arg_this){
|
|||
|
||||
|
||||
void
|
||||
weapon_base_setWholeAttackDelay(player pl, float amount){
|
||||
weapon_base_setWholeAttackDelay(player pl, float amount)
|
||||
{
|
||||
pl.w_attack_next = amount;
|
||||
pl.w_attack_akimbo_next = amount;
|
||||
|
||||
|
@ -43,14 +45,16 @@ weapon_base_setWholeAttackDelay(player pl, float amount){
|
|||
|
||||
// normal delay only?
|
||||
void
|
||||
weapon_base_setLeftAttackDelay(player pl, float amount){
|
||||
weapon_base_setLeftAttackDelay(player pl, float amount)
|
||||
{
|
||||
pl.w_attack_next = amount;
|
||||
//SAVE_STATE(pl.w_attack_next);
|
||||
}
|
||||
|
||||
// akimbo secondary delay only?
|
||||
void
|
||||
weapon_base_setRightAttackDelay(player pl, float amount){
|
||||
weapon_base_setRightAttackDelay(player pl, float amount)
|
||||
{
|
||||
pl.w_attack_akimbo_next = amount;
|
||||
//SAVE_STATE(pl.w_attack_akimbo_next);
|
||||
}
|
||||
|
@ -61,7 +65,8 @@ weapon_base_setRightAttackDelay(player pl, float amount){
|
|||
// If there are 2 seconds left until firing is allowed, ignore a request
|
||||
// to set it to 0.3 seconds.
|
||||
void
|
||||
weapon_base_setLeftAttackDelay_AtLeast(player pl, float amount){
|
||||
weapon_base_setLeftAttackDelay_AtLeast(player pl, float amount)
|
||||
{
|
||||
if(pl.w_attack_next <= amount){
|
||||
pl.w_attack_next = amount;
|
||||
//SAVE_STATE(pl.w_attack_next);
|
||||
|
@ -70,7 +75,8 @@ weapon_base_setLeftAttackDelay_AtLeast(player pl, float amount){
|
|||
|
||||
// akimbo secondary delay only?
|
||||
void
|
||||
weapon_base_setRightAttackDelay_AtLeast(player pl, float amount){
|
||||
weapon_base_setRightAttackDelay_AtLeast(player pl, float amount)
|
||||
{
|
||||
if(pl.w_attack_akimbo_next <= amount){
|
||||
pl.w_attack_akimbo_next = amount;
|
||||
//SAVE_STATE(pl.w_attack_akimbo_next);
|
||||
|
@ -272,7 +278,8 @@ weapon_base_onPrimaryAttack_melee_fromCustomDirection(
|
|||
|
||||
// Apparently serverside-only? ok...
|
||||
void
|
||||
weapon_base_onAttack(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
|
||||
weapon_base_onAttack(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int attackTypeUsed)
|
||||
{
|
||||
weapon_base_onAttack_multi(pl, basePRef, arg_thisWeapon, 1, attackTypeUsed);
|
||||
}// weapon_base_onAttack
|
||||
|
||||
|
@ -287,7 +294,8 @@ weapon_base_onAttack(player pl, weapondata_basic_t* basePRef, weapondynamic_t ar
|
|||
// (effectively becomes 'max number of penetrations allowed', which is still something only for guns)
|
||||
// NOTE - checks for being unable to fire yet not included!
|
||||
void
|
||||
weapon_base_onAttack_multi(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int shellCount, int attackTypeUsed){
|
||||
weapon_base_onAttack_multi(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int shellCount, int attackTypeUsed)
|
||||
{
|
||||
|
||||
#ifdef SERVER
|
||||
weapondata_gun_t baseRef = *((weapondata_gun_t*)basePRef);
|
||||
|
@ -526,7 +534,8 @@ weapon_shotgun_reload(
|
|||
// (don't do anything if not of course)
|
||||
// Also, this is meant to completely replace the weapon_gun_onThink call that most would have used.
|
||||
void
|
||||
weapon_shotgun_onThink_reloadLogic(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon){
|
||||
weapon_shotgun_onThink_reloadLogic(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon)
|
||||
{
|
||||
weapondata_gun_t baseRef = *basePRef;
|
||||
weapondata_shotgun_extra_t* shotgunExtraRef;
|
||||
|
||||
|
@ -1642,7 +1651,8 @@ weapon_gun_onThink_burstFireLogic(
|
|||
|
||||
|
||||
void
|
||||
weapon_gun_onDrawHUD(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon){
|
||||
weapon_gun_onDrawHUD(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
weapondata_gun_t baseRef = *basePRef;
|
||||
|
||||
|
@ -1780,7 +1790,8 @@ weapon_gun_onDrawHUD(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_
|
|||
|
||||
|
||||
void
|
||||
weapon_throwable_onDrawHUD(player pl, weapondata_throwable_t* basePRef, weapondynamic_t arg_thisWeapon){
|
||||
weapon_throwable_onDrawHUD(player pl, weapondata_throwable_t* basePRef, weapondynamic_t arg_thisWeapon)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
weapondata_throwable_t baseRef = *basePRef;
|
||||
|
||||
|
@ -1806,7 +1817,8 @@ weapon_throwable_onDrawHUD(player pl, weapondata_throwable_t* basePRef, weapondy
|
|||
|
||||
|
||||
void
|
||||
weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t arg_thisWeapon){
|
||||
weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t arg_thisWeapon)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
weapondata_melee_t baseRef = *basePRef;
|
||||
|
||||
|
@ -1830,16 +1842,25 @@ weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t
|
|||
}// weapon_throwable_onDrawHUD
|
||||
|
||||
|
||||
|
||||
void
|
||||
weapon_ShowMuzzleFlash(int arg_muzzleFlashType){
|
||||
weapon_ShowMuzzleFlash(int arg_muzzleFlashType)
|
||||
{
|
||||
weapon_ShowMuzzleFlashAkimbo(arg_muzzleFlashType, BITS_AKIMBOCHOICE_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
weapon_ShowMuzzleFlashAkimbo(int arg_muzzleFlashType, int arg_akimboChoice)
|
||||
{
|
||||
|
||||
#ifdef CLIENT
|
||||
if(arg_muzzleFlashType != MUZZLEFLASH_ID::NONE){
|
||||
// not yet!
|
||||
//muzzleflashdata_t* tempRef = ary_muzzleFlashData[arg_muzzleFlashType];
|
||||
//View_ShowMuzzleflash((*tempRef).iSpritePrecacheID);
|
||||
// Set up an event to do this instead so that being called over and over by the client
|
||||
// with packet delays (realistic network delays in multiplayer) don't cause the flash
|
||||
// to appear frozen until a server update.
|
||||
player pl = (player)self;
|
||||
pl.iMuzzleFlashType = arg_muzzleFlashType;
|
||||
pl.iMuzzleFlashAkimboChoice = arg_akimboChoice;
|
||||
View_AddEvent(viewEv_weapon_ShowMuzzleFlash, 0.0f);
|
||||
}
|
||||
#else
|
||||
|
@ -1848,18 +1869,25 @@ weapon_ShowMuzzleFlash(int arg_muzzleFlashType){
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Not to be confused with the clientside-only event "viewEv_weapon_EjectShell".
|
||||
// This is called by weapons to add the event, handles setting the shell-type global
|
||||
// for it to see. If shell-ejects are done serverside, that would not be an amazing
|
||||
// idea. Per-player would be better.
|
||||
|
||||
void
|
||||
weapon_EjectShell(int arg_shellEjectType)
|
||||
{
|
||||
weapon_EjectShellAkimbo(arg_shellEjectType, BITS_AKIMBOCHOICE_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
weapon_EjectShellAkimbo(int arg_shellEjectType, int arg_akimboChoice)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
player pl = (player)self;
|
||||
if(arg_shellEjectType != SHELLEJECT_ID::NONE){
|
||||
player pl = (player)self;
|
||||
pl.iShellEjectType = arg_shellEjectType;
|
||||
pl.iShellEjectAkimboChoice = arg_akimboChoice;
|
||||
View_AddEvent(viewEv_weapon_EjectShell, 0.0f);
|
||||
}
|
||||
#else
|
||||
|
@ -1867,14 +1895,30 @@ weapon_EjectShell(int arg_shellEjectType)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
weapon_ClientEffects(int arg_muzzleFlashType, int arg_shellEjectType)
|
||||
{
|
||||
weapon_ClientEffectsAkimbo(arg_muzzleFlashType, arg_shellEjectType, BITS_AKIMBOCHOICE_NONE);
|
||||
}
|
||||
|
||||
|
||||
// Both weapon_ShowMuzzleFlash and weapon_EjectShell in one call for scheduling
|
||||
// one event that calls both, otherwise, only either can happen (one event allowed;
|
||||
// any more and they just overwrite each other on being set)
|
||||
void weapon_ClientEffects(int arg_muzzleFlashType, int arg_shellEjectType){
|
||||
void
|
||||
weapon_ClientEffectsAkimbo(int arg_muzzleFlashType, int arg_shellEjectType, int arg_akimboChoice)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
player pl = (player)self;
|
||||
pl.iMuzzleFlashType = arg_muzzleFlashType;
|
||||
pl.iShellEjectType = arg_shellEjectType;
|
||||
if(arg_shellEjectType != SHELLEJECT_ID::NONE){
|
||||
pl.iShellEjectType = arg_shellEjectType;
|
||||
pl.iShellEjectAkimboChoice = arg_akimboChoice;
|
||||
}
|
||||
if(arg_muzzleFlashType != MUZZLEFLASH_ID::NONE){
|
||||
pl.iMuzzleFlashType = arg_muzzleFlashType;
|
||||
pl.iMuzzleFlashAkimboChoice = arg_akimboChoice;
|
||||
}
|
||||
View_AddEvent(viewEv_weapon_ClientEffects, 0.0f);
|
||||
#else
|
||||
// ?
|
||||
|
@ -2015,7 +2059,8 @@ weapondata_basic_t weapon_none_akimbo =
|
|||
//Or would it make sense to extern the structs here and keep this method in the same file?
|
||||
// (compile weapon-specific files first, then weapon.c)
|
||||
void
|
||||
setupWeaponData(void){
|
||||
setupWeaponData(void)
|
||||
{
|
||||
|
||||
// for reference, old way. REDO THAT MACRO to involve g_weapons, described more below
|
||||
//#define ASSIGN_WEAPONDATA(arg_constName) ary_weaponData[WEAPON_ID::##arg_constName] = (weapondata_basic_t*) &weapon_##arg_constName;
|
||||
|
@ -2156,7 +2201,8 @@ setupWeaponData(void){
|
|||
|
||||
|
||||
weapondata_basic_t*
|
||||
getWeaponData(int arg_weaponID, BOOL arg_akimbo){
|
||||
getWeaponData(int arg_weaponID, BOOL arg_akimbo)
|
||||
{
|
||||
weapondata_basic_t* basicP;
|
||||
|
||||
// no cap check for now
|
||||
|
@ -2235,8 +2281,6 @@ getAmmoTypeOfWeapon(int arg_weaponID)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
// This is based off what the HL glock does, adjust with custom shell-choices per
|
||||
// different weapons that use them.
|
||||
// Is HL's "w_shotgun_ejectshell" even any different from this besides shell-model
|
||||
|
@ -2262,28 +2306,34 @@ viewEv_playShotgunInsertShellSound(void)
|
|||
void
|
||||
viewEv_weapon_EjectShell(void)
|
||||
{
|
||||
// Actually, queue a shell eject during the next LatePreDraw call
|
||||
// (TS_View_DrawCustom to be more specific). This makes the generated shell
|
||||
// position more accurate. It will use the player's tempvars to set up
|
||||
// the shell for the akimbo choice like here would have.
|
||||
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
// TODO - how about a first-person check? Doesn't make sense if in thirdperson.
|
||||
// Although that might've been needed earlier unless this event-thing works fine for being
|
||||
// a playermodel too. Players other than the local one being rendered and needing to drop
|
||||
// shells, that sounds like a whole other story
|
||||
pl.bShellEjectScheduled = TRUE;
|
||||
/*
|
||||
if(pl.iShellEjectType != SHELLEJECT_ID::NONE){
|
||||
CTSShellEject::generateForViewmodel(pl.iShellEjectType);
|
||||
CTSShellEject::generateForViewModelAkimbo(pl.iShellEjectType, pl.iShellEjectAkimboChoice);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
viewEv_weapon_ShowMuzzleFlash(void){
|
||||
viewEv_weapon_ShowMuzzleFlash(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
if(pl.iMuzzleFlashType != MUZZLEFLASH_ID::NONE){
|
||||
muzzleflashdata_t* tempRef = ary_muzzleFlashData[pl.iMuzzleFlashType];
|
||||
View_ShowMuzzleflash((*tempRef).iSpritePrecacheID);
|
||||
TS_View_ShowMuzzleflash(tempRef->iSpritePrecacheID, pl.iMuzzleFlashAkimboChoice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
viewEv_weapon_ClientEffects(void){
|
||||
viewEv_weapon_ClientEffects(void)
|
||||
{
|
||||
viewEv_weapon_EjectShell();
|
||||
viewEv_weapon_ShowMuzzleFlash();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ void weapon_m61grenade_onThink(player pl, weapondynamic_t arg_thisWeapon){
|
|||
pl.grenadeSpawnTime = -1;
|
||||
|
||||
#ifdef SERVER
|
||||
weapon_m61grenade_spawnProjectile(pl, arg_thisWeapon, pl.grenadeToss, pl.grenadeHeldDuration);
|
||||
weapon_m61grenade_spawnProjectile(pl, arg_thisWeapon, pl.bGrenadeToss, pl.grenadeHeldDuration);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ void weapon_m61grenade_onThink(player pl, weapondynamic_t arg_thisWeapon){
|
|||
// should this be joined by else or no?
|
||||
if(pl.grenadeFireIndex == 1){
|
||||
// Release detected, do the throw anim + spawn the grenade soon
|
||||
if(!pl.grenadeToss){
|
||||
if(!pl.bGrenadeToss){
|
||||
TS_Weapons_ViewAnimation(weaponseq_m61grenade::throw, 11.0f/30.0f);
|
||||
}else{
|
||||
TS_Weapons_ViewAnimation(weaponseq_m61grenade::throw_slide, 11.0f/30.0f);
|
||||
|
@ -196,9 +196,9 @@ void weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int
|
|||
// Once already started, this can affect being a normal throw or slide-throw.
|
||||
if(pl.grenadeFireIndex == 0){
|
||||
if(attackTypeUsed & BITS_AKIMBOCHOICE_LEFT){
|
||||
pl.grenadeToss = FALSE; //throw, this was primary.
|
||||
pl.bGrenadeToss = FALSE; //throw, this was primary.
|
||||
}else if(attackTypeUsed & BITS_AKIMBOCHOICE_RIGHT){
|
||||
pl.grenadeToss = TRUE; //throw, this was sec.
|
||||
pl.bGrenadeToss = TRUE; //throw, this was sec.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,9 +161,6 @@ void weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, i
|
|||
// NOTE! weapon_akimbo_semiAttackChoice already handles telling to skip firing if
|
||||
// pl.recentAttackHadAmmo == FALSE or finalAkimboChoice is 0 or -1, no need
|
||||
// to keep track of w_attack_next per variant.
|
||||
// Also,
|
||||
//TODO - CRITICAL!
|
||||
// Muzzle flashes and shell ejections for akimbo pending!
|
||||
|
||||
// because I am not copy/pasting this monstrosity 5 times.
|
||||
finalAkimboChoice = weapon_akimbo_semiAttackChoice(pl, ary_weaponData[WEAPON_ID::SOCOMMK23_AKIMBO], arg_thisWeapon, attackTypeUsed);
|
||||
|
@ -315,14 +312,12 @@ void weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, i
|
|||
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: akimbo support
|
||||
if(!(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SILENCER) ){
|
||||
weapon_ClientEffects(MUZZLEFLASH_ID::SMALL, SHELLEJECT_ID::GENERIC, finalAkimboChoice);
|
||||
weapon_ClientEffectsAkimbo(MUZZLEFLASH_ID::SMALL, SHELLEJECT_ID::GENERIC, finalAkimboChoice);
|
||||
} else {
|
||||
weapon_EjectShell(SHELLEJECT_ID::GENERIC, finalAkimboChoice);
|
||||
weapon_EjectShellAkimbo(SHELLEJECT_ID::GENERIC, finalAkimboChoice);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}// weapon_socommk23_akimbo_attack
|
||||
|
||||
|
|
Loading…
Reference in a new issue