muzzleflash struct, zoom var cleanup, entity renaming, network latency experimental

This commit is contained in:
Christopher Dawalt 2021-08-11 05:18:29 -04:00
parent bfafbec9ad
commit 34ffbd54dc
69 changed files with 1971 additions and 1631 deletions

View File

@ -45,8 +45,9 @@ var float FONT_ARIAL_STD; //stands for "standard" ya hooligans.
var float FONT_ARIAL_NUMSLASH;
var float FONT_ARIAL_SCOPEMAG;
// Be sure to keep this up to date with the font FONT_ARIAL_STD as it's loaded in _base/client/entry.c,
// notice this is always one less than the actual expected corresponding font.
// Be sure to keep this up to date with the font FONT_ARIAL_STD as it's loaded in
// ui.qc, notice this is always one less than the actual expected corresponding font.
// TODO - a some things may be unused at this point, check.
const vector vButtonFontSize = [13, 13, 0];
const vector vFontSizeNumSlash = [15, 15, 0];
const vector vFontArialScopeMag = [16, 16, 0];

View File

@ -1,13 +1,16 @@
// for ejected shells to use
class CShellEject{
class CTSShellEject{
// what to use for info. Saved to a var since this must be known
// between being spawned and when the event is picked, not going to
// try and guess how that works knowing FTE
int iShellEjectType;
void(void) CShellEject;
void(void) CTSShellEject;
static void(void) precache;
static CShellEject(int arg_iShellEjectType) generate;
static CTSShellEject(int arg_iShellEjectType) generateForViewmodel;
static CTSShellEject(int arg_iShellEjectType, vector arg_vOrigin, vector arg_vDir) generate;
virtual void(void) touch;
};

View File

@ -1,10 +1,11 @@
void
CShellEject::CShellEject(void){
CTSShellEject::CTSShellEject(void){
}
void
CShellEject::precache(void){
CTSShellEject::precache(void)
{
Sound_Precache("modelevent_shell.land");
Sound_Precache("modelevent_shotgunshell.land");
// no need, handled in soundscript preaches
@ -16,6 +17,16 @@ CShellEject::precache(void){
precache_sound("weapons/sshell3.wav");
*/
// whoops, forgot looping through the struct and precaching that way would've worked,
// but keeping individual precaches if just for some comments.
// Also - could do it the getmodleindex way and record ID's, but don't see a benefit
// to that.
/*
for(i = 0; i < SHELLEJECT_ID::LAST_ID; i++){
ary_shellEjectData[i].iModelPrecacheID = (int)getmodelindex(ary_shellEjectData[i].sModelPath);
}
*/
// nearly identical..?
precache_model("models/56_shell.mdl");
precache_model("models/556_shell.mdl");
@ -34,9 +45,10 @@ CShellEject::precache(void){
// The practical constructor, manually call this after spawning.
// NOTE: assumes pSeat->m_eViewModel is valid for involving in determining
// origin, angles, velocity
CShellEject
CShellEject::generate(int arg_iShellEjectType){
CShellEject eShell = spawn(CShellEject);
CTSShellEject
CTSShellEject::generateForViewmodel(int arg_iShellEjectType)
{
CTSShellEject eShell = spawn(CTSShellEject);
vector vOrigin; // tempvar
@ -68,7 +80,8 @@ CShellEject::generate(int arg_iShellEjectType){
// viewmodel laser-start or flashlight sprite glow effect in the right place.
// FreeHL way (forget all the rest if so)
vOrigin = pSeat->m_eViewModel.origin + (v_forward * 26) + (v_right * 8) + (v_up * -4);
//vOrigin = pSeat->m_eViewModel.origin + (v_forward * 26) + (v_right * 8) + (v_up * -4);
/*
// way #1
@ -94,10 +107,47 @@ CShellEject::generate(int arg_iShellEjectType){
// or only be vOffset
vOrigin = vOffset;
*/
// way #4:
vector gunpos;
vector gunpos_tempEnd;
vector dirGun;
vector angGun;
gunpos = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 0i);
gunpos_tempEnd = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 3i);
dirGun = normalize(gunpos_tempEnd - gunpos);
angGun = vectoangles(dirGun);
makevectors(angGun);
//TODO: No idea what consistent formula would put shell ejections across the right place
// of all weapons. Might just have to be a piece of weapondata for what relative forward, up,
// and right multiples to apply to relative vectors here. Or maybe only the multiple on v_forward
// is necessary, would have to check the attachment points of everything
// 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
vOrigin = gunpos;
vOrigin += v_forward * -3.5;
vOrigin += v_up * -0.02;
vOrigin += v_right * 0.00;
setorigin(eShell, vOrigin);
}
void CShellEject::touch(void){
// TODO. For playermodels as seen in thirdperson (local one) or looking at other players
// that called for shell ejecting.
CTSShellEject
CTSShellEject::generate(int arg_iShellEjectType, vector arg_vOrigin, vector arg_vDir){
}
void
CTSShellEject::touch(void)
{
if(other == world){
shellejectdata_t* mySED = ary_shellEjectData[iShellEjectType];
// self? this? Is there a difference in this context?

View File

@ -187,6 +187,9 @@ ClientGame_EventParse(float fHeader)
case EVENT_TS::PLAYER_DEATH:
EV_PlayerDeath();
break;
case EVENT_TS::EQUIP_CALLBACK:
EV_EquipCallback();
break;
case EVENT_TS::SOUNDPITCHED:
SoundPitched_Receive();
break;
@ -195,7 +198,7 @@ ClientGame_EventParse(float fHeader)
break;
/*
// can this even happen anymore?
// If a drop-weapon call can be signaled by the server, not shared with th
// If a drop-weapon call can be signaled by the server, not shared with the
// client and server reaching a drop call independently, then yes.
case EVENT_TS::DROP_WEAPON:
EV_TS_playerDropWeapon(pl);

View File

@ -15,12 +15,27 @@
*/
// Nope, HUD/UI-related precaches in client/precache.qc instead
// ...mostly, keeping this one here?
void
HUD_Init(void)
{
// leftover HL precache that's used in scoreboard.qc it seems,
// haven't looked into what TS does for that yet.
g_hud1_spr = spriteframe("sprites/640hud1.spr", 0, 0.0f);
precache_model("sprites/player/crouched.spr");
precache_model("sprites/player/divestepb.spr");
precache_model("sprites/player/divestepc.spr");
precache_model("sprites/player/divestept.spr");
precache_model("sprites/player/health.spr");
precache_model("sprites/player/kevlar.spr");
precache_model("sprites/player/kungfu.spr");
precache_model("sprites/player/movement.spr");
precache_model("sprites/player/prone.spr");
precache_model("sprites/player/run.spr");
precache_model("sprites/player/stand.spr");
precache_model("sprites/weapons/item_installed.spr");
precache_model("sprites/weapons/item_not_installed.spr");
}
@ -71,8 +86,8 @@ HUD_Draw(void)
//////////////////////////////////////////////////////////////
//View_HandleZoom();
//printfline("SCOPE LEVEL %.2f", pl.flZoomLevel);
if(pl.flZoomLevel < 0.5){ //is this < 40? yes.
//printfline("SCOPE LEVEL %.2f", pl.flZoomCurrent);
if(pl.flZoomCurrent < 0.5){ //is this < 40? yes.
HUD_DrawScope();
}else{
// We'll leave details like extra details for the lasersight and the

View File

@ -41,7 +41,7 @@ void HUD_DrawScope_Pic( vector vPos, vector vSize, string sSprite ) {
=================
HUD_DrawScope
Tries to draw a scope whenever viewzoom < 1.0f
Tries to draw a scope
=================
*/
void HUD_DrawScope( void ) {
@ -167,7 +167,7 @@ void HUD_DrawScope( void ) {
int magAmount = (int)(1.0f / (pl.flZoomLevel ));
int magAmount = (int)(1.0f / (pl.flZoomCurrent ));
//int xOffset = drawSpriteNumber(ary_LCD_numberSet, 24, 24, magAmount, 3, BITS_DIGITOPT_NONE, clrPaleBlue, 0.88f);
//[24 + xOffset + 1, 24 + 4]
Gfx_Text( [24, 27], sprintf("%ix", magAmount), vFontArialScopeMag, clrPaleBlue, 0.95f, DRAWFLAG_ADDITIVE, FONT_ARIAL_SCOPEMAG );

View File

@ -173,20 +173,4 @@ ClientGame_RendererRestart(string rstr)
// Hook into precache.qc
ClientGame_Precache();
Obituary_Precache();
// All forked effects!
FX_Blood_Init();
FX_BreakModel_Init();
FX_Explosion_Init();
FX_GibHuman_Init();
FX_Spark_Init();
FX_Impact_Init();
// NEW
FX_TS_Explosion_Grenade_Init();
FX_Impact_Melee_Init();
}

View File

@ -1,5 +1,3 @@
//var int MUZZLE_CUSTOM;
void ClientGame_Precache(void);

View File

@ -8,41 +8,32 @@ void ClientGame_Precache(void){
SharedGame_Precache();
// Example of loading a muzzle flash sprite
//MUZZLE_CUSTOM = (int)getmodelindex("sprites/muzzleCUSTOM.spr");
// things from ClientGame_RendererRestart from FreeHL mostly for referred-to effects
////////////////////////////////////////////////////////////////////////////////////
Obituary_Precache();
// All forked effects!
FX_Blood_Init();
FX_BreakModel_Init();
FX_Explosion_Init();
FX_GibHuman_Init();
FX_Spark_Init();
FX_Impact_Init();
////////////////////////////////////////////////////////////////////////////////////
// NEW
CTSShellEject::precache();
FX_TS_Explosion_Grenade_Init();
FX_Impact_Melee_Init();
MuzzleFlash_precache();
CShellEject::precache();
//TAGGG - From FreeHL.
// Does TS use something else?
////////////////////////////////////////////////////////////
precache_model("sprites/muzzleflash1.spr");
precache_model("sprites/muzzleflash2.spr");
precache_model("sprites/muzzleflash3.spr");
////////////////////////////////////////////////////////////
precache_sound("weapons/draw.wav");
precache_model("sprites/mapsprites/ts_gpc1.spr");
precache_model("sprites/mapsprites/ts_gpc2.spr");
precache_model("sprites/player/crouched.spr");
precache_model("sprites/player/divestepb.spr");
precache_model("sprites/player/divestepc.spr");
precache_model("sprites/player/divestept.spr");
precache_model("sprites/player/health.spr");
precache_model("sprites/player/kevlar.spr");
precache_model("sprites/player/kungfu.spr");
precache_model("sprites/player/movement.spr");
precache_model("sprites/player/prone.spr");
precache_model("sprites/player/run.spr");
precache_model("sprites/player/stand.spr");
precache_model("sprites/weapons/item_installed.spr");
precache_model("sprites/weapons/item_not_installed.spr");
precache_model("sprites/wires/bwire.spr");
precache_model("sprites/wires/bwirecutted.spr");

View File

@ -31,7 +31,9 @@ defs.h
../shared/weapons.h
../shared/player.h
../shared/powerup.h
entity/shelleject.h
../shared/sound_pitched.h
entity/ts_shelleject.h
clientinfo.h
seatlocal.h
@ -58,7 +60,7 @@ hud.h
../shared/player.qc
../shared/inventory_logic.qc
entity/shelleject.qc
entity/ts_shelleject.qc
// old location of UI draw stuff
@ -93,13 +95,10 @@ scoreboard.qc
../../../base/src/client/modelevent.qc
../shared/util.qc
../shared/precache.qc
util.qc
precache.qc
//../_base/client/voice.c
//../_base/client/sound.c
//../_base/client/music.c
//../_base/client/prints.c
//../_base/client/util.c
../../../src/client/include.src

View File

@ -118,11 +118,13 @@ UI_MOTD_Draw(void)
{
#ifdef MOTD_NEW_VGUI
if(!(UI_MOTD_win.m_iFlags & 1) && !g_UI_MOTD_everClosed){
if(!(UI_MOTD_win.m_iFlags & 1) /*&& !g_UI_MOTD_everClosed*/){
// this means the window was hidden by closing with the X button.
// The OK button sets that flag so that this can't be reached that way.
// The point is, closing the MoTD the first time by any means should lead
// to the buy menu
// ACTUALLY, leaving that up to btnOK to determine. Still want to solidly set
// the current screen to NONE regardless of closing the MoTD for the first time.
UI_MOTD_btnOK_Clicked();
}

View File

@ -97,6 +97,9 @@ TS_SetViewModelFromStats(void)
SAVE_STATE(pl.w_idle_next);
SAVE_STATE(pl.viewzoom);
SAVE_STATE(pl.weapontime);
//TAGGG - NEW VAR
SAVE_STATE(pl.w_attack_akimbo_next);
SAVE_STATE(pl.flZoomTarget);
skel_delete( mflash.skeletonindex );
mflash.skeletonindex = skel_create( vm.modelindex );
@ -206,6 +209,7 @@ View_UpdateWeapon(entity vm, entity mflash)
SAVE_STATE(pl.weapontime);
//TAGGG - NEW VAR.
SAVE_STATE(pl.w_attack_akimbo_next);
SAVE_STATE(pl.flZoomTarget);
//TAGGG - also new line. It is a good idea to reset the event
// on changing models, right?
@ -258,17 +262,34 @@ void View_HandleZoom(void){
return;
}
//TAGGG - any references to STAT_VIEWZOOM are now garbage.
// Rely on pl.flTargetZoom instead, it's sent to the client every frame
// and should be handled serverside anyway.
// flCurrentZoom is actually the "target" zoom we want to reach.
// flOldZoom is the zoom we started at, at the time of the change.
// flZoomLerp is how far along we are from oldZoom to currentZoom.
// flZoomLevel is the actual zoom we are at this very moment.
// test
/*
pl.flZoomCurrent = pl.flZoomTarget;
pl.viewzoom = pl.flZoomTarget;
printfline("flZoomTarget: %.2f", pl.flZoomTarget);
return;
*/
if (pl.flCurrentZoom != pl.flTargetZoom ) {
pl.flOldZoom = pl.flCurrentZoom;
pl.flCurrentZoom = pl.flTargetZoom ;
//printfline("WHATS GOING ON %.2f %.2f %.2f %.2f %.2f", pl.flZoomEnd, pl.flZoomTarget, pl.flZoomStart, pl.flZoomLerp, pl.flZoomCurrent);
//TAGGG - any references to STAT_VIEWZOOM are now garbage.
// Rely on pl.flZoomTarget instead, it's sent to the client every frame
// and should be handled serverside anyway.
// flZoomEnd is actually the "target" zoom we want to reach.
// flZoomStart is the zoom we started at, at the time of the change.
// flZoomLerp is how far along we are from oldZoom to currentZoom.
// flZoomCurrent is the actual zoom we are at this very moment.
if (pl.flZoomEnd != pl.flZoomTarget ) {
// is setting flZoomStart to flZoomEnd or flZoomCurrent a better idea?
// at flZoomEnd means, on changing before the current lerp has finished, it jumps to beginning
// at the end point of the lerp in progress. But starting at flZoomCurrent might be smoother?
// if it isn't glitchy that could be nice. Trying that out.
pl.flZoomStart = pl.flZoomCurrent;
//pl.flZoomStart = pl.flZoomEnd;
pl.flZoomEnd = pl.flZoomTarget;
pl.flZoomLerp = 0.0f;
}
@ -277,24 +298,24 @@ void View_HandleZoom(void){
// 0.8 can be safe.
// The Wastes default was 4.
pl.flZoomLerp += clframetime * 8;
pl.flZoomLerp += clframetime * 5.7;
if(pl.flZoomLerp >= 1.0){
//enforce the cap.
pl.flZoomLerp = 1.0;
}
//pl.flZoomLevel = getstatf(STAT_VIEWZOOM);
pl.flZoomLevel = Math_Lerp(pl.flOldZoom, pl.flCurrentZoom, pl.flZoomLerp);
//pl.flZoomCurrent = getstatf(STAT_VIEWZOOM);
pl.flZoomCurrent = Math_Lerp(pl.flZoomStart, pl.flZoomEnd, pl.flZoomLerp);
}
// Set this, since Nuclide will read it in and apply instantly.
// So same effect without having to edit Nuclide, this pipes it over for it
// to do the setproperty thing below to apply
pl.viewzoom = pl.flZoomLevel;
pl.viewzoom = pl.flZoomCurrent;
////setproperty(VF_AFOV, DEFAULT_FOV * pl.flZoomLevel);
////setsensitivityscaler(pl.flZoomLevel);
////setproperty(VF_AFOV, DEFAULT_FOV * pl.flZoomCurrent);
////setsensitivityscaler(pl.flZoomCurrent);
// here's the way old FreeCS did it
//setproperty(VF_AFOV, cvar("fov") * pl.viewzoom);
@ -329,5 +350,3 @@ View_ShowMuzzleflash(int index)
}

View File

@ -1,2 +0,0 @@
class TSAmmoPack;

View File

@ -1,9 +0,0 @@
class TSGrenadeProjectile{
void(void) TSGrenadeProjectile;
static void(void) precache;
static TSGrenadeProjectile(player arg_player, vector arg_vOrigin, vector arg_vThrowDir, vector arg_vPlayerForward, int arg_weaponTypeID) generate;
virtual void(void) touch;
};
void TSGrenadeProjectile_Explode(void);

View File

@ -0,0 +1,2 @@
class CTSAmmoPack;

View File

@ -1,237 +1,237 @@
class TSAmmoPack{
// After being recently accessed by a player but not deleted,
// I enforce a cooldown time before any other player (including the same one)
// can try to pick me up again. This stops spamming inventory scans every
// single frame if a player stands over a weapon they can't pick up.
float accessibleCooldownTime;
// To avoid server clutter over time, a pickup will delete itself
float expireTime;
//myInfo
int ary_ammoTotal[AMMO_ID::LAST_ID];
void(void) TSAmmoPack;
virtual void() Think;
virtual void() Touch;
virtual void() PlayerUse;
static TSAmmoPack(player arg_player) generate;
virtual void(player arg_player) copyFrom;
virtual BOOLEAN(player arg_player) copyTo;
//static Container_STR_ptr *Event::commandList;
/*
// in-class constructor.
void(void) TSAmmoPack = {
// can do stuff here too.
};
*/
/*
// in-class method.
virtual int (int arg1, int arg2) doMath = {
return arg1 + arg2;
};
*/
};
static var int TSAmmoPack::testStaticVar = 0;
void TSAmmoPack::TSAmmoPack(void){
accessibleCooldownTime = -1;
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
ary_ammoTotal[i] = 0; //safe default
}
}
// Static method called from elsewhere to create and initialize a
// weapon drop entity, given a player and what weapon to copy information from.
TSAmmoPack TSAmmoPack::generate(player arg_player){
TSAmmoPack eDrop = spawn(TSAmmoPack);
TSAmmoPack::testStaticVar++;
//printfline("AmmoPacks ever dropped: %i", testStaticVar);
//eDrop.setup(arg_player, arg_weaponID);
//TSAmmoPack eDrop = spawn(TSAmmoPack);
setorigin( eDrop, arg_player.origin + arg_player.view_ofs );
setmodel( eDrop, "models/ammopack.mdl");
eDrop.classname = "remove_me";
eDrop.owner = arg_player;
eDrop.movetype = MOVETYPE_TOSS;
eDrop.solid = SOLID_TRIGGER; //or CORPSE
//eDrop.weapon = dynaRefPRE.weaponID;
eDrop.think = TSAmmoPack::Think;
eDrop.touch = TSAmmoPack::Touch;
eDrop.nextthink = time + 0.5f;
eDrop.copyFrom(arg_player);
//uhh.. ok, sure
eDrop.health = 1;
setsize( eDrop, '-16 -16 0', '16 16 16' );
//is this v_forward sometimes bad.. ?
makevectors( arg_player.v_angle );
eDrop.velocity = arg_player.velocity + v_forward * 256;
//And lastly, assume I need to expire at some point.
eDrop.expireTime = time + autocvar_weaponstay; //autocvar_weaponstay
eDrop.PlayerUse = TSAmmoPack::PlayerUse;
return eDrop;
}//END OF generate
// Pack all the player's ammo pools into me.
void TSAmmoPack::copyFrom(player arg_player){
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
this.ary_ammoTotal[i] = arg_player.ary_ammoTotal[i]; //take it all.
arg_player.ary_ammoTotal[i] = 0;
}
}//END OF copyFrom
// Give this player my ammo pools, whatever will fit.
// Returns whether any ammo transaction happened (pretty likely)
BOOLEAN TSAmmoPack::copyTo(player arg_player){
ammodata_t ammoRef;
BOOLEAN anyAmmoTaken = FALSE;
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
ammoRef = *ary_ammoData[i];
//How much can I give to the player?
//this.ary_ammoTotal[i] = arg_player.ary_ammoTotal[i]; //take it all.
//arg_player.ary_ammoTotal[i] = 0;
int amountToTake;
int existingCount = arg_player.ary_ammoTotal[i];
int pickupCount = this.ary_ammoTotal[i];
if(existingCount + pickupCount <= ammoRef.iMax){
//absorb it all.
amountToTake = pickupCount;
}else{
//too much in the pickup? this is ok, take as much as we can.
amountToTake = ammoRef.iMax - existingCount;
}
if(amountToTake > 0){
anyAmmoTaken = TRUE;
}else{
}
arg_player.ary_ammoTotal[i] += amountToTake;
//arg_pickupRef.myInfo.iCount -= amountToTake;
this.ary_ammoTotal[i]-= amountToTake;
}//END OF for loop through ammo types
if(anyAmmoTaken){
sound(arg_player, CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM, 100, SOUNDFLAG_PLAYER_COMMON );
}else{
//sound( arg_player, CHAN_ITEM, "common/wpn_select.wav", 1, ATTN_NORM, 100, SOUNDFLAG_PLAYER_COMMON );
}
return anyAmmoTaken;
}//END OF copyTo
void TSAmmoPack::Touch( void ) {
if ( other.classname != "player" ) {
// assume it's the world.. play this sound?
//printfline("the thing I touched is %s", other.classname);
// TODO - any others we need to keep track of for making the drop?
if(other.classname == "worldspawn" || other.classname == "func_breakable"){
sound( this, CHAN_ITEM, "items/weapondrop1.wav", 1, ATTN_NORM, 100, SOUNDFLAG_PLAYER_COMMON );
}
return;
}
//entity eOld = self;
//TSAmmoPack selfRef = (TSAmmoPack)self;
//self = other;
player otherPlayerRef = (player)other; //safe assumption now.
BOOLEAN shouldDelete;
if(time >= this.accessibleCooldownTime){
shouldDelete = copyTo(otherPlayerRef);
this.accessibleCooldownTime = time + 0.8;
}else{
shouldDelete = FALSE;
}
//self = eOld;
if(shouldDelete){
remove(this);
}
}//END OF touch method
void TSAmmoPack::PlayerUse( void ) {
}
void TSAmmoPack::Think( void ) {
//TSAmmoPack selfRef = (TSAmmoPack)self;
// oh.. this makes the weapon collidable with the original dropper
// again.
if(time >= this.expireTime){
//expire.
remove(this);
}else{
this.owner = world;
//set the next think to aim around this time then.
this.nextthink = this.expireTime + 0.1;
}
}
class CTSAmmoPack{
// After being recently accessed by a player but not deleted,
// I enforce a cooldown time before any other player (including the same one)
// can try to pick me up again. This stops spamming inventory scans every
// single frame if a player stands over a weapon they can't pick up.
float accessibleCooldownTime;
// To avoid server clutter over time, a pickup will delete itself
float expireTime;
//myInfo
int ary_ammoTotal[AMMO_ID::LAST_ID];
void(void) CTSAmmoPack;
virtual void() Think;
virtual void() Touch;
virtual void() PlayerUse;
static CTSAmmoPack(player arg_player) generate;
virtual void(player arg_player) copyFrom;
virtual BOOLEAN(player arg_player) copyTo;
//static Container_STR_ptr *Event::commandList;
/*
// in-class constructor.
void(void) CTSAmmoPack = {
// can do stuff here too.
};
*/
/*
// in-class method.
virtual int (int arg1, int arg2) doMath = {
return arg1 + arg2;
};
*/
};
static var int CTSAmmoPack::testStaticVar = 0;
void CTSAmmoPack::CTSAmmoPack(void){
accessibleCooldownTime = -1;
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
ary_ammoTotal[i] = 0; //safe default
}
}
// Static method called from elsewhere to create and initialize a
// weapon drop entity, given a player and what weapon to copy information from.
CTSAmmoPack CTSAmmoPack::generate(player arg_player){
CTSAmmoPack eDrop = spawn(CTSAmmoPack);
CTSAmmoPack::testStaticVar++;
//printfline("AmmoPacks ever dropped: %i", testStaticVar);
//eDrop.setup(arg_player, arg_weaponID);
//CTSAmmoPack eDrop = spawn(CTSAmmoPack);
setorigin( eDrop, arg_player.origin + arg_player.view_ofs );
setmodel( eDrop, "models/ammopack.mdl");
eDrop.classname = "remove_me";
eDrop.owner = arg_player;
eDrop.movetype = MOVETYPE_TOSS;
eDrop.solid = SOLID_TRIGGER; //or CORPSE
//eDrop.weapon = dynaRefPRE.weaponID;
eDrop.think = CTSAmmoPack::Think;
eDrop.touch = CTSAmmoPack::Touch;
eDrop.nextthink = time + 0.5f;
eDrop.copyFrom(arg_player);
//uhh.. ok, sure
eDrop.health = 1;
setsize( eDrop, '-16 -16 0', '16 16 16' );
//is this v_forward sometimes bad.. ?
makevectors( arg_player.v_angle );
eDrop.velocity = arg_player.velocity + v_forward * 256;
//And lastly, assume I need to expire at some point.
eDrop.expireTime = time + autocvar_weaponstay; //autocvar_weaponstay
eDrop.PlayerUse = CTSAmmoPack::PlayerUse;
return eDrop;
}//END OF generate
// Pack all the player's ammo pools into me.
void CTSAmmoPack::copyFrom(player arg_player){
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
this.ary_ammoTotal[i] = arg_player.ary_ammoTotal[i]; //take it all.
arg_player.ary_ammoTotal[i] = 0;
}
}//END OF copyFrom
// Give this player my ammo pools, whatever will fit.
// Returns whether any ammo transaction happened (pretty likely)
BOOLEAN CTSAmmoPack::copyTo(player arg_player){
ammodata_t ammoRef;
BOOLEAN anyAmmoTaken = FALSE;
for(int i = 0; i < AMMO_ID::LAST_ID; i++){
ammoRef = *ary_ammoData[i];
//How much can I give to the player?
//this.ary_ammoTotal[i] = arg_player.ary_ammoTotal[i]; //take it all.
//arg_player.ary_ammoTotal[i] = 0;
int amountToTake;
int existingCount = arg_player.ary_ammoTotal[i];
int pickupCount = this.ary_ammoTotal[i];
if(existingCount + pickupCount <= ammoRef.iMax){
//absorb it all.
amountToTake = pickupCount;
}else{
//too much in the pickup? this is ok, take as much as we can.
amountToTake = ammoRef.iMax - existingCount;
}
if(amountToTake > 0){
anyAmmoTaken = TRUE;
}else{
}
arg_player.ary_ammoTotal[i] += amountToTake;
//arg_pickupRef.myInfo.iCount -= amountToTake;
this.ary_ammoTotal[i]-= amountToTake;
}//END OF for loop through ammo types
if(anyAmmoTaken){
sound(arg_player, CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM, 100, SOUNDFLAG_PLAYER_COMMON );
}else{
//sound( arg_player, CHAN_ITEM, "common/wpn_select.wav", 1, ATTN_NORM, 100, SOUNDFLAG_PLAYER_COMMON );
}
return anyAmmoTaken;
}//END OF copyTo
void CTSAmmoPack::Touch( void ) {
if ( other.classname != "player" ) {
// assume it's the world.. play this sound?
//printfline("the thing I touched is %s", other.classname);
// TODO - any others we need to keep track of for making the drop?
if(other.classname == "worldspawn" || other.classname == "func_breakable"){
sound( this, CHAN_ITEM, "items/weapondrop1.wav", 1, ATTN_NORM, 100, SOUNDFLAG_PLAYER_COMMON );
}
return;
}
//entity eOld = self;
//CTSAmmoPack selfRef = (CTSAmmoPack)self;
//self = other;
player otherPlayerRef = (player)other; //safe assumption now.
BOOLEAN shouldDelete;
if(time >= this.accessibleCooldownTime){
shouldDelete = copyTo(otherPlayerRef);
this.accessibleCooldownTime = time + 0.8;
}else{
shouldDelete = FALSE;
}
//self = eOld;
if(shouldDelete){
remove(this);
}
}//END OF touch method
void CTSAmmoPack::PlayerUse( void ) {
}
void CTSAmmoPack::Think( void ) {
//CTSAmmoPack selfRef = (CTSAmmoPack)self;
// oh.. this makes the weapon collidable with the original dropper
// again.
if(time >= this.expireTime){
//expire.
remove(this);
}else{
this.owner = world;
//set the next think to aim around this time then.
this.nextthink = this.expireTime + 0.1;
}
}

View File

@ -0,0 +1,9 @@
class TS_GrenadeProjectile{
void(void) TS_GrenadeProjectile;
static void(void) precache;
static TS_GrenadeProjectile(player arg_player, vector arg_vOrigin, vector arg_vThrowDir, vector arg_vPlayerForward, int arg_weaponTypeID) generate;
virtual void(void) touch;
};
void TS_GrenadeProjectile_Explode(void);

View File

@ -1,21 +1,21 @@
void
TSGrenadeProjectile::TSGrenadeProjectile(void){
TS_GrenadeProjectile::TS_GrenadeProjectile(void){
}
void
TSGrenadeProjectile::precache(void)
TS_GrenadeProjectile::precache(void)
{
Sound_Precache("weapon_m61grenade.bounce");
// Explosion sound is already precached in fx_ts_explosion_grenade.qc
// And the projectile model uses the world model, so that is also already handled
}
TSGrenadeProjectile
TSGrenadeProjectile::generate(
TS_GrenadeProjectile
TS_GrenadeProjectile::generate(
player arg_player, vector arg_vOrigin, vector arg_vThrowDir,
vector arg_vPlayerForward, int arg_weaponTypeID
){
TSGrenadeProjectile eNade = spawn(TSGrenadeProjectile);
TS_GrenadeProjectile eNade = spawn(TS_GrenadeProjectile);
weapondata_throwable_t* basicP = ((weapondata_throwable_t*)ary_weaponData[arg_weaponTypeID]);
@ -37,14 +37,14 @@ TSGrenadeProjectile::generate(
eNade.movetype = MOVETYPE_BOUNCE;
eNade.gravity = 0.5f;
eNade.think = TSGrenadeProjectile_Explode;
eNade.think = TS_GrenadeProjectile_Explode;
eNade.nextthink = time + 3.0f;
return eNade;
}
void
TSGrenadeProjectile::touch(void){
TS_GrenadeProjectile::touch(void){
if ( other.solid == SOLID_TRIGGER ) {
return;
}
@ -62,7 +62,7 @@ TSGrenadeProjectile::touch(void){
void
TSGrenadeProjectile_Explode(void){
TS_GrenadeProjectile_Explode(void){
//float randomChoice;
// Also - don't worry about the shakes, sound script file for the
@ -92,22 +92,6 @@ TSGrenadeProjectile_Explode(void){
//Damage_Apply( self, world, fFallDamage, 0, DMG_FALL);
/*
randomChoice = random();
if(randomChoice < 0.2){
SoundPitched_Send(self, SNDP_EXPLODE);
}else if(randomChoice < 0.4){
SoundPitched_Send(self, SNDP_EXPLODE1);
}else if(randomChoice < 0.6){
SoundPitched_Send(self, SNDP_EXPLODE2);
}else if(randomChoice < 0.8){
SoundPitched_Send(self, SNDP_EXPLODE3);
}else{
SoundPitched_Send(self, SNDP_EXPLODE4);
}
*/
// delay this so damage indicators can figure out where I came from!
// ...weird, I know.
//remove( self );

View File

@ -21,7 +21,7 @@ enum pwuptype_choice{
#ifdef SERVER
class ts_powerup:CBaseEntity{
class CTSPowerUp:CBaseEntity{
//key values?
pwuptype_choice m_ePwuptype;
@ -41,7 +41,7 @@ class ts_powerup:CBaseEntity{
vector mem_origin;
void(void) ts_powerup;
void(void) CTSPowerUp;
static void(void) precache;
virtual void(void) CustomInit;
//virtual void(void) restartAnim;
@ -56,7 +56,7 @@ class ts_powerup:CBaseEntity{
void
ts_powerup::ts_powerup(void)
CTSPowerUp::CTSPowerUp(void)
{
// And why don't we just receive these as name/value pairs like clientside does?
@ -64,7 +64,7 @@ ts_powerup::ts_powerup(void)
// And is it a problem we never call CBaseEntity's constructor?
// If we did it would read every single field that way, in addition to us
// reading every single field here, just to get info that the CBaseEntity expects
// (origin) and what ts_powerup expects. Not efficient!
// (origin) and what CTSPowerUp expects. Not efficient!
int nfields = tokenize( __fullspawndata );
@ -98,15 +98,9 @@ ts_powerup::ts_powerup(void)
}// constructor
void
ts_powerup::precache(void)
{
precache_model(POWERUP_MODEL_PATH);
}
void
ts_powerup::CustomInit(void)
CTSPowerUp::CustomInit(void)
{
@ -131,8 +125,8 @@ ts_powerup::CustomInit(void)
//customphysics?
//eDrop.think = ts_powerup::Think;
//eDrop.touch = ts_powerup::Touch;
//eDrop.think = CTSPowerUp::Think;
//eDrop.touch = CTSPowerUp::Touch;
//this.nextthink = time + 0.5f;
//uhh.. ok, sure
@ -192,8 +186,8 @@ ts_powerup::CustomInit(void)
this.SendEntity = send;
this.SendFlags = 1;
//this.touch = ts_powerup::Touch;
//this.think = ts_powerup::Think;
//this.touch = CTSPowerUp::Touch;
//this.think = CTSPowerUp::Think;
this.nextthink = time + 0;
// ??? SERVERTEST
@ -206,7 +200,7 @@ ts_powerup::CustomInit(void)
float ts_powerup::send(entity pvsent, float cflags)
float CTSPowerUp::send(entity pvsent, float cflags)
{
WriteByte(MSG_ENTITY, ENT_POWERUP);
WriteCoord(MSG_ENTITY, this.origin[0]);
@ -232,7 +226,7 @@ float ts_powerup::send(entity pvsent, float cflags)
void
ts_powerup::Respawn(void)
CTSPowerUp::Respawn(void)
{
CustomInit();
@ -243,7 +237,7 @@ ts_powerup::Respawn(void)
void
ts_powerup::think(void)
CTSPowerUp::think(void)
{
//TAGGG - CRITICAL. DISCUSS.
@ -274,7 +268,7 @@ ts_powerup::think(void)
void
ts_powerup::touch(void)
CTSPowerUp::touch(void)
{
@ -312,7 +306,7 @@ ts_powerup::touch(void)
void
ts_powerup::determineDataID(void)
CTSPowerUp::determineDataID(void)
{
int bitsToChoose[9];
@ -429,7 +423,7 @@ ts_powerup::determineDataID(void)
void
ts_powerup::declareDisposable(void)
CTSPowerUp::declareDisposable(void)
{
// Since we clearly weren't spawned by the map for this method to be called,
@ -465,7 +459,7 @@ ts_powerup::declareDisposable(void)
#ifdef CLIENT
class ts_powerup:CBaseEntity{
class CTSPowerUp:CBaseEntity{
//key values?
pwuptype_choice m_ePwuptype;
@ -476,7 +470,8 @@ class ts_powerup:CBaseEntity{
POWERUP_ID dataID;
BOOL alreadyPickedUp;
void(void) ts_powerup;
void(void) CTSPowerUp;
static void(void) precache;
virtual void(void) Initialized;
virtual void(void) updateAnim;
virtual void(string strField, string strKey) SpawnKey;
@ -493,14 +488,14 @@ class ts_powerup:CBaseEntity{
void
ts_powerup::ts_powerup(void)
CTSPowerUp::CTSPowerUp(void)
{
}
// Use me instead for startup stuff expected after reading spawnflags.
void
ts_powerup::Initialized(void)
CTSPowerUp::Initialized(void)
{
//base method is empty, this is pointless
//CBaseEntity::Initialized();
@ -529,7 +524,7 @@ ts_powerup::Initialized(void)
//this.think = updateAnim;
//this.nextthink = time + (31-1)/50;
//ts_powerup selfRef = this;
//CTSPowerUp selfRef = this;
}// Initialized
@ -537,13 +532,13 @@ ts_powerup::Initialized(void)
void
ts_powerup::updateAnim(void)
CTSPowerUp::updateAnim(void)
{
//this.lerpfrac = 1;
//this.baseframe1time = 0;
//this.frame1time = 0;
//printfline("ts_powerup::updateAnim %0.2f", this.frame1time);
//printfline("CTSPowerUp::updateAnim %0.2f", this.frame1time);
//this.frame1time += clframetime;
//resets the anim frame.
@ -570,7 +565,7 @@ void
Powerup_Parse(void)
{
ts_powerup selfRef;
CTSPowerUp selfRef;
/* convert us to an object of type decal */
@ -579,11 +574,11 @@ Powerup_Parse(void)
if(self.classname != "ts_powerup"){
//is this really persistent?
//printfline("ts_powerup: Powerup_Parse. MY CLASSNAME IS INCORRECT: %s", self.classname);
spawnfunc_ts_powerup();
spawnfunc_CTSPowerUp();
self.classname = "ts_powerup";
}
selfRef = (ts_powerup)self;
selfRef = (CTSPowerUp)self;
BOOL mem_alreadyPickedUp = selfRef.alreadyPickedUp;
@ -631,7 +626,7 @@ Powerup_Parse(void)
if(isRespawnCall || (!selfRef.alreadyPickedUp && (mem_alreadyPickedUp != selfRef.alreadyPickedUp))){
// forcively respawned, or appearing since being hidden? Force animation time to 0 (start at beginning)
selfRef.frame1time = 0;
selfRef.think = ts_powerup::updateAnim;
selfRef.think = CTSPowerUp::updateAnim;
selfRef.nextthink = time + (31-1)/20 - 0.005;
}
@ -659,12 +654,12 @@ Powerup_Parse(void)
}
//selfRef.customphysics = ts_powerup::Physics;
//selfRef.think = ts_powerup::Think;
//selfRef.customphysics = CTSPowerUp::Physics;
//selfRef.think = CTSPowerUp::Think;
//selfRef.nextthink = time + 0;
// unnecessary.
//selfRef.predraw = ts_powerup::predraw;
//selfRef.predraw = CTSPowerUp::predraw;
// Why do we have to do this in Powerup_Parse and not just once in "Initialized?"
selfRef.drawmask = MASK_ENGINE;
@ -675,9 +670,9 @@ Powerup_Parse(void)
float
ts_powerup::predraw(void)
CTSPowerUp::predraw(void)
{
ts_powerup selfRef = (ts_powerup)self;
CTSPowerUp selfRef = (CTSPowerUp)self;
selfRef.frame1time += clframetime;
@ -689,13 +684,13 @@ ts_powerup::predraw(void)
/*
void ts_powerup::Physics(void){
void CTSPowerUp::Physics(void){
this.frame1time += clframetime;
}// Physics
void ts_powerup::Think(void){
void CTSPowerUp::Think(void){
this.frame1time += clframetime;
this.nextthink = time + 0;
@ -706,9 +701,9 @@ void ts_powerup::Think(void){
void
ts_powerup::SpawnKey(string strField, string strKey)
CTSPowerUp::SpawnKey(string strField, string strKey)
{
//printfline("SpawnKey:: ts_powerup: (%s: %s)", strField, strKey);
//printfline("SpawnKey:: CTSPowerUp: (%s: %s)", strField, strKey);
switch (strField) {
case "pwuptype":
@ -717,7 +712,8 @@ ts_powerup::SpawnKey(string strField, string strKey)
case "pwupduration":
m_iPwupduration = stoi(strKey);
break;
case "message":m_strMessage = strKey;
case "message":
m_strMessage = strKey;
break;
@ -754,3 +750,17 @@ ts_powerup::SpawnKey(string strField, string strKey)
#endif
// SHARED?
void
CTSPowerUp::precache(void)
{
precache_model(POWERUP_MODEL_PATH);
}
// ent name on maps is ts_powerup
void
ts_powerup(void)
{
spawnfunc_CTSPowerUp();
}

View File

@ -1,36 +1,36 @@
// NOTE - this was not a type in the original TS, just seemed convenient to make.
//class TSThrownProjectile;
class TSThrownProjectile : TSWorldGun{
void(void) TSThrownProjectile;
virtual void() Think;
virtual void() Touch;
virtual void() PlayerUse;
static TSThrownProjectile (player arg_player, int arg_weaponID) generate;
static TSThrownProjectile (player arg_player, weapondynamic_t dynaRefPRE) generate2;
virtual void (player arg_player, int arg_weaponID) copyFrom;
virtual void (player arg_player, weapondynamic_t tempRef) copyFrom2;
virtual void (player arg_player, int arg_weaponID) copyTo;
virtual void (BOOL becomeStuck, optional vector dir, optional entity stuckTo, BOOL touchedBreakableGlass)becomePickupable;
// Like FTE's supplied 'owner' field, but for keeping track of who threw this knife after
// the 'owner' field gets reset to still keep track of who should be blamed for damage inflicted.
entity m_owner;
float startAngularVelocityDelay;
//vector vPreviousVelocity;
float forceBecomePickupableTime;
vector queuedVelocity;
float queuedVelocityApplyTime;
float switchToNormalPickupBoundsTime;
};
// NOTE - this was not a type in the original TS, just seemed convenient to make.
//class CTSThrownProjectile;
class CTSThrownProjectile : CTSWorldGun{
void(void) CTSThrownProjectile;
virtual void() Think;
virtual void() Touch;
virtual void() PlayerUse;
static CTSThrownProjectile (player arg_player, int arg_weaponID) generate;
static CTSThrownProjectile (player arg_player, weapondynamic_t dynaRefPRE) generate2;
virtual void (player arg_player, int arg_weaponID) copyFrom;
virtual void (player arg_player, weapondynamic_t tempRef) copyFrom2;
virtual void (player arg_player, int arg_weaponID) copyTo;
virtual void (BOOL becomeStuck, optional vector dir, optional entity stuckTo, BOOL touchedBreakableGlass)becomePickupable;
// Like FTE's supplied 'owner' field, but for keeping track of who threw this knife after
// the 'owner' field gets reset to still keep track of who should be blamed for damage inflicted.
entity m_owner;
float startAngularVelocityDelay;
//vector vPreviousVelocity;
float forceBecomePickupableTime;
vector queuedVelocity;
float queuedVelocityApplyTime;
float switchToNormalPickupBoundsTime;
};

View File

@ -1,36 +1,36 @@
//class TSWorldGun;
// not inheriting from CBaseEntity... this wasn't made with that in mind,
// and it doesn't look like it needs anything from there.
// If there were a version of this to be respawnable, it may make sense to make it a child of
// CBaseEntiy and then remove the GF_CANRESPAWN flag gflags added to all CBaseEntities by default
// (I think)... since changed to the IDENTITY_CANRESPAWN flag of ".identity" for CBaseEntity's
class TSWorldGun{
// After being recently accessed by a player but not deleted,
// I enforce a cooldown time before any other player (including the same one)
// can try to pick me up again. This stops spamming inventory scans every
// single frame if a player stands over a weapon they can't pick up.
float accessibleCooldownTime;
// To avoid server clutter over time, a pickup will delete itself
float expireTime;
weapondynamic_t myInfo;
void(void) TSWorldGun;
virtual void() Think;
virtual void() Touch;
virtual void() PlayerUse;
static TSWorldGun (player arg_player, int arg_weaponID) generate;
static TSWorldGun (player arg_player, weapondynamic_t dynaRefPRE) generate2;
virtual void (player arg_player, int arg_weaponID) copyFrom;
virtual void (player arg_player, weapondynamic_t tempRef) copyFrom2;
virtual void (player arg_player, int arg_weaponID) copyTo;
};
//class CTSWorldGun;
// not inheriting from CBaseEntity... this wasn't made with that in mind,
// and it doesn't look like it needs anything from there.
// If there were a version of this to be respawnable, it may make sense to make it a child of
// CBaseEntiy and then remove the GF_CANRESPAWN flag gflags added to all CBaseEntities by default
// (I think)... since changed to the IDENTITY_CANRESPAWN flag of ".identity" for CBaseEntity's
class CTSWorldGun{
// After being recently accessed by a player but not deleted,
// I enforce a cooldown time before any other player (including the same one)
// can try to pick me up again. This stops spamming inventory scans every
// single frame if a player stands over a weapon they can't pick up.
float accessibleCooldownTime;
// To avoid server clutter over time, a pickup will delete itself
float expireTime;
weapondynamic_t myInfo;
void(void) CTSWorldGun;
virtual void() Think;
virtual void() Touch;
virtual void() PlayerUse;
static CTSWorldGun (player arg_player, int arg_weaponID) generate;
static CTSWorldGun (player arg_player, weapondynamic_t dynaRefPRE) generate2;
virtual void (player arg_player, int arg_weaponID) copyFrom;
virtual void (player arg_player, weapondynamic_t tempRef) copyFrom2;
virtual void (player arg_player, int arg_weaponID) copyTo;
};

View File

@ -1,259 +1,259 @@
void TSWorldGun::TSWorldGun(void){
accessibleCooldownTime = -1;
myInfo = spawn(weapondynamic_t);
}
TSWorldGun TSWorldGun::generate(player arg_player, int arg_weaponID){
weapondynamic_t dynaRefPRE = arg_player.ary_myWeapons[arg_weaponID];
return TSWorldGun::generate2(arg_player, dynaRefPRE);
}
// Static method called from elsewhere to create and initialize a
// weapon drop entity, given a player and what weapon to copy information from.
TSWorldGun TSWorldGun::generate2(player arg_player, weapondynamic_t dynaRefPRE){
TSWorldGun eDrop = spawn(TSWorldGun);
//eDrop.setup(arg_player, arg_weaponID);
//weapondynamic_t dynaRefPRE = arg_player.ary_myWeapons[arg_weaponID];
weapondata_basic_t* basicPointerPRE = (weapondata_basic_t*) ary_weaponData[dynaRefPRE.weaponID];
weapondata_basic_t basicRefPRE = *(basicPointerPRE);
eDrop.movetype = MOVETYPE_TOSS;
eDrop.solid = SOLID_TRIGGER; //or CORPSE
//TSWorldGun eDrop = spawn(TSWorldGun);
setorigin( eDrop, arg_player.origin + arg_player.view_ofs );
setmodel( eDrop, basicRefPRE.sWorldModelPath );
eDrop.angles = [0, randomInRange_f(0, 360), 0];
eDrop.avelocity = [0, randomInRange_f(100, 500), 0];
eDrop.classname = "remove_me";
eDrop.owner = arg_player;
//eDrop.weapon = dynaRefPRE.weaponID;
eDrop.think = TSWorldGun::Think;
eDrop.touch = TSWorldGun::Touch;
eDrop.nextthink = time + 0.5f;
eDrop.copyFrom2(arg_player, dynaRefPRE);
//uhh.. ok, sure
eDrop.health = 1;
setsize( eDrop, '-16 -16 0', '16 16 16' );
//is this v_forward sometimes bad.. ?
makevectors( arg_player.v_angle );
eDrop.velocity = arg_player.velocity + v_forward * 320; //256?
eDrop.gravity = 0.9;
//And lastly, assume I need to expire at some point.
eDrop.expireTime = time + autocvar_weaponstay; //autocvar_weaponstay
eDrop.PlayerUse = TSWorldGun::PlayerUse;
return eDrop;
}//END OF generate
void TSWorldGun::copyFrom(player arg_player, int arg_weaponID){
weapondynamic_t tempRef = arg_player.ary_myWeapons[arg_weaponID];
copyFrom2(arg_player, tempRef);
}
// From what index in the player's inventory should I copy stats from?
// Called as we're being filled to be thrown from the player.
void TSWorldGun::copyFrom2(player arg_player, weapondynamic_t tempRef){
//weapondynamic_t tempRef = arg_player.ary_myWeapons[arg_weaponID];
COPYVARFROM(weaponID)
COPYVARFROM(weaponTypeID)
//COPYVARFROM(iBitsUpgrade)
//actually want to exclude the AKIMBO and FULLLOAD bits. They were only for the shop really.
myInfo.iBitsUpgrade = tempRef.iBitsUpgrade & ~(BITS_WEAPONOPT_AKIMBO | BITS_WEAPONOPT_FULLLOAD);
//COPYVARFROM(iCount)
weapondata_basic_t* weaponPointer = ary_weaponData[tempRef.weaponID];
weapondata_basic_t basicRef = *((weapondata_basic_t*) weaponPointer);
if(basicRef.typeID == WEAPONDATA_TYPEID_THROWABLE){
//we're a throwable? Send the count over.
COPYVARFROM(iCount)
}else{
// Always a count of 1. Any dropped weapon from akimbo is really just "one" of the two pickups needed.
// Even weapons that only come in akimbo, like goldencolts, don't hurt by being called a count of "1".
// They keep the same shop stats, which is really the point here.
myInfo.iCount = 1;
}
COPYVARFROM(iPrice) //who cares.
//COPYVARFROM(iSlots)
//re-calculate the slots now.
myInfo.iSlots = myInfo.iCount * basicRef.iSlots;
//Hold on... this isn't so simple.
if(basicRef.typeID == WEAPONDATA_TYPEID_GUN || basicRef.typeID == WEAPONDATA_TYPEID_IRONSIGHT){
if(basicRef.iBitsUpgradeAuto & BITS_WEAPONOPT_AKIMBO){
//If the weapon we're spawned from is forced akimbo, the intuitive way works.
//iClipLeft & iClipAkimboLeft can be filled, this is a singular drop to represent akimbo.
COPYVARFROM(iClipLeft)
COPYVARFROM(iClipAkimboLeft)
}else if(basicRef.iBitsUpgrade & BITS_WEAPONOPT_AKIMBO && tempRef.iBitsUpgrade & BITS_WEAPONOPT_AKIMBO){
//If the weapon supports akimbo and we have it, assume the thing dropped is the 2nd weapon.
//That is, the one tied to "iClipAkimboLeft".
if(arg_player.weaponEquippedAkimbo){
myInfo.iClipLeft = tempRef.iClipAkimboLeft;
myInfo.iClipAkimboLeft = 0;
}else{
//oh.. drop the singular varient's ammo count then.
myInfo.iClipLeft = tempRef.iClipLeft;
myInfo.iClipAkimboLeft = 0;
}
}else{
//not akimbo or doesn't support it? Only this one.
myInfo.iClipLeft = tempRef.iClipLeft;
myInfo.iClipAkimboLeft = 0;
}
}else{
//doesn't use these.
myInfo.iClipLeft = 0;
myInfo.iClipAkimboLeft = 0;
}
COPYVARFROM(iBitsUpgrade_on)
COPYVARFROM(iFireMode) //we can always copy both firemodes to any individual weapon, can't really hurt.
COPYVARFROM(iFireModeAkimbo)
//COPYVARFROM(iIronSight)
COPYVARFROM(forceBodygroup1Submodel)
myInfo.iIronSight = 0; //default: not using it.
}//END OF copyFrom
// From what index in the player's inventory should I copy stats from?
// Called as we're being picked up by a player to fill one of their weapon slots.
void TSWorldGun::copyTo(player arg_player, int arg_weaponID){
weapondynamic_t tempRef = arg_player.ary_myWeapons[arg_weaponID];
COPYVARTO(weaponID)
COPYVARTO(weaponTypeID)
//COPYVARTO(iBitsUpgrade)
//COPYVARTO(iCount)
COPYVARTO(iPrice) //no one cares.
//COPYVARTO(iSlots) //re-calculated.
//COPYVARTO(iClipLeft)
//COPYVARTO(iClipAkimboLeft)
//COPYVARTO(iBitsUpgrade_on)
//COPYVARTO(iFireMode)
//COPYVARTO(iFireModeAkimbo)
//COPYVARTO(iIronSight)
COPYVARTO(forceBodygroup1Submodel)
tempRef.iIronSight = 0; //default: not using it.
}//END OF copyTo
void TSWorldGun::Touch( void ) {
if ( other.classname != "player" ) {
// assume it's the world.. play this sound?
//printfline("the thing I touched is %s", other.classname);
// TODO - any others we need to keep track of for making the drop?
if(other.classname == "worldspawn" || other.classname == "func_breakable"){
sound( this, CHAN_ITEM, "items/weapondrop1.wav", 1, ATTN_NORM, 100, SOUNDFLAG_FOLLOW );
}
return;
}
}//END OF touch method
void TSWorldGun::PlayerUse( void ) {
//laziness.
//entity other = eActivator;
//...no, hides a global, not wise.
other = eActivator; //this however should be fine?
// !!! IMPORTANT !!!
// Want to be able to pick me up rapidly? You have to remove this check too,
// or setting the owner to "player" on generation.
// This means the player that spawend me can't pick me up for a little while.
// This is completely independent of accessibleCooldownTime, which prevents
// all players from picking me up too soon instead.
if ( other.classname != "player" ) {
return;
} else if ( other == this.owner ) {
return;
}
//entity eOld = self;
//TSWorldGun selfRef = (TSWorldGun)self;
//self = other;
player otherPlayerRef = (player)other; //safe assumption now.
BOOLEAN shouldDelete;
if(time >= this.accessibleCooldownTime){
shouldDelete = otherPlayerRef.attemptAddWeaponFromPickup(this);
this.accessibleCooldownTime = time + 0.8;
}else{
shouldDelete = FALSE;
}
//self = eOld;
if(shouldDelete){
remove(this);
}
}
void TSWorldGun::Think( void ) {
//TSWorldGun selfRef = (TSWorldGun)self;
// oh.. this makes the weapon collidable with the original dropper
// again.
if(time >= this.expireTime){
//expire.
remove(this);
}else{
this.owner = world;
//set the next think to aim around this time then.
this.nextthink = this.expireTime + 0.1;
}
}
void CTSWorldGun::CTSWorldGun(void){
accessibleCooldownTime = -1;
myInfo = spawn(weapondynamic_t);
}
CTSWorldGun CTSWorldGun::generate(player arg_player, int arg_weaponID){
weapondynamic_t dynaRefPRE = arg_player.ary_myWeapons[arg_weaponID];
return CTSWorldGun::generate2(arg_player, dynaRefPRE);
}
// Static method called from elsewhere to create and initialize a
// weapon drop entity, given a player and what weapon to copy information from.
CTSWorldGun CTSWorldGun::generate2(player arg_player, weapondynamic_t dynaRefPRE){
CTSWorldGun eDrop = spawn(CTSWorldGun);
//eDrop.setup(arg_player, arg_weaponID);
//weapondynamic_t dynaRefPRE = arg_player.ary_myWeapons[arg_weaponID];
weapondata_basic_t* basicPointerPRE = (weapondata_basic_t*) ary_weaponData[dynaRefPRE.weaponID];
weapondata_basic_t basicRefPRE = *(basicPointerPRE);
eDrop.movetype = MOVETYPE_TOSS;
eDrop.solid = SOLID_TRIGGER; //or CORPSE
//CTSWorldGun eDrop = spawn(CTSWorldGun);
setorigin( eDrop, arg_player.origin + arg_player.view_ofs );
setmodel( eDrop, basicRefPRE.sWorldModelPath );
eDrop.angles = [0, randomInRange_f(0, 360), 0];
eDrop.avelocity = [0, randomInRange_f(100, 500), 0];
eDrop.classname = "remove_me";
eDrop.owner = arg_player;
//eDrop.weapon = dynaRefPRE.weaponID;
eDrop.think = CTSWorldGun::Think;
eDrop.touch = CTSWorldGun::Touch;
eDrop.nextthink = time + 0.5f;
eDrop.copyFrom2(arg_player, dynaRefPRE);
//uhh.. ok, sure
eDrop.health = 1;
setsize( eDrop, '-16 -16 0', '16 16 16' );
//is this v_forward sometimes bad.. ?
makevectors( arg_player.v_angle );
eDrop.velocity = arg_player.velocity + v_forward * 320; //256?
eDrop.gravity = 0.9;
//And lastly, assume I need to expire at some point.
eDrop.expireTime = time + autocvar_weaponstay; //autocvar_weaponstay
eDrop.PlayerUse = CTSWorldGun::PlayerUse;
return eDrop;
}//END OF generate
void CTSWorldGun::copyFrom(player arg_player, int arg_weaponID){
weapondynamic_t tempRef = arg_player.ary_myWeapons[arg_weaponID];
copyFrom2(arg_player, tempRef);
}
// From what index in the player's inventory should I copy stats from?
// Called as we're being filled to be thrown from the player.
void CTSWorldGun::copyFrom2(player arg_player, weapondynamic_t tempRef){
//weapondynamic_t tempRef = arg_player.ary_myWeapons[arg_weaponID];
COPYVARFROM(weaponID)
COPYVARFROM(weaponTypeID)
//COPYVARFROM(iBitsUpgrade)
//actually want to exclude the AKIMBO and FULLLOAD bits. They were only for the shop really.
myInfo.iBitsUpgrade = tempRef.iBitsUpgrade & ~(BITS_WEAPONOPT_AKIMBO | BITS_WEAPONOPT_FULLLOAD);
//COPYVARFROM(iCount)
weapondata_basic_t* weaponPointer = ary_weaponData[tempRef.weaponID];
weapondata_basic_t basicRef = *((weapondata_basic_t*) weaponPointer);
if(basicRef.typeID == WEAPONDATA_TYPEID_THROWABLE){
//we're a throwable? Send the count over.
COPYVARFROM(iCount)
}else{
// Always a count of 1. Any dropped weapon from akimbo is really just "one" of the two pickups needed.
// Even weapons that only come in akimbo, like goldencolts, don't hurt by being called a count of "1".
// They keep the same shop stats, which is really the point here.
myInfo.iCount = 1;
}
COPYVARFROM(iPrice) //who cares.
//COPYVARFROM(iSlots)
//re-calculate the slots now.
myInfo.iSlots = myInfo.iCount * basicRef.iSlots;
//Hold on... this isn't so simple.
if(basicRef.typeID == WEAPONDATA_TYPEID_GUN || basicRef.typeID == WEAPONDATA_TYPEID_IRONSIGHT){
if(basicRef.iBitsUpgradeAuto & BITS_WEAPONOPT_AKIMBO){
//If the weapon we're spawned from is forced akimbo, the intuitive way works.
//iClipLeft & iClipAkimboLeft can be filled, this is a singular drop to represent akimbo.
COPYVARFROM(iClipLeft)
COPYVARFROM(iClipAkimboLeft)
}else if(basicRef.iBitsUpgrade & BITS_WEAPONOPT_AKIMBO && tempRef.iBitsUpgrade & BITS_WEAPONOPT_AKIMBO){
//If the weapon supports akimbo and we have it, assume the thing dropped is the 2nd weapon.
//That is, the one tied to "iClipAkimboLeft".
if(arg_player.weaponEquippedAkimbo){
myInfo.iClipLeft = tempRef.iClipAkimboLeft;
myInfo.iClipAkimboLeft = 0;
}else{
//oh.. drop the singular varient's ammo count then.
myInfo.iClipLeft = tempRef.iClipLeft;
myInfo.iClipAkimboLeft = 0;
}
}else{
//not akimbo or doesn't support it? Only this one.
myInfo.iClipLeft = tempRef.iClipLeft;
myInfo.iClipAkimboLeft = 0;
}
}else{
//doesn't use these.
myInfo.iClipLeft = 0;
myInfo.iClipAkimboLeft = 0;
}
COPYVARFROM(iBitsUpgrade_on)
COPYVARFROM(iFireMode) //we can always copy both firemodes to any individual weapon, can't really hurt.
COPYVARFROM(iFireModeAkimbo)
//COPYVARFROM(iIronSight)
COPYVARFROM(forceBodygroup1Submodel)
myInfo.iIronSight = 0; //default: not using it.
}//END OF copyFrom
// From what index in the player's inventory should I copy stats from?
// Called as we're being picked up by a player to fill one of their weapon slots.
void CTSWorldGun::copyTo(player arg_player, int arg_weaponID){
weapondynamic_t tempRef = arg_player.ary_myWeapons[arg_weaponID];
COPYVARTO(weaponID)
COPYVARTO(weaponTypeID)
//COPYVARTO(iBitsUpgrade)
//COPYVARTO(iCount)
COPYVARTO(iPrice) //no one cares.
//COPYVARTO(iSlots) //re-calculated.
//COPYVARTO(iClipLeft)
//COPYVARTO(iClipAkimboLeft)
//COPYVARTO(iBitsUpgrade_on)
//COPYVARTO(iFireMode)
//COPYVARTO(iFireModeAkimbo)
//COPYVARTO(iIronSight)
COPYVARTO(forceBodygroup1Submodel)
tempRef.iIronSight = 0; //default: not using it.
}//END OF copyTo
void CTSWorldGun::Touch( void ) {
if ( other.classname != "player" ) {
// assume it's the world.. play this sound?
//printfline("the thing I touched is %s", other.classname);
// TODO - any others we need to keep track of for making the drop?
if(other.classname == "worldspawn" || other.classname == "func_breakable"){
sound( this, CHAN_ITEM, "items/weapondrop1.wav", 1, ATTN_NORM, 100, SOUNDFLAG_FOLLOW );
}
return;
}
}//END OF touch method
void CTSWorldGun::PlayerUse( void ) {
//laziness.
//entity other = eActivator;
//...no, hides a global, not wise.
other = eActivator; //this however should be fine?
// !!! IMPORTANT !!!
// Want to be able to pick me up rapidly? You have to remove this check too,
// or setting the owner to "player" on generation.
// This means the player that spawend me can't pick me up for a little while.
// This is completely independent of accessibleCooldownTime, which prevents
// all players from picking me up too soon instead.
if ( other.classname != "player" ) {
return;
} else if ( other == this.owner ) {
return;
}
//entity eOld = self;
//CTSWorldGun selfRef = (CTSWorldGun)self;
//self = other;
player otherPlayerRef = (player)other; //safe assumption now.
BOOLEAN shouldDelete;
if(time >= this.accessibleCooldownTime){
shouldDelete = otherPlayerRef.attemptAddWeaponFromPickup(this);
this.accessibleCooldownTime = time + 0.8;
}else{
shouldDelete = FALSE;
}
//self = eOld;
if(shouldDelete){
remove(this);
}
}
void CTSWorldGun::Think( void ) {
//CTSWorldGun selfRef = (CTSWorldGun)self;
// oh.. this makes the weapon collidable with the original dropper
// again.
if(time >= this.expireTime){
//expire.
remove(this);
}else{
this.owner = world;
//set the next think to aim around this time then.
this.nextthink = this.expireTime + 0.1;
}
}

View File

@ -3,5 +3,5 @@
// Likely never used by the map as it's not mentioned in ts_fgd.ffd,
// and our own logic for weapons does not use an entity anyway.
// This was likely used to represent a weapon in the player's
// inventory in the original game, since TSWorldGun is clearly the
// inventory in the original game, since CTSWorldGun is clearly the
// in-world pickup.

View File

@ -319,6 +319,9 @@ TSMultiplayerRules::PlayerDeath(base_player pp)
printfline("setInventoryEquippedIndex Flag Z");
TS_resetViewModel(pl);
pl.setInventoryEquippedIndex(-1);
pl.resetZoom();
for(int i = pl.ary_myWeapons_softMax-1; i >= 0; i--){
pl.dropWeapon(i, TRUE);

View File

@ -17,7 +17,7 @@
/* PICKUP ITEMS */
// Bare minimum to compile with what Nuclide's src/server/weapons.qc expects.
// TS already has its own weapons-pickup class: TSWorldGun.
// TS already has its own weapons-pickup class: CTSWorldGun.
// Although that could fill in Nuclide's expected item_pickup and let anything in-map
// redirect to this if that were preferred.

View File

@ -5,6 +5,9 @@ void ServerGame_Precache(void){
printfline("***ServerGame_Precache called***");
SharedGame_Precache();
// yes, a serverside to this for now, the sound call is from serverside for the time being
FX_TS_Explosion_Grenade_Init();
//TAGGG - From FreeHL. Anything that ends up unused by FreeTS can be removed,
// including sound config files that are then unused.
@ -17,8 +20,7 @@ void ServerGame_Precache(void){
precache_model("models/player.mdl");
////////////////////////////////////////////////////////////
TSGrenadeProjectile::precache();
ts_powerup::precache();
TS_GrenadeProjectile::precache();
precache_model("models/powerup.mdl");

View File

@ -59,15 +59,16 @@ defs.h
../shared/weapons.h
../shared/player.h
../shared/powerup.h
../shared/sound_pitched.h
precache.h
entity/ts_powerup.h
//player.c
entity/TSWorldGun.h
entity/TSThrownProjectile.h
entity/TSGrenadeProjectile.h
entity/ts_worldgun.h
entity/ts_thrownprojectile.h
entity/ts_ammopack.h
entity/ts_grenadeprojectile.h
../shared/include.src
@ -85,10 +86,10 @@ entity/ts_slowmotionpoint.qc
entity/ts_teamescape.qc
entity/ts_trigger.qc
entity/ts_wingiver.qc
entity/TSWorldGun.qc
entity/TSThrownProjectile.qc
entity/TSAmmoPack.qc
entity/TSGrenadeProjectile.qc
entity/ts_worldgun.qc
entity/ts_thrownprojectile.qc
entity/ts_ammopack.qc
entity/ts_grenadeprojectile.qc
../shared/player.qc
../shared/inventory_logic.qc
@ -117,9 +118,10 @@ spawn.qc
../shared/util.qc
../shared/precache.qc
// no server util.qc
precache.qc
//money.qc
//spectator.qc

View File

@ -5,6 +5,9 @@
#define ASSIGN_SHELLEJECTDATA(arg_constName) ary_shellEjectData[SHELLEJECT_ID::##arg_constName] = (shellejectdata_t*) &shelleject_##arg_constName;
#define DECLARE_SHELLEJECTDATA(arg_varName, arg_sModelPath, arg_sTouchSound) shellejectdata_t shelleject_##arg_varName = {arg_sModelPath, arg_sTouchSound};
#define ASSIGN_MUZZLEFLASHDATA(arg_constName) ary_muzzleFlashData[MUZZLEFLASH_ID::##arg_constName] = (muzzleflashdata_t*) &muzzleflash_##arg_constName;
#define DECLARE_MUZZLEFLASHDATA(arg_varName, arg_sSpritePath) var muzzleflashdata_t muzzleflash_##arg_varName = {0, arg_sSpritePath};
enum AMMO_ID{
NONE = 0,
@ -69,6 +72,12 @@ enum SHELLEJECT_ID{
};
// For now, ShellEject and MuzzleFlash structs are clientside only.
// ENUMs to let calls to related shared methods be dummied serverside for now
#ifdef CLIENT
// any other info tied to shell choice?
typedef struct{
string sModelPath;
@ -76,4 +85,41 @@ typedef struct{
string sTouchSound;
} shellejectdata_t;
#endif
// first three are the default HL muzzle flashes, which might even be skiped by TS.
// TS does come with its own muzzleflash sprites, haven't look into those much yet
enum MUZZLEFLASH_ID{
NONE = 0,
RIFLE,
SMALL,
WEIRD,
LAST_ID
};
// NOTE! iSpritePrecacheID is only for clientside so far, not precached serverside.
// This is based off how FreeHL does muzzleflash sprite precaches: only clientside.
// Structure is here in case they ever become shared.
#ifdef CLIENT
// Not much to a muzzle flash
typedef struct{
int iSpritePrecacheID;
string sSpritePath;
} muzzleflashdata_t;
void MuzzleFlash_precache(void);
#endif
// shared
void setupAmmoData(void);

View File

@ -15,6 +15,8 @@ DECLARE_AMMODATA(_32ACP, ".32 ACP", 0.5, 300)
DECLARE_AMMODATA(_7P62X51MM, "7.62 x 51mm", 30, 35)
#ifdef CLIENT
DECLARE_SHELLEJECTDATA(NONE, "", "")
DECLARE_SHELLEJECTDATA(_56, "models/56_shell.mdl", "modelevent_shell.land")
DECLARE_SHELLEJECTDATA(_556, "models/556_shell.mdl", "modelevent_shell.land")
@ -25,3 +27,102 @@ DECLARE_SHELLEJECTDATA(_SHOTGUN, "models/shotgun_shell.mdl", "modelevent_shotgun
DECLARE_SHELLEJECTDATA(_SHOTGUN_BLUE, "models/shotgun_shell_blue.mdl", "modelevent_shotgunshell.land")
DECLARE_SHELLEJECTDATA(_SHOTGUN_GOLD, "models/shotgun_shell_gold.mdl", "modelevent_shotgunshell.land")
DECLARE_MUZZLEFLASHDATA(NONE, "")
DECLARE_MUZZLEFLASHDATA(RIFLE, "sprites/muzzleflash1.spr")
DECLARE_MUZZLEFLASHDATA(SMALL, "sprites/muzzleflash2.spr")
DECLARE_MUZZLEFLASHDATA(WEIRD, "sprites/muzzleflash3.spr")
// some muzzleflash candidates from TS files:
/*
gun_muzzle.spr
gun_muzzle2.spr
shotgun_pellets.spr a glowing effect? what?
ts_muzzleflash1.spr
ts_muzzleflash1h.spr
ts_muzzleflash1s.spr
ts_muzzleflash2h.spr
ts_muzzleflash6.spr
ts_muzzleflash6b.spr
*/
// In here since the MuzzleFlash isn't getting a class.
// Also, only clientside for now.
void MuzzleFlash_precache(void){
int i;
// taking these from Nuclide for now, may as well.
// Wait, why precache these if Nuclide already does getmodelindex to fetch the ID's?
//precache_model("sprites/muzzleflash1.spr");
//precache_model("sprites/muzzleflash2.spr");
//precache_model("sprites/muzzleflash3.spr");
// oh hey, arrow operator works in QuakeC.
// ... don't tell me how long this has been the case, alright.
(ary_muzzleFlashData[MUZZLEFLASH_ID::RIFLE])->iSpritePrecacheID = MUZZLE_RIFLE;
(ary_muzzleFlashData[MUZZLEFLASH_ID::SMALL])->iSpritePrecacheID = MUZZLE_SMALL;
(ary_muzzleFlashData[MUZZLEFLASH_ID::WEIRD])->iSpritePrecacheID = MUZZLE_WEIRD;
// NOTE - lines like this:
// (*whatever).var = thing
// will not save the change! Or, sometimes it seems they do? Maybe this rarely comes up
// For the rest, do the whole process
// start at 4 because 0 is for NONE, then 1,2,3's prechaches are handled by Nuclide
for(i = 4; i < MUZZLEFLASH_ID::LAST_ID; i++){
muzzleflashdata_t* tempRef = ary_muzzleFlashData[i];
int theModelIndex;
if((*tempRef).sSpritePath != NULL){
theModelIndex = (int)getmodelindex((*tempRef).sSpritePath);
}else{
theModelIndex = 0;
}
tempRef->iSpritePrecacheID = theModelIndex;
}
}
#endif
// for ammodata structs and all the other oddities
void setupAmmoData(void){
ASSIGN_AMMODATA(NONE)
ASSIGN_AMMODATA(_9X19MM)
ASSIGN_AMMODATA(_45ACP)
ASSIGN_AMMODATA(_P50AE)
ASSIGN_AMMODATA(_5P7X28)
ASSIGN_AMMODATA(_10MMAUTO)
ASSIGN_AMMODATA(_P22LR)
ASSIGN_AMMODATA(_P454CASULL)
ASSIGN_AMMODATA(_5P56NATO)
ASSIGN_AMMODATA(_7P62X39MM)
ASSIGN_AMMODATA(_50BMG)
ASSIGN_AMMODATA(_SHELLS)
ASSIGN_AMMODATA(_32ACP)
ASSIGN_AMMODATA(_7P62X51MM)
#ifdef CLIENT
ASSIGN_SHELLEJECTDATA(NONE)
ASSIGN_SHELLEJECTDATA(_56)
ASSIGN_SHELLEJECTDATA(_556)
ASSIGN_SHELLEJECTDATA(_22)
ASSIGN_SHELLEJECTDATA(_9MM)
ASSIGN_SHELLEJECTDATA(_GENERIC)
ASSIGN_SHELLEJECTDATA(_SHOTGUN)
ASSIGN_SHELLEJECTDATA(_SHOTGUN_BLUE)
ASSIGN_SHELLEJECTDATA(_SHOTGUN_GOLD)
printfline("ASSIGNMENT HAPPENED");
ASSIGN_MUZZLEFLASHDATA(NONE)
ASSIGN_MUZZLEFLASHDATA(SMALL)
ASSIGN_MUZZLEFLASHDATA(RIFLE)
ASSIGN_MUZZLEFLASHDATA(WEIRD)
#endif
}// setupAmmoData

View File

@ -43,19 +43,6 @@ enum TS_Team{
//TAGGG
//FLAG. Rename of the same value used by FL_SEMI_TOGGLED, since that name isn't used in The Specialists
//now. It will instead tell whether this is the first time firing since a release or not.
// One for secondary added too. hope that's a good idea
// ...unfortunately using these for flag values might've been a bad idea.
// Even in the old version, "1<<21" was already used for something else.
// They've been offset in the new version (base FreeCS by the way).
// So these will just be player bool's instead.
//#define FL_PRIMARY_FIRE_FIRST_FRAME (1<<20)
//#define FL_SECONDARY_FIRE_FIRST_FRAME (1<<21)
// MODERN FREECS STATS (in case they're needed for the sake of being
// an extensive gamemod, but seeing as FreeHL has none of these, I doubt
// that)

View File

@ -10,15 +10,12 @@ void TS_playerEquippedWeapon_Shared(player pl, int newWeaponEquipped, BOOL useAk
#ifdef CLIENT
void _TS_playerEquippedWeapon(player pl, int newWeaponEquipped, BOOL useAkimbo);
void TS_playerEquippedWeapon(player pl, int newWeaponEquipped, BOOL useAkimbo);
void EV_EquipCallback(void);
#endif
#ifdef SERVER
void _TS_playerEquippedWeapon(player pl, int newWeaponEquipped, BOOL useAkimbo);
void TS_playerEquippedWeapon(player pl, int newWeaponEquipped, BOOL useAkimbo);
void CSEv_TS_playerEquippedWeapon_ii(int newWeaponEquipped, BOOL useAkimbo);
#endif

View File

@ -37,7 +37,8 @@ TS_Weapon_Draw_extra(void){
printfline("PLAYER DREW WEAPON: invID:%i (g_weapons ID:%d)", pl.inventoryEquippedIndex, pl.activeweapon);
pl.currentZoomChoice = -1;
pl.resetZoom();
pl.aryNextBurstShotTime_softLength = 0;
pl.aryNextBurstShotTime_listenIndex = -1;
@ -180,6 +181,32 @@ TS_playerEquippedWeapon(player pl, int newWeaponEquipped, BOOL useAkimbo){
_TS_playerEquippedWeapon(pl, newWeaponEquipped, useAkimbo);
sendevent("TS_playerEquippedWeapon", "ii", newWeaponEquipped, (int)useAkimbo);
// EXPERIMENTAL
pl.equippedWeaponWaitingForCallback = TRUE;
// Not sure how you'd deal with a ping worse than 0.5 seconds
pl.equippedWeaponWaitingForCallback_maxWaitTime = time + 0.6;
}
// EXPERIMENTAL. If the currently equipped weapon has been changed, reject
// messages received between the time I sent an order to change the current wepaon
// and the time it takes to get a response that the new weapon was seen by the server.
// This stops out-of-date calls coming in from reverting the zoom (or whatever other var)
// back to the old state.
// Or, example:
// Var A is networked (server sends updates to the client of its current value to keep it
// from going too far out of sync).
// var A starts at 30 both places. Say the ping is 500 milliseconds.
// Client sets var A to 12, sends a message to the server to have it changed too.
// But, during those 500 milliseconds to reach the server, messages sent from the server
// with the old A value (30), sent before the client sent the A-update to the server, reach
// the client and rever the value of A back to that 30.
// Only after the A-update of 12 reaches the server and the server updates the client back
// does that stop.
void
EV_EquipCallback(void){
player pl = (player)self;
pl.equippedWeaponWaitingForCallback = FALSE;
}
#endif
@ -200,8 +227,16 @@ TS_playerEquippedWeapon(player pl, int newWeaponEquipped, BOOL useAkimbo){
//pl.activeweapon_net = 255;
//pl.inventoryEquippedIndex_net = 255;
// The client is waiting for a callback? Go on!
// Trying the reliable (_R) version for now
WriteByte( MSG_MULTICAST, SVC_CGAMEPACKET );
WriteByte( MSG_MULTICAST, EVENT_TS::EQUIP_CALLBACK );
msg_entity = pl;
multicast( [0,0,0], MULTICAST_ONE_R );
}
// This is a received call from the client.
// We do need to let the server update first, which then tells the client
// of the updated state. Even though the client initiated the call in this case.
@ -305,6 +340,10 @@ EV_PlayerDeath(void){
// after this PlayerDeath one, somehow. Stopping damage-drawing on the "*dead" key
// being 1 works.
//pSeat->m_flDamageAlpha = 0;
player pl = (player)self;
pl.resetZoom();
}
#endif

View File

@ -10,6 +10,7 @@ enum EVENT_TS{
EV_IMPACT_MELEE,
//DROP_WEAPON,
FX_TS_EXPLOSION_GRENADE,
EQUIP_CALLBACK,
SOUNDPITCHED,
SOUNDPITCHED_CHANNEL,
TEST,

View File

@ -250,8 +250,9 @@ FX_Impact_Melee(int iType, vector vecPos, vector vNormal)
multicast(vecPos, MULTICAST_PVS);
#else
//TAGGG - TODO. See _base\server\footsteps.c for other pl_... sounds to use
// as TS did for various surfaces hit by melee.
//TAGGG - TODO. See Nuclide's footsteps.qc for other pl_... sounds to use
// as TS did for various surfaces hit by melee. Used in sound script files.
// Or that might be all done now.
float impactSoundVolume = 0.55;

View File

@ -10,9 +10,19 @@ var int FX_TS_EXPLOSION_PARTICLE;
void
FX_TS_Explosion_Grenade_Init(void)
{
Sound_Precache("fx.ts_explosion_grenade");
//Sound_Precache("fx.ts_explosion_grenade");
FX_TS_EXPLOSION_PARTICLE = particleeffectnum("ts_fx_explosion_grenade.explosion_grenade");
}
#else
// sound only
void
FX_TS_Explosion_Grenade_Init(void)
{
Sound_Precache("fx.ts_explosion_grenade");
}
#endif
@ -47,10 +57,30 @@ FX_TS_Explosion_Grenade(vector vecPos)
#ifdef SERVER
// call me around a FX_TS_Explosion_Grenade call in TSGrenadeProjectile
// call me around a FX_TS_Explosion_Grenade call in TS_GrenadeProjectile
void
FX_TS_Explosion_Grenade_PlaySound(entity ePlayer){
Sound_Play(ePlayer, CHAN_WEAPON, "fx.ts_explosion_grenade");
FX_TS_Explosion_Grenade_PlaySound(entity eSelf){
//Sound_Play(eSelf, CHAN_WEAPON, "fx.ts_explosion_grenade");
// if we're not using the sound-script, do it by a manual call
//Client_ShakeOnce(vector pos, float radius, float duration, float frequency, float amplitude)
// there is a command, soundlength("x") that takes a path to a .wav file I think?
// Probably unnecessary
Client_ShakeOnce(eSelf.origin, 512, 1.7, 2.1, 3.4);
float randomChoice = random();
if(randomChoice < 0.2){
SoundPitched_Channel_Send(eSelf, SNDP_EXPLODE, CHAN_AUTO);
}else if(randomChoice < 0.4){
SoundPitched_Channel_Send(eSelf, SNDP_EXPLODE1, CHAN_AUTO);
}else if(randomChoice < 0.6){
SoundPitched_Channel_Send(eSelf, SNDP_EXPLODE2, CHAN_AUTO);
}else if(randomChoice < 0.8){
SoundPitched_Channel_Send(eSelf, SNDP_EXPLODE3, CHAN_AUTO);
}else{
SoundPitched_Channel_Send(eSelf, SNDP_EXPLODE4, CHAN_AUTO);
}
}
#endif

View File

@ -1,6 +1,5 @@
// If enabled, pressing left and right fire within a small amount of time
// (more forgiving than the default "same-frame only" timing) lets firing
// immediately change into the akimbo dual-fire animation.
@ -15,7 +14,6 @@
#includelist
//TAGGG - NEW
init.h
entities.h
@ -41,7 +39,6 @@ precache.h
inventory_logic.h
event_enum.h
event_custom.h
//init.h
// Nope! Leave this one up to per-project.
@ -72,20 +69,13 @@ fx_ts_explosion_grenade.qc
event_custom.qc
util.qc
precache.qc
// leaving these up to client/server projects too now
//util.qc
//precache.qc
sound_pitched.qc
//fx_impact.h
//pmove.c
//animations.c
//items.h
//weapons.h
// <half life weapons files were here>
weapons/weapon_karate.qc
weapons/weapon_glock18.qc
weapons/weapon_socommk23.qc

View File

@ -1,5 +1,12 @@
// for client and serverside individually, data structs never need to be assigned
// more than once. However, this does not necessarily apply to precaches, the client
// renderer may restart sometimes.
// This is why precache calls should be handled elsewhere in precache methods
// that get called when needed.
var BOOL g_bDataStructsInit = FALSE;
// NOTE - for clientside, not called in ClientGame_RendererRestart, only
// once in ClientGame_Init.
@ -10,8 +17,13 @@ void SharedGame_Init(void){
// those had to lead here to be reached (SharedGame_Init is not called by
// Nuclide's src directly).
setupWeaponData();
setupPowerupData();
if(!g_bDataStructsInit){
g_bDataStructsInit = TRUE;
setupWeaponData();
setupPowerupData();
setupAmmoData();
}
}

View File

@ -96,7 +96,7 @@ BOOL attemptBuyWeapon(player pl, int arg_weaponID, int arg_iBitsUpgrade, int iCo
#endif
#ifdef SERVER
int addWeaponToInventory(player pl, TSWorldGun arg_pickupRef);
int addWeaponToInventory(player pl, CTSWorldGun arg_pickupRef);
#endif
#ifdef CLIENT

View File

@ -1467,7 +1467,7 @@ BOOL attemptBuyWeapon(player pl, int arg_weaponID, int arg_iBitsUpgrade, int iCo
//TAGGG - TODO. Could this even be shared?
// It is only called by the player picking up weapons ingame, which only happens serverside.
// The client does not even receive the implementation details of TSWorldGun.
// The client does not even receive the implementation details of CTSWorldGun.
#ifdef SERVER
// This method may only be used by the server ingame, not at all buy-related.
@ -1480,7 +1480,7 @@ BOOL attemptBuyWeapon(player pl, int arg_weaponID, int arg_iBitsUpgrade, int iCo
// if there is room for it... this should not call this method at all)
// Picking up the new weapon cannot put the player overbudget for slots (default 81). If so, we deny the pickup.
//int addWeaponToInventory(player pl, int arg_weaponID, int arg_iClip, int arg_iClipAkimbo, int arg_iBitsUpgrade, int iCount){
int addWeaponToInventory(player pl, TSWorldGun arg_pickupRef){
int addWeaponToInventory(player pl, CTSWorldGun arg_pickupRef){
//safe assumption... for now.
//NOTICE that this doesn't mean anything if we return -1,

View File

@ -1,6 +1,6 @@
//TAGGG - NEW. Header file for gamemod player
class TSWorldGun;
class CTSWorldGun;
// NOTE-
@ -100,13 +100,38 @@ class player:base_player
// Should this be predicted? Unsure, I doubt it.
float maxspeed_raw;
// ZOOM VARS
////////////////////////////////
// Don't use viewzoom, that's used by Nucldie to enforce the real zoom.
// The closest thing is flZoomCurrent further down, the raw value even after the current
// state of lerp to be given to viewzoom.
// The current choice of zoom of some incremental number offered by the current weapon.
// 0 is the default (no zoom). There is no standard for what zoom value there is for each
// zoom level in general, that is up to the equipped weapon's secondaryfire method to fill
// on right-clicking to change the zoom level.
PREDICTED_INT(iZoomLevel);
// Set this (or the setZoom method) to tap into the lerp system properly.
// When noticed (client/view.qc), the current zoom value goes to flZoomStart and
// flZoomTarget goes to flZoomEnd. The lerp goes from Start to End for a smooth transition.
PREDICTED_FLOAT(flZoomTarget);
#ifdef CLIENT
//TAGGG - related to how to handle FOV changes.
float flCurrentZoom;
float flOldZoom;
float flZoomEnd;
float flZoomStart;
float flZoomLerp;
float flZoomLevel;
float flZoomCurrent;
#endif
////////////////////////////////
#ifdef CLIENT
BOOL equippedWeaponWaitingForCallback;
float equippedWeaponWaitingForCallback_maxWaitTime;
// For telling how long it's been since I've been on the ground.
// Don't oscillate the view model bob on going down short steps.
@ -163,10 +188,6 @@ class player:base_player
#endif
// shared zoom var! Don't use viewzoom, that's used by Nucldie to enforce the real zoom
PREDICTED_FLOAT(flTargetZoom);
float flKarateBlockCooldown;
@ -257,11 +278,7 @@ class player:base_player
BOOL inputPrimaryReleasedQueue;
BOOL inputSecondaryReleasedQueue;
// -1 means not using a scope, regardless of whether the weapon has it.
// We'll keep this serverside too, since that's the one relaying the decisions to the
// client.
int currentZoomChoice;
// Shared, but don't network! I think?
int aryNextBurstShotTime_softLength;
float aryNextBurstShotTime[5];
@ -449,6 +466,8 @@ class player:base_player
virtual void (void)handleAccuracyKickback;
virtual void(float arg_theZoom) setZoom;
virtual void(void) resetZoom;
virtual void(int arg_newIndex) setInventoryEquippedIndex;
virtual void(int arg_newIndex, BOOL useAkimbo) setInventoryEquippedIndex_Akimbo;
@ -493,9 +512,9 @@ class player:base_player
//virtual void () frameThink;
//TAGGG - QUESTION. Does this need to be separate from postThink at all? Same for above,
// forget what these are for
virtual void () frameThink_fromServer;
virtual void(void) frameThink_fromServer;
virtual BOOL(TSWorldGun arg_pickup) attemptAddWeaponFromPickup;
virtual BOOL(CTSWorldGun arg_pickup) attemptAddWeaponFromPickup;
virtual void(int arg_weaponID, BOOL completeDrop) dropWeapon;
virtual BOOL(void) anyAmmoPoolNonEmpty;
virtual void(void) dropAmmo;

View File

@ -13,6 +13,12 @@
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//#define FORCE_NETWORK_ALL_INVENTORY
/* all potential SendFlags bits we can possibly send */
enumflags
@ -180,7 +186,20 @@ player::ReceiveEntity(float new, float fl)
w_attack_akimbo_next = readfloat();
isReloading = readbyte();
isChangingIronsight = readbyte();
flTargetZoom = readfloat();
//flZoomTarget = readfloat();
float tempThing = readfloat();
/*
if(tempThing != flZoomTarget){
printfline("flZoomTarget change! %.2f - %.2f", flZoomTarget, tempThing);
}
*/
// That's a good thing, yes?
if(!equippedWeaponWaitingForCallback){
flZoomTarget = tempThing;
}
iZoomLevel = readbyte();
nextAkimboAttackPreference = readbyte();
akimboDualFireToleranceTime = readfloat();
grenadeFireIndex = readbyte() - 1;
@ -212,7 +231,6 @@ player::ReceiveEntity(float new, float fl)
//doFiremodeChange = readbyte();
currentZoomChoice = readbyte() - 1;
ary_myWeapons_softMax = readbyte();
@ -358,7 +376,8 @@ player::PredictPreFrame(void)
SAVE_STATE(w_attack_akimbo_next);
SAVE_STATE(isReloading);
SAVE_STATE(isChangingIronsight);
SAVE_STATE(flTargetZoom);
SAVE_STATE(flZoomTarget);
SAVE_STATE(iZoomLevel);
SAVE_STATE(nextAkimboAttackPreference);
SAVE_STATE(akimboDualFireToleranceTime);
SAVE_STATE(grenadeFireIndex);
@ -456,7 +475,8 @@ player::PredictPostFrame(void)
ROLL_BACK(w_attack_akimbo_next);
ROLL_BACK(isReloading);
ROLL_BACK(isChangingIronsight);
ROLL_BACK(flTargetZoom);
ROLL_BACK(flZoomTarget);
ROLL_BACK(iZoomLevel);
ROLL_BACK(nextAkimboAttackPreference);
ROLL_BACK(akimboDualFireToleranceTime);
ROLL_BACK(grenadeFireIndex);
@ -505,6 +525,7 @@ player::EvaluateEntity(void)
base_player::EvaluateEntity();
int i;
int myAmmoType;
/* animation */
if (ATTR_CHANGED(anim_bottom) || ATTR_CHANGED(anim_bottom_time))
@ -613,7 +634,7 @@ player::EvaluateEntity(void)
if(ATTR_CHANGED(ary_myWeapons[i].iIronSight)) SendFlags |= PLAYER_UNUSED1;
if(ATTR_CHANGED(ary_myWeapons[i].forceBodygroup1Submodel)) SendFlags |= PLAYER_UNUSED1;
//}
int myAmmoType = getAmmoTypeOfWeapon(this.activeweapon);
myAmmoType = getAmmoTypeOfWeapon(this.activeweapon);
if(myAmmoType != -1){
i = myAmmoType;
//UNNECESSARY. This array is of fixed length, so known at all times.
@ -642,7 +663,8 @@ player::EvaluateEntity(void)
SAVE_STATE(w_attack_akimbo_next);
SAVE_STATE(isReloading);
SAVE_STATE(isChangingIronsight);
SAVE_STATE(flTargetZoom);
SAVE_STATE(flZoomTarget);
SAVE_STATE(iZoomLevel);
SAVE_STATE(nextAkimboAttackPreference);
SAVE_STATE(akimboDualFireToleranceTime);
SAVE_STATE(grenadeFireIndex);
@ -680,7 +702,7 @@ player::EvaluateEntity(void)
//}
int myAmmoType = getAmmoTypeOfWeapon(this.activeweapon);
myAmmoType = getAmmoTypeOfWeapon(this.activeweapon);
if(myAmmoType != -1){
i = myAmmoType;
//UNNECESSARY. This array is of fixed length, so known at all times.
@ -796,7 +818,8 @@ player::SendEntity(entity ePEnt, float fChanged)
WriteFloat(MSG_ENTITY, w_attack_akimbo_next );
WriteByte(MSG_ENTITY, isReloading );
WriteByte(MSG_ENTITY, isChangingIronsight );
WriteFloat(MSG_ENTITY, flTargetZoom);
WriteFloat(MSG_ENTITY, flZoomTarget);
WriteByte(MSG_ENTITY, iZoomLevel);
WriteByte(MSG_ENTITY, nextAkimboAttackPreference);
WriteFloat(MSG_ENTITY, akimboDualFireToleranceTime);
WriteByte(MSG_ENTITY, grenadeFireIndex + 1);
@ -828,7 +851,6 @@ player::SendEntity(entity ePEnt, float fChanged)
//WriteByte(MSG_ENTITY, doFiremodeChange);
WriteByte(MSG_ENTITY, currentZoomChoice + 1 );
//weapondynamic_t ary_myWeapons[ary_myWeapons_length];
@ -933,10 +955,6 @@ player::player(void){
flag_lastWeaponAkimbo = FALSE;
flCurrentZoom = 1;
flOldZoom = 1;
flZoomLerp = 0;
flZoomLevel = 0;
#endif
flKarateBlockCooldown = 0;
@ -1014,63 +1032,55 @@ player::reset(BOOL resetInventory){
// should this even make any assumptions about this?
//iState = ?;
resetZoom();
#ifdef CLIENT
// For safety, doing this.
// If anywhere that ever calls for this method clientside has this set
// properly before the call to here, (whatever event-method in base files leads
// to here most likely), this is not necessary.
// Also, no need for pSeatLocal yet, but add in if that changes.
int s = (float)getproperty(VF_ACTIVESEAT);
pSeat = &g_seats[s];
pSeat->m_flHUDWeaponSelectTime = -1;
// we don't want damage related to the death / between spawns carrying over
// at the start of the next spawn.
pSeat->m_flDamageAlpha = 0;
// doing this in reset too to avoid a little glitch.
weaponSelectHighlightID = -1;
w_freeze_idle_next = -1;
flOldZoom = 1;
flCurrentZoom = 1;
flZoomLevel = 1;
flRecentGroundTime = 0;
//TAGGG - BobNEW.
// Reset the vars here? Or only on an inventory wipe?
pViewBob = &g_viewBobVars[s];
pViewBob->m_flBobTime = 0;
pViewBob->m_flBob = 0;
pViewBob->m_flBobCycle = 0;
pViewBob->m_flSpeed = 0;
pViewBob->m_vCam = [0,0,0];
/////////////////////////////////////////////////////
flViewShake = 0;
recentLaserHitPosSet = FALSE;
lasersightUnlockTime = FALSE;
forceViewModelUpdate = FALSE;
prev_forceBodygroup1Submodel = 0;
// For safety, doing this.
// If anywhere that ever calls for this method clientside has this set
// properly before the call to here, (whatever event-method in base files leads
// to here most likely), this is not necessary.
// Also, no need for pSeatLocal yet, but add in if that changes.
int s = (float)getproperty(VF_ACTIVESEAT);
pSeat = &g_seats[s];
pSeat->m_flHUDWeaponSelectTime = -1;
// we don't want damage related to the death / between spawns carrying over
// at the start of the next spawn.
pSeat->m_flDamageAlpha = 0;
// doing this in reset too to avoid a little glitch.
weaponSelectHighlightID = -1;
w_freeze_idle_next = -1;
flRecentGroundTime = 0;
//TAGGG - BobNEW.
// Reset the vars here? Or only on an inventory wipe?
pViewBob = &g_viewBobVars[s];
pViewBob->m_flBobTime = 0;
pViewBob->m_flBob = 0;
pViewBob->m_flBobCycle = 0;
pViewBob->m_flSpeed = 0;
pViewBob->m_vCam = [0,0,0];
/////////////////////////////////////////////////////
flViewShake = 0;
recentLaserHitPosSet = FALSE;
lasersightUnlockTime = FALSE;
forceViewModelUpdate = FALSE;
prev_forceBodygroup1Submodel = 0;
#endif
#ifdef SERVER
switchToRecentlyAddedWeapon = FALSE;
nextUseCooldown = 0;
switchToRecentlyAddedWeapon = FALSE;
nextUseCooldown = 0;
#endif
currentZoomChoice = -1;
setZoom(1.0f);
viewzoom = 1.0f; // and apply instantly.
// Shared, but don't network! I think?
aryNextBurstShotTime_softLength = 0;
@ -1103,9 +1113,6 @@ player::reset(BOOL resetInventory){
shotgunReloadIndex = 0;
shotgunAddAmmoTime = -1;
shotgunAddAmmoSoundTime = -1;
#ifdef CLIENT
//shotgunAddAmmoTime_cooldownSetTime = -1;
#endif
doFiremodeChange = FALSE;
@ -1119,14 +1126,6 @@ player::reset(BOOL resetInventory){
isReloading = FALSE;
isChangingIronsight = FALSE;
// maybe not necessary, but I don't think
// the client gets any benefit from this.
#ifdef SERVER
//the first time you fire will be the first frame of firing.
//flags = flags | FL_PRIMARY_FIRE_FIRST_FRAME;
//flags = flags | FL_SECONDARY_FIRE_FIRST_FRAME;
#endif
nextAkimboAttackPreference = BITS_AKIMBOCHOICE_LEFT;
recentAttackHadAmmo = FALSE;
@ -1143,6 +1142,8 @@ player::reset(BOOL resetInventory){
if(resetInventory){
// could this be done for resets outside of resetInventory? unsure
flags = 0;
gflags = 0;
@ -1155,6 +1156,10 @@ player::reset(BOOL resetInventory){
shotgunWaitingForPump = FALSE;
#ifdef CLIENT
equippedWeaponWaitingForCallback = FALSE;
#endif
#ifdef SERVER
// other projects do that so sure?
weapon = 0;
@ -1247,7 +1252,28 @@ player::handleAccuracyKickback(void){
void
player::setZoom(float arg_theZoom)
{
flTargetZoom = arg_theZoom;
printfline("ORDER! %.2f", arg_theZoom);
flZoomTarget = arg_theZoom;
}
// forget any zoom-related settings instantly.
// Unsure if a message should be sent to the client if called from the server, or assume the
// calls coincide.
void
player::resetZoom(void)
{
iZoomLevel = 0;
viewzoom = 1.0f;
setZoom(1.0f); // sets flZoomTarget
#ifdef CLIENT
// IMPORTANT! ZoomLerp under 0 tries to involve flZoomOld, set or not
flZoomLerp = 1.0f;
SAVE_STATE(iZoomLevel);
SAVE_STATE(viewzoom);
SAVE_STATE(flZoomTarget);
flZoomEnd = 1.0f;
flZoomCurrent = 1.0f;
#endif
}
void
@ -1337,16 +1363,17 @@ player::setInventoryEquippedIndex_Akimbo(int arg_newIndex, BOOL useAkimbo)
// ... Marvelous. But at least that's a completely separate issue, again with or without below.
// (force a sendoff, expect it area)
/*
#ifdef SERVER
// Force a sendoff!
//SendFlags |= PLAYER_WEAPON;
SendFlags |= PLAYER_WEAPON;
#else
SAVE_STATE(activeweapon);
// unsure if this one's needed
//SAVE_STATE(inventoryEquippedIndex);
SAVE_STATE(inventoryEquippedIndex);
#endif
*/
}
@ -1510,7 +1537,7 @@ player::frameThink_fromServer(void){
#ifdef CLIENT
// Note that these pre/postThink's aren't game events, they're just called by _base/entry.c
// Note that these pre/postThink's aren't game events, they're just called
// before/after prediction accordingly, and every single rendered frame.
// Unlike serverside preThink / postThink, which (I think?) are called independent of any
// logic frame-rate on the server.
@ -1524,6 +1551,11 @@ player::preThink(void){
}
if(time >= equippedWeaponWaitingForCallback_maxWaitTime){
// stop then
equippedWeaponWaitingForCallback = FALSE;
}
// Called before rendering, so this is an acceptable place.
View_HandleZoom();
@ -1649,7 +1681,7 @@ player::postThink(void){
#ifdef SERVER
BOOL
player::attemptAddWeaponFromPickup(TSWorldGun arg_pickup){
player::attemptAddWeaponFromPickup(CTSWorldGun arg_pickup){
//int existingMatchingIndex = findWeaponInConfig((player)other, (int)arg_pickup.myInfo.weaponID);
@ -1723,7 +1755,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
// record the number of slots lost for removing from the total later,
// typically those of the 'eDrop' entity. Adjust for being more than one.
int iSlotsDropped = 0;
TSWorldGun eDrop = NULL;
CTSWorldGun eDrop = NULL;
// there is a "TS_playerDropWeapon" method in event_custom.c we could call if needed.
// Looks like we never really intended for it to go anywhere though, no need for that.
@ -1795,7 +1827,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
// basicRefX.iAkimboID > 0
if((*basicPS).iBitsUpgradeAuto & BITS_WEAPONOPT_AKIMBO){
// singular akimbo? dropping removes.
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
removeWeaponFromInventory(this, arg_weaponID);
if(!completeDrop){
playerEquipIdealSafe(this);
@ -1812,7 +1844,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
// WAIT NOT JUST YET. The weapon drop will think we're dropping the weapon while it
// didn't have akimbo.
if(!completeDrop){
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
if(weaponEquippedAkimbo){
// safety. dynaRefPRE.iClipLeft stays as it is, just enforcing that the akimbo one was dropped.
@ -1849,10 +1881,10 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
// Player is dying? Remove this weapon and drop two copies.
// Pretty simple.
// ...but we need to override how they get ammo.
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
eDrop.myInfo.iClipLeft = dynaRefPRE.iClipLeft;
eDrop.myInfo.iClipAkimboLeft = 0;
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
eDrop.myInfo.iClipLeft = dynaRefPRE.iClipAkimboLeft;
eDrop.myInfo.iClipAkimboLeft = 0;
@ -1865,7 +1897,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
}else{
// doesn't support akimbo or not akimbo? remove.
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
removeWeaponFromInventory(this, arg_weaponID);
if(!completeDrop){
playerEquipIdealSafe(this);
@ -1875,7 +1907,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
//drop away
if(!completeDrop){
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
eDrop.myInfo.iCount = 1;
eDrop.myInfo.iSlots = (*basicPS).iSlots * 1;
@ -1894,7 +1926,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
}else{
// combine them all, happens naturally.
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
removeWeaponFromInventory(this, arg_weaponID);
playerEquipIdealSafe(this);
}
@ -1902,7 +1934,7 @@ player::dropWeapon(int arg_weaponID, BOOL completeDrop){
}else{ // if((*basicPS).typeID == WEAPONDATA_TYPEID_MELEE)
eDrop = TSWorldGun::generate(this, arg_weaponID);
eDrop = CTSWorldGun::generate(this, arg_weaponID);
removeWeaponFromInventory(this, arg_weaponID);
if(!completeDrop){
playerEquipIdealSafe(this);
@ -1941,8 +1973,8 @@ player::anyAmmoPoolNonEmpty(void){
// oh.. I guess that's it.
void
player::dropAmmo(void){
//TSAmmoPack eDrop =
TSAmmoPack::generate(this);
//CTSAmmoPack eDrop =
CTSAmmoPack::generate(this);
}// dropAmmo

View File

@ -13,8 +13,10 @@
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// !!! IMPORTANT NOTE.
// NOTE - Physics_WaterMove is in pmove_water.qc instead
// !!! IMPORTANT
// Any methods starting with "Game" in here are no longer called by Nuclide.
// Most methods have been changed to player-methods instead, see much further
// down. Keeping mine as they are to be inserted as needed.
@ -264,13 +266,6 @@ player::Physics_WaterJump(void)
}
void
player::Physics_WaterMove(void)
{
base_player::Physics_WaterMove();
}
float
player::Physics_MaxSpeed(void)
{

View File

@ -14,65 +14,73 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//TAGGG - Clone of FreeHL's way, which is a clone of Nuclide's way
// (base_player::Physics_WaterMove). I'll keep this as a copy too then?
void
GamePMove_WaterMove(player target)
player::Physics_WaterMove(void)
{
if (target.movetype == MOVETYPE_NOCLIP) {
if (movetype == MOVETYPE_NOCLIP) {
return;
}
#ifdef SERVER
if (target.health < 0) {
if (health < 0) {
return;
}
/* we've just exited water */
if (target.waterlevel != 3) {
if (target.underwater_time < time) {
Sound_Play(target, CHAN_BODY, "player.gasplight");
} else if (target.underwater_time < time + 9) {
Sound_Play(target, CHAN_BODY, "player.gaspheavy");
if (waterlevel != 3) {
if (underwater_time < time) {
Sound_Play(this, CHAN_BODY, "player.gasplight");
} else if (underwater_time < time + 9) {
Sound_Play(this, CHAN_BODY, "player.gaspheavy");
}
target.underwater_time = time + 12;
} else if (target.underwater_time < time) {
underwater_time = time + 12;
} else if (underwater_time < time) {
/* we've been underwater... for too long. */
if (target.pain_time < time) {
Damage_Apply(target, world, 5, DMG_DROWN, 0);
target.pain_time = time + 1;
if (pain_time < time) {
Damage_Apply(this, world, 5, DMG_DROWN, 0);
pain_time = time + 1;
}
}
#endif
if (!target.waterlevel){
if (target.flags & FL_INWATER) {
if (!waterlevel){
if (flags & FL_INWATER) {
#ifdef SERVER
Sound_Play(target, CHAN_BODY, "player.waterexit");
Sound_Play(this, CHAN_BODY, "player.waterexit");
#endif
target.flags &= ~FL_INWATER;
flags &= ~FL_INWATER;
}
return;
}
#ifdef SERVER
if (target.watertype == CONTENT_LAVA) {
if (target.pain_time < time) {
target.pain_time = time + 0.2;
Damage_Apply(target, world, 10*target.waterlevel, DMG_BURN, 0);
if (watertype == CONTENT_LAVA) {
if (pain_time < time) {
pain_time = time + 0.2;
Damage_Apply(this, world, 10*waterlevel, DMG_BURN, 0);
}
} else if (target.watertype == CONTENT_SLIME) {
if (target.pain_time < time) {
target.pain_time = time + 1;
Damage_Apply(target, world, 4*target.waterlevel, DMG_ACID, 0);
} else if (watertype == CONTENT_SLIME) {
if (pain_time < time) {
pain_time = time + 1;
Damage_Apply(this, world, 4*waterlevel, DMG_ACID, 0);
}
}
#endif
if (!(target.flags & FL_INWATER)) {
if (!(flags & FL_INWATER)) {
#ifdef SERVER
Sound_Play(target, CHAN_BODY, "player.waterenter");
target.pain_time = 0;
Sound_Play(this, CHAN_BODY, "player.waterenter");
pain_time = 0;
#endif
target.flags |= FL_INWATER;
flags |= FL_INWATER;
}
/* we might need to apply extra-velocity to get out of water-volumes */
if (waterlevel >= 2) {
Physics_WaterJump();
}
}

View File

@ -93,8 +93,8 @@ powerupdata_basic_t* ary_powerupData[POWERUP_ID::LAST_ID];
#ifdef SERVER
class ts_powerup;
extern void powerup_linkToStruct(ts_powerup arg_entity, POWERUP_ID arg_id);
class CTSPowerUp;
extern void powerup_linkToStruct(CTSPowerUp arg_entity, POWERUP_ID arg_id);
#endif
extern void setupPowerupData(void);

View File

@ -16,9 +16,12 @@ void SharedGame_Precache(void){
//printfline("***SharedGame_Precache called***");
// good idea to have precache shared? Unsure, but it has script client and serverside
CTSPowerUp::precache();
precache_model("models/powerup.mdl");
// In FreeTS, looks like shell eject effects are precached both client & serverside
// In FreeTS, looks like shell eject effects are precached both client and serverside
// (so here in shared/precache.qc is good).
// physics-related / slow-mo?

View File

@ -0,0 +1,66 @@
void SoundPitched_Send(entity ent, int id);
void SoundPitched_Channel_Send(entity ent, int id, float chan);
#ifdef CLIENT
void SoundPitched_Receive(void);
void SoundPitched_Channel_Receive(void);
#endif
typedef enum
{
SNDP_AK47_FIRE,
SNDP_AKIMBOCOLTS_FIRE,
SNDP_BARRETTM82_FIRE,
SNDP_BENELLIM3_FIRE,
SNDP_BERETTA_FIRE,
SNDP_BERETTA_FIRE_SIL,
SNDP_CONTENDERG2_FIRE,
SNDP_DESERTEAGLE_FIRE,
SNDP_DESERTEAGLE_FIRE_SIL,
SNDP_FIVESEVEN_FIRE,
SNDP_FIVESEVEN_FIRE_SIL,
SNDP_GLOCK18_FIRE,
SNDP_GLOCK18_FIRE_SIL,
SNDP_GLOCK20_FIRE,
SNDP_GLOCK20_FIRE_SIL,
SNDP_HKPDW_FIRE,
SNDP_HKPDW_FIRE_SIL,
SNDP_KATANA_MISS,
SNDP_KATANA_MISS1,
SNDP_M4A1_FIRE,
SNDP_M4A1_FIRE_SIL,
SNDP_M16A4_FIRE,
SNDP_M60_FIRE,
SNDP_MAC10_FIRE,
SNDP_MAC10_FIRE_SIL,
SNDP_MINIUZI_FIRE,
SNDP_MINIUZI_FIRE_SIL,
SNDP_MOSSBERG500_FIRE,
SNDP_MP5K_FIRE,
SNDP_MP5K_FIRE_SIL,
SNDP_MP5SD_FIRE,
SNDP_RAGINGBULL_FIRE,
SNDP_RUGERMK1_FIRE,
SNDP_SAWEDOFF_FIRE,
SNDP_SKORPION_FIRE,
SNDP_SOCOMMK23_FIRE,
SNDP_SOCOMMK23_FIRE_SIL,
SNDP_SPAS12_FIRE,
SNDP_STEYRAUG_FIRE,
SNDP_STEYRAUG_FIRE_SIL,
SNDP_STEYRTMP_FIRE,
SNDP_STEYRTMP_FIRE_SIL,
SNDP_UMP_FIRE,
SNDP_UMP_FIRE_SIL,
SNDP_USAS12_FIRE,
SNDP_EXPLODE,
SNDP_EXPLODE1,
SNDP_EXPLODE2,
SNDP_EXPLODE3,
SNDP_EXPLODE4
} sfx_pitched_t;

View File

@ -20,61 +20,8 @@
// katana sounds except miss and miss1 are pitched normally in the
// as-is sound files.
typedef enum
{
SNDP_AK47_FIRE,
SNDP_AKIMBOCOLTS_FIRE,
SNDP_BARRETTM82_FIRE,
SNDP_BENELLIM3_FIRE,
SNDP_BERETTA_FIRE,
SNDP_BERETTA_FIRE_SIL,
SNDP_CONTENDERG2_FIRE,
SNDP_DESERTEAGLE_FIRE,
SNDP_DESERTEAGLE_FIRE_SIL,
SNDP_FIVESEVEN_FIRE,
SNDP_FIVESEVEN_FIRE_SIL,
SNDP_GLOCK18_FIRE,
SNDP_GLOCK18_FIRE_SIL,
SNDP_GLOCK20_FIRE,
SNDP_GLOCK20_FIRE_SIL,
SNDP_HKPDW_FIRE,
SNDP_HKPDW_FIRE_SIL,
SNDP_KATANA_MISS,
SNDP_KATANA_MISS1,
SNDP_M4A1_FIRE,
SNDP_M4A1_FIRE_SIL,
SNDP_M16A4_FIRE,
SNDP_M60_FIRE,
SNDP_MAC10_FIRE,
SNDP_MAC10_FIRE_SIL,
SNDP_MINIUZI_FIRE,
SNDP_MINIUZI_FIRE_SIL,
SNDP_MOSSBERG500_FIRE,
SNDP_MP5K_FIRE,
SNDP_MP5K_FIRE_SIL,
SNDP_MP5SD_FIRE,
SNDP_RAGINGBULL_FIRE,
SNDP_RUGERMK1_FIRE,
SNDP_SAWEDOFF_FIRE,
SNDP_SKORPION_FIRE,
SNDP_SOCOMMK23_FIRE,
SNDP_SOCOMMK23_FIRE_SIL,
SNDP_SPAS12_FIRE,
SNDP_STEYRAUG_FIRE,
SNDP_STEYRAUG_FIRE_SIL,
SNDP_STEYRTMP_FIRE,
SNDP_STEYRTMP_FIRE_SIL,
SNDP_UMP_FIRE,
SNDP_UMP_FIRE_SIL,
SNDP_USAS12_FIRE/*,
SNDP_EXPLODE,
SNDP_EXPLODE1,
SNDP_EXPLODE2,
SNDP_EXPLODE3,
SNDP_EXPLODE4
*/
} sfx_pitched_t;
//#define SOUNDPITCHED_SEND_ALL_DEBUG
void
@ -109,6 +56,8 @@ SoundPitched_Channel_Send(entity ent, int id, float chan)
#endif
}
#ifdef CLIENT
const string sfx_pitched_s[] =
{
@ -156,13 +105,12 @@ const string sfx_pitched_s[] =
"weapons/tmp/fire-sil.wav",
"weapons/ump/ump-fire.wav",
"weapons/ump/ump-fire-sil.wav",
"weapons/usas/usas-fire.wav"/*,
"weapons/usas/usas-fire.wav",
"explo/explode.wav",
"explo/explode1.wav",
"explo/explode2.wav",
"explo/explode3.wav",
"explo/explode4.wav"
*/
};
void
@ -177,6 +125,8 @@ SoundPitched_Receive(void)
sound(ent, CHAN_WEAPON, sfx_pitched_s[id], 1.0f, ATTN_NORM, 400, SOUNDFLAG_FOLLOW);
}
#ifndef SOUNDPITCHED_SEND_ALL_DEBUG
void
SoundPitched_Channel_Receive(void)
{
@ -188,7 +138,9 @@ SoundPitched_Channel_Receive(void)
sound(ent, chan, sfx_pitched_s[id], 1.0f, ATTN_NORM, 400, SOUNDFLAG_FOLLOW);
}
/*
#else
// ISSUE: sounds seem to play only for the entity that called for
// the message to be played from serverside. If it's a spawned entity
// (like a grenade sending itself to make the explosion sound), no player
@ -217,6 +169,7 @@ SoundPitched_Channel_Receive(void)
// sound(ent, chan, sfx_pitched_s[id], 1.0f, ATTN_NORM, 400, SOUNDFLAG_FOLLOW);
sound(self, chan, sfx_pitched_s[id], 1.0f, ATTN_NORM, 400, SOUNDFLAG_FOLLOW);
}
*/
#endif
#endif// SOUNDPITCHED_SEND_ALL_DEBUG
#endif// CLIENT

View File

@ -80,7 +80,7 @@
#endif
////////////////////////////////////////////////////////
// situational, see TSWorldGun and TSThrownProjectile.
// situational, see CTSWorldGun and CTSThrownProjectile.
// (consider unpacking, this is kinda unnecessary)
// anywhere in inventory_logic.qc still do something like that?? I forget.
#define COPYVARFROM(varName) myInfo.##varName = tempRef.##varName;

View File

@ -772,7 +772,10 @@ typedef struct{
//TODO. Is extern'ing these earlier possible?
ammodata_t* ary_ammoData[AMMO_ID::LAST_ID];
#ifdef CLIENT
shellejectdata_t* ary_shellEjectData[SHELLEJECT_ID::LAST_ID];
muzzleflashdata_t* ary_muzzleFlashData[MUZZLEFLASH_ID::LAST_ID];
#endif
//weapondata_normal_t* ary_weaponData[WEAPON_ID::LAST_ID];
//Void pointer should be fine, right? Cast to the right weapondata_ struct above (typeID tells what that is).
@ -847,7 +850,8 @@ void weapon_gun_onDrawHUD(player pl, weapondata_gun_t* basePRef, weapondynamic_t
void weapon_throwable_onDrawHUD(player pl, weapondata_throwable_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_ejectShell(int arg_shellEjectType);
void weapon_ShowMuzzleFlash(int arg_muzzleFlashTypeID);
void weapon_EjectShell(int arg_shellEjectType);
void weapon_precache(weapondata_basic_t* basePRef);
@ -948,10 +952,11 @@ int getAmmoTypeOfWeapon(int arg_weaponID);
#ifdef CLIENT
void viewEv_playShotgunInsertShellSound(void);
// TEMP DUMMY
// dummy
void w_ejectshell_pistol(void){};
void viewEv_weapon_ejectShell(void);
void viewEv_weapon_EjectShell(void);
void copyWeaponConfig(weaponconfig_weapon_t* arg_dest, weaponconfig_weapon_t* arg_src);
void copyConfig(weaponconfig_data_t* arg_dest, weaponconfig_data_t* arg_src);

View File

@ -497,8 +497,7 @@ weapon_shotgun_reload(
}
pl.isChangingIronsight = FALSE;
pl.currentZoomChoice = -1;
pl.setZoom(1.00f);
pl.resetZoom();
pl.aryNextBurstShotTime_softLength = 0;
pl.aryNextBurstShotTime_listenIndex = -1;
@ -1364,8 +1363,7 @@ weapon_gun_Reload(
}
pl.isChangingIronsight = FALSE;
pl.currentZoomChoice = -1;
pl.setZoom(1.00f);
pl.resetZoom();
pl.aryNextBurstShotTime_softLength = 0;
pl.aryNextBurstShotTime_listenIndex = -1;
pl.isReloading = TRUE;
@ -1408,8 +1406,7 @@ weapon_gun_Reload_CustomSequence(
}
pl.isChangingIronsight = FALSE;
pl.currentZoomChoice = -1;
pl.setZoom(1.00f);
pl.resetZoom();
pl.aryNextBurstShotTime_softLength = 0;
pl.aryNextBurstShotTime_listenIndex = -1;
pl.isReloading = TRUE;
@ -1455,8 +1452,7 @@ weapon_ironsight_Reload(
}
pl.isChangingIronsight = FALSE;
pl.currentZoomChoice = -1;
pl.setZoom(1.00f);
pl.resetZoom();
pl.aryNextBurstShotTime_softLength = 0;
pl.aryNextBurstShotTime_listenIndex = -1;
pl.isReloading = TRUE;
@ -1830,16 +1826,33 @@ weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t
}// weapon_throwable_onDrawHUD
void
weapon_ShowMuzzleFlash(int arg_muzzleFlashTypeID){
#ifdef CLIENT
if(arg_muzzleFlashTypeID != MUZZLEFLASH_ID::NONE){
muzzleflashdata_t* tempRef = ary_muzzleFlashData[arg_muzzleFlashTypeID];
View_ShowMuzzleflash((*tempRef).iSpritePrecacheID);
}
#else
// anything for other players to see, or will this be per animation in clientside rendering
// (player predraw) for whoever sees another player firing?
#endif
}
// Not to be confused with the clientside-only event "viewEv_weapon_ejectShell".
// 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){
void
weapon_EjectShell(int arg_shellEjectType)
{
#ifdef CLIENT
player pl = (player)self;
pl.iShellEjectType = arg_shellEjectType;
View_AddEvent(viewEv_weapon_ejectShell, 0.0f);
View_AddEvent(viewEv_weapon_EjectShell, 0.0f);
#else
// anything for the playermodel? Also only do that for all players except the
// localplayer if using a viewmodel.
@ -1848,11 +1861,14 @@ void weapon_ejectShell(int arg_shellEjectType){
#endif
}
// Precache models and the HUD icon given in FreeTS weapondata.
// Weapon sounds and anything else not in the struct shuold be precached
// in the weapon's own precache method or globally (precache.qc) if reused
// between different weapons like shell models/sounds.
void weapon_precache(weapondata_basic_t* basePRef){
void
weapon_precache(weapondata_basic_t* basePRef)
{
#ifdef SERVER
if((*basePRef).sWorldModelPath != NULL){
precache_model((*basePRef).sWorldModelPath);
@ -1886,7 +1902,9 @@ void weapon_gun_updateAmmo(player pl, weapondata_gun_t* basePRef, weapondynamic_
}
*/
// Easier way for the caller.
void weapon_gun_updateAmmo(player pl, int weaponTypeID){
void
weapon_gun_updateAmmo(player pl, int weaponTypeID)
{
if(pl.inventoryEquippedIndex != -1){
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// no need to hardcode ammo names when they're given by weapondata
@ -2110,35 +2128,6 @@ setupWeaponData(void){
ary_shotgunExtra[SHOTGUN_EXTRA_ID::SPAS12] = &weapon_spas12_shotgunExtra;
ASSIGN_AMMODATA(NONE)
ASSIGN_AMMODATA(_9X19MM)
ASSIGN_AMMODATA(_45ACP)
ASSIGN_AMMODATA(_P50AE)
ASSIGN_AMMODATA(_5P7X28)
ASSIGN_AMMODATA(_10MMAUTO)
ASSIGN_AMMODATA(_P22LR)
ASSIGN_AMMODATA(_P454CASULL)
ASSIGN_AMMODATA(_5P56NATO)
ASSIGN_AMMODATA(_7P62X39MM)
ASSIGN_AMMODATA(_50BMG)
ASSIGN_AMMODATA(_SHELLS)
ASSIGN_AMMODATA(_32ACP)
ASSIGN_AMMODATA(_7P62X51MM)
ASSIGN_SHELLEJECTDATA(NONE)
ASSIGN_SHELLEJECTDATA(_56)
ASSIGN_SHELLEJECTDATA(_556)
ASSIGN_SHELLEJECTDATA(_22)
ASSIGN_SHELLEJECTDATA(_9MM)
ASSIGN_SHELLEJECTDATA(_GENERIC)
ASSIGN_SHELLEJECTDATA(_SHOTGUN)
ASSIGN_SHELLEJECTDATA(_SHOTGUN_BLUE)
ASSIGN_SHELLEJECTDATA(_SHOTGUN_GOLD)
}//setupWeaponData
@ -2249,11 +2238,15 @@ viewEv_playShotgunInsertShellSound(void)
}
void
viewEv_weapon_ejectShell(void)
viewEv_weapon_EjectShell(void)
{
player pl = (player)pSeat->m_ePlayer;
CShellEject::generate(pl.iShellEjectType);
}//viewEv_weapon_ejectShell
// 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
CTSShellEject::generateForViewmodel(pl.iShellEjectType);
}
// also clientside only, dealing with configs

View File

@ -159,8 +159,8 @@ w_ak47_primary(void)
}
#ifdef CLIENT
View_ShowMuzzleflash(MUZZLE_SMALL);
View_AddEvent(w_ejectshell_pistol, 0.0f);
weapon_ShowMuzzleFlash(MUZZLEFLASH_ID::RIFLE);
weapon_EjectShell(SHELLEJECT_ID::_56);
#endif
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::AK47], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
@ -189,21 +189,16 @@ w_ak47_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
case -1:{
//pl.viewzoom = 32/80;
pl.setZoom(0.4f);
pl.currentZoomChoice++;
break;}
pl.iZoomLevel = (pl.iZoomLevel + 1) % 3;
switch(pl.iZoomLevel){
case 0:{
//pl.viewzoom = 13/80;
pl.setZoom(0.1625f);
pl.currentZoomChoice++;
pl.setZoom(1.00f);
break;}
case 1:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.setZoom(0.4f);
break;}
case 2:{
pl.setZoom(0.1625f);
break;}
}//END OF switch

View File

@ -182,21 +182,21 @@ w_barrettm82_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 32/80;
pl.setZoom(0.4f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 8/80;
pl.setZoom(0.10f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 1:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -254,15 +254,15 @@ w_benellim3_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 40/80;
pl.setZoom(0.5f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -185,7 +185,7 @@ w_combatknife_secondary(void)
arg_thisWeapon.forceBodygroup1Submodel = 1; //reset, new knife is not bloody.
TS_Weapons_PlaySoundDirect(pl, "weapons/knife/knife_miss.wav");
#ifdef SERVER
TSThrownProjectile::generate2(pl, arg_thisWeapon);
CTSThrownProjectile::generate2(pl, arg_thisWeapon);
#endif
}

View File

@ -182,16 +182,16 @@ w_contenderg2_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 26/80;
pl.setZoom(0.325f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -226,15 +226,15 @@ w_deserteagle_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 60/80;
pl.setZoom(0.75f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -173,14 +173,11 @@ w_glock18_primary(void)
TS_Weapons_ViewAnimation(weaponseq_glock18::shootempty, (31.0f/30.0f) );
}
#ifdef CLIENT
View_ShowMuzzleflash(MUZZLE_SMALL);
// TODO:
//weapon_showMuzzleFlash(MUZZLE_SMALL);
#endif
weapon_ejectShell(SHELLEJECT_ID::_9MM);
// TODO.
// For now using lazy HL defaults for muzzle flashes, I'll leave
// TS's own muzzle flashes, whichever ones are even used, for another time
weapon_ShowMuzzleFlash(MUZZLEFLASH_ID::SMALL);
weapon_EjectShell(SHELLEJECT_ID::_9MM);
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::GLOCK18], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);

View File

@ -189,16 +189,16 @@ w_hkpdw_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 40/80;
pl.setZoom(0.50f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -241,21 +241,21 @@ w_m16a4_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 32/80;
pl.setZoom(0.4f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 8/80;
pl.setZoom(0.10f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 1:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -246,16 +246,16 @@ w_m4a1_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 26/80;
pl.setZoom(0.325f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -27,7 +27,7 @@ void weapon_m61grenade_spawnProjectile(player pl, weapondynamic_t arg_thisWeapon
vector vGrenadeOrigin = (pl.origin + pl.view_ofs) + (v_forward * 16);
vector vDir = aim ( pl, 100000 );
TSGrenadeProjectile::generate(pl, vGrenadeOrigin, vDir, v_forward, WEAPON_ID::M61GRENADE);
TS_GrenadeProjectile::generate(pl, vGrenadeOrigin, vDir, v_forward, WEAPON_ID::M61GRENADE);
}
#endif
@ -239,7 +239,7 @@ w_m61grenade_precache(void)
weapon_precache(ary_weaponData[WEAPON_ID::M61GRENADE]);
#ifdef SERVER
// grenade-bounce and explode sounds are precached in
// TSGrenadeProjectile::precache and fx_ts_explosion_grenade_Init respectively
// TS_GrenadeProjectile::precache and fx_ts_explosion_grenade_Init respectively
//precache_sound("weapons/gr_pull.wav");
//precache_sound("weapons/gr_safe.wav");
#else

View File

@ -230,16 +230,16 @@ w_mp5k_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 32/80;
pl.setZoom(0.40f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -205,16 +205,16 @@ w_mp5sd_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 32/80;
pl.setZoom(0.40f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -178,16 +178,16 @@ w_ragingbull_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 40/80;
pl.setZoom(0.5f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -177,7 +177,7 @@ w_sealknife_secondary(void)
arg_thisWeapon.forceBodygroup1Submodel = 1; //reset, new knife is not bloody.
TS_Weapons_PlaySoundDirect(pl, "weapons/knife/knife_miss.wav");
#ifdef SERVER
TSThrownProjectile::generate2(pl, arg_thisWeapon);
CTSThrownProjectile::generate2(pl, arg_thisWeapon);
#endif
}

View File

@ -181,16 +181,16 @@ w_steyraug_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 40/80;
pl.setZoom(0.5f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -191,16 +191,16 @@ w_ump_secondary(void)
if(arg_thisWeapon.iBitsUpgrade & BITS_WEAPONOPT_SCOPE){
// toggle through the zoom.
switch(pl.currentZoomChoice){
switch(pl.iZoomLevel){
case -1:{
//pl.viewzoom = 40/80;
pl.setZoom(0.50f);
pl.currentZoomChoice++;
pl.iZoomLevel++;
break;}
case 0:{
//pl.viewzoom = 0;
pl.setZoom(1.00f);
pl.currentZoomChoice = -1;
pl.iZoomLevel = -1;
break;}
}//END OF switch

View File

@ -1,7 +1,11 @@
// And yes, pitch is a decimal, 0.5 to 4.0 is likely the allowed range
// Unfortuantely this isn't quite there, the greatest pitch mod allowed
// this way is 200%. Strange, have to use sound_pitched.qc instead
//
fx.ts_explosion_grenade
{
pitch 400
shakes 2.7
pitch 4
shakes 3.5
sample explo/explode.wav
sample explo/explode1.wav
sample explo/explode2.wav