758 lines
18 KiB
C++
758 lines
18 KiB
C++
#include "q_shared.h"
|
|
#include "..\ghoul\ighoul.h"
|
|
#include "w_public.h"
|
|
#include "w_types.h"
|
|
#include "w_weapons.h"
|
|
#include "w_utils.h"
|
|
#include "player.h"
|
|
#include "../gamecpp/game.h"
|
|
|
|
extern player_com_import_t picom;
|
|
extern player_cl_import_t picl;
|
|
extern player_sv_import_t pisv;
|
|
|
|
extern int isClient;
|
|
extern int fireEvent;
|
|
extern int altfireEvent;
|
|
|
|
// noiserad does NOT belong here...
|
|
|
|
attackInfoExtra_t attacks[] =
|
|
{
|
|
//ammo noiseRad waver waverMax kickamount AttackID
|
|
{AMMO_NONE, 0.0, 0.0, 0.0, 0.0, ATK_NOTHING}, //SFW_EMPTYSLOT
|
|
{AMMO_KNIFE, 0.0, 0.0, 0.0, 0.0, ATK_KNIFE}, //SFW_KNIFE,
|
|
{AMMO_KNIFE, 0.0, 0.0, 0.0, 0.0, ATK_KNIFE_ALT}, //SFW_KNIFE,
|
|
{AMMO_44, 900.0, 0.2, 0.8, 5.0, ATK_PISTOL2}, //SFW_PISTOL2,
|
|
{AMMO_9MM, 600.0, 0.3, 1.5, 1.0, ATK_PISTOL1}, //SFW_PISTOL1,
|
|
{AMMO_9MM, 10.0, 0.6, 3.5, 0.0, ATK_MACHINEPISTOL}, //SFW_MACHINEPISTOL,
|
|
{AMMO_556, 800.0, 0.4, 1.8, 0.0, ATK_ASSAULTRIFLE}, //SFW_ASSAULTRIFLE,
|
|
{AMMO_556, 0.0, 0.0, 0.0, 2.0, ATK_SNIPER}, //SFW_SNIPER, ->sniper rifle
|
|
{AMMO_NONE, 0.0, 0.0, 0.0, 0.0, ATK_SNIPER_ALT}, //SFW_SNIPER, ->sniper rifle
|
|
{AMMO_SLUG, 1200.0, 1.5, 1.5, 4.0, ATK_AUTOSHOTGUN}, //SFW_AUTOSHOTGUN, ->shotgun
|
|
{AMMO_SLUG, 0.0, 0.0, 0.0, 4.0, ATK_AUTOSHOTGUN_ALT}, //SFW_AUTOSHOTGUN, ->shotgun
|
|
{AMMO_SHELLS, 1200.0, 0.0, 0.0, 5.0, ATK_SHOTGUN}, //SFW_SHOTGUN, ->shotgun
|
|
{AMMO_556, 1500.0, 0.1, 0.4, 0.0, ATK_MACHINEGUN}, //SFW_MACHINEGUN, -> machinegun
|
|
{AMMO_556, 500.0, 0.0, 0.0, 0.0, ATK_MACHINEGUN_ALT}, //SFW_MACHINEGUN, -> machinegun
|
|
{AMMO_ROCKET, 0.0, 0.0, 0.0, 0.0, ATK_ROCKET}, //SFW_ROCKET, -> rocketlauncher
|
|
{AMMO_ROCKET, 0.0, 0.0, 0.0, 0.0, ATK_ROCKET_ALT}, //SFW_ROCKET, -> rocketlauncher
|
|
{AMMO_MWAVE, 0.0, 0.0, 0.0, 0.0, ATK_MICROWAVE}, //SFW_MICROWAVEPULSE,
|
|
{AMMO_MWAVE, 0.0, 0.0, 0.0, 0.0, ATK_MICROWAVE_ALT}, //SFW_MICROWAVEPULSE,
|
|
{AMMO_FTHROWER, 0.0, 0.0, 0.0, 0.0, ATK_FLAMEGUN}, //SFW_FLAMETHROWER,
|
|
{AMMO_FTHROWER, 0.0, 0.0, 0.0, 0.0, ATK_FLAMEGUN_ALT}, //SFW_FLAMETHROWER,
|
|
};
|
|
|
|
WeapSoundCallBack theWeapSoundCallback;
|
|
GunFireCallBack theGunFireCallback;
|
|
AltfireCallBack theAltfireCallback;
|
|
EOSCallBack theEOSCallback;
|
|
KnifeCleanCallBack theKnifeCleanCallback;
|
|
MinimiReloadCallBack theMinimiReloadCallback;
|
|
EffectCallBack theEffectCallback;
|
|
|
|
weaponInfoExtra_t extraInfo[] =
|
|
{ // name slotsNeeded clipsize attack1 attack2
|
|
{"", 0, -1, &attacks[0], &attacks[0]}, //SFW_EMPTYSLOT
|
|
{"Knife", 0, 0, &attacks[1], &attacks[2]}, //SFW_KNIFE,
|
|
{"Pistol2", 1, 9, &attacks[3], &attacks[0]}, //SFW_PISTOL2,
|
|
{"Pistol1", 1, 18, &attacks[4], &attacks[0]}, //SFW_PISTOL1,
|
|
{"MPistol", 2, 32, &attacks[5], &attacks[0]}, //SFW_MACHINEPISTOL,
|
|
{"Assaultrifle", 2, 40, &attacks[6], &attacks[0]}, //SFW_ASSAULTRIFLE,
|
|
{"SniperRifle", 2, 6, &attacks[7], &attacks[8]}, //SFW_SNIPER, ->sniper rifle
|
|
{"Autoshotgun", 2, 10, &attacks[9], &attacks[10]}, //SFW_AUTOSHOTGUN, ->shotgun
|
|
{"Shotgun", 2, 8, &attacks[11], &attacks[0]}, //SFW_SHOTGUN, ->shotgun
|
|
{"Machinegun", 2, 40, &attacks[12], &attacks[13]}, //SFW_MACHINEGUN, -> machinegun
|
|
{"Rocket", 3, 4, &attacks[14], &attacks[15]}, //SFW_ROCKET, -> rocketlauncher
|
|
{"MPG", 3, 30, &attacks[16], &attacks[17]}, //SFW_MICROWAVEPULSE,
|
|
{"Flamegun", 3, 60, &attacks[18], &attacks[19]}, //SFW_FLAMETHROWER,
|
|
{"Hurthand", 0, 0, &attacks[0], &attacks[0]}, //SFW_HURTHAND,
|
|
{"Throwhand", 0, 0, &attacks[0], &attacks[0]}, //SFW_THROWHAND,
|
|
};
|
|
|
|
weaponInfo_c noweap(&extraInfo[0]);
|
|
knifeInfo knife(&extraInfo[1]);
|
|
pistol2Info eagle(&extraInfo[2]);
|
|
pistol1Info glock(&extraInfo[3]);
|
|
machinePistolInfo ingram(&extraInfo[4]);
|
|
assaultRifleInfo hk53(&extraInfo[5]);
|
|
sniperInfo sig(&extraInfo[6]);
|
|
autoshotgunInfo jhammer(&extraInfo[7]);
|
|
shotgunInfo spas(&extraInfo[8]);
|
|
machinegunInfo minimi(&extraInfo[9]);
|
|
rocketInfo m202a2(&extraInfo[10]);
|
|
microInfo micro(&extraInfo[11]);
|
|
flamegunInfo fthrow(&extraInfo[12]);
|
|
hurthandInfo hhand(&extraInfo[13]);
|
|
throwhandInfo thand(&extraInfo[14]);
|
|
|
|
weaponInfo_c *weapInfo[SFW_NUM_WEAPONS] =
|
|
{
|
|
&noweap,
|
|
&knife,
|
|
&eagle,
|
|
&glock,
|
|
&ingram,
|
|
&hk53,
|
|
&sig,
|
|
&jhammer,
|
|
&spas,
|
|
&minimi,
|
|
&m202a2,
|
|
µ,
|
|
&fthrow,
|
|
&hhand,
|
|
&thand,
|
|
};
|
|
|
|
weaponInfo_c::weaponInfo_c(weaponInfoExtra_t *w)
|
|
{
|
|
clip = w->clipsize;
|
|
slotsNeeded = w->slotsNeeded;
|
|
ammoType[0] = w->a1->ammoType;
|
|
ammoType[1] = w->a2->ammoType;
|
|
noiseRad[0] = w->a1->noiseRad;
|
|
noiseRad[1] = w->a2->noiseRad;
|
|
waver[0] = w->a1->waver;
|
|
waver[1] = w->a2->waver;
|
|
waverMax[0] = w->a1->waverMax;
|
|
waverMax[1] = w->a2->waverMax;
|
|
|
|
kick[0] = w->a1->kickAmount;
|
|
kick[1] = w->a2->kickAmount;
|
|
|
|
strcpy(modelName, w->name);
|
|
|
|
atkID[0] = w->a1->id;
|
|
atkID[1] = w->a2->id;
|
|
|
|
soundToken = NULL_GhoulID;
|
|
}
|
|
|
|
int weaponInfo_c::useAmmo1(sharedEdict_t &ent, int *skipIdle)
|
|
{
|
|
weapon_c *weap = inven(ent)->getCurWeapon();
|
|
|
|
if(getAmmoType(0) == AMMO_NONE)
|
|
return 1;
|
|
|
|
if(!inven(ent)->rulesDoWeaponsUseAmmo())
|
|
return 1;
|
|
|
|
if(!weap->getClip())
|
|
{
|
|
if(inven(ent)->rulesIsWeaponReloadAutomatic())
|
|
inven(ent)->reload();
|
|
else
|
|
inven(ent)->dryfire();
|
|
|
|
return 0;
|
|
}
|
|
|
|
weap->setClip(weap->getClip() - 1);
|
|
return 1;
|
|
}
|
|
|
|
int weaponInfo_c::useAmmo2(sharedEdict_t &ent, int *skipIdle)
|
|
{
|
|
weapon_c *weap = inven(ent)->getCurWeapon();
|
|
|
|
if(getAmmoType(1) == AMMO_NONE)
|
|
return 1;
|
|
|
|
if(!inven(ent)->rulesDoWeaponsUseAmmo())
|
|
return 1;
|
|
|
|
if(!weap->getClip())
|
|
{
|
|
if(inven(ent)->rulesIsWeaponReloadAutomatic())
|
|
inven(ent)->reload();
|
|
else
|
|
inven(ent)->dryfire();
|
|
|
|
return 0;
|
|
}
|
|
|
|
weap->setClip(weap->getClip() - 1);
|
|
return 1;
|
|
}
|
|
|
|
int weaponInfo_c::checkReloadAtEOS(sharedEdict_t &ent)
|
|
{
|
|
if((wAnim(ent)->getAnimType() == WANIM_FIRE)||(wAnim(ent)->getAnimType() == WANIM_ALTFIRE))
|
|
{
|
|
if(!inven(ent)->rulesDoWeaponsUseAmmo())
|
|
return 0;
|
|
|
|
if(!inven(ent)->getCurClip())
|
|
{
|
|
if(inven(ent)->rulesIsWeaponReloadAutomatic())
|
|
{
|
|
inven(ent)->reload();
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void weaponInfo_c::precacheResources()
|
|
{
|
|
if(getAtkID(0) != ATK_NOTHING)
|
|
{
|
|
pisv.CacheAttack((int)getAtkID(0));
|
|
}
|
|
if(getAtkID(1) != ATK_NOTHING)
|
|
{
|
|
pisv.CacheAttack((int)getAtkID(1));
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
weapon_c::weapon_c(void)
|
|
{
|
|
curClip = 0;
|
|
cannotFire = 0;
|
|
type = SFW_EMPTYSLOT;
|
|
}
|
|
|
|
weapon_c::weapon_c(weaponInfo_c *wInfo)
|
|
{
|
|
curClip = getWeaponInfo()->getClipSize();
|
|
cannotFire = 0;
|
|
type = SFW_EMPTYSLOT;
|
|
}
|
|
|
|
void weapon_c::setType(int newType, int startWithFullClip)
|
|
{
|
|
type = newType;
|
|
|
|
if(startWithFullClip == -1)
|
|
{
|
|
curClip = getWeaponInfo()->getClipSize();
|
|
}
|
|
else if(startWithFullClip)
|
|
{
|
|
curClip = startWithFullClip;
|
|
}
|
|
else
|
|
{
|
|
curClip = 0;
|
|
}
|
|
}
|
|
|
|
int weapon_c::handleAmmo(sharedEdict_t &ent, int mode, int *skipIdle)
|
|
{
|
|
return((mode) ? getWeaponInfo()->useAmmo2(ent, skipIdle) : getWeaponInfo()->useAmmo1(ent, skipIdle));
|
|
}
|
|
|
|
weaponInfo_c *weapon_c::getWeaponInfo(void)
|
|
{
|
|
return weapInfo[type];
|
|
}
|
|
|
|
int weapon_c::canSelect(sharedEdict_t &ent,int withNoAmmo)
|
|
{
|
|
if(type == SFW_EMPTYSLOT)
|
|
return 0;
|
|
|
|
if(isClient)
|
|
{
|
|
// Client is always able to select any weapon.
|
|
return(1);
|
|
}
|
|
|
|
if(!withNoAmmo)
|
|
{
|
|
if((curClip == 0)&&(inven(ent)->rulesDoWeaponsUseAmmo()))
|
|
{
|
|
if((inven(ent)->hasAmmo(weapInfo[type]->getAmmoType(0)) == 0)&&(!weapInfo[type]->canSelectWithNoAmmo()))
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------
|
|
//
|
|
// wrapper funcs
|
|
//
|
|
//---------------------------------------------------------------------------------------------
|
|
|
|
void Fire(sharedEdict_t &sh, edict_t &ent, inven_c &inven)
|
|
{
|
|
if(!inven.getCurWeapon()->getWeaponInfo()->atMomentOfFire(sh))
|
|
return;
|
|
|
|
if(wAnim(sh)->getAnimType() != WANIM_FIRE)
|
|
return;
|
|
|
|
if(!isClient)
|
|
pisv.FireHelper(sh, ent, inven);
|
|
else
|
|
picl.FireHelper(sh, ent, inven);
|
|
|
|
sh.weaponkick_angles[PITCH]=-(inven.getCurWeapon()->getWeaponInfo()->getKick(0));
|
|
}
|
|
|
|
void Altfire(sharedEdict_t &sh, edict_t &ent, inven_c &inven)
|
|
{
|
|
if(!inven.getCurWeapon()->getWeaponInfo()->atMomentOfFire(sh))
|
|
return;
|
|
|
|
if(wAnim(sh)->getAnimType() != WANIM_ALTFIRE)
|
|
return;
|
|
|
|
if(!isClient)
|
|
pisv.AltfireHelper(sh, ent, inven);
|
|
else
|
|
picl.AltfireHelper(sh, ent, inven);
|
|
|
|
sh.weaponkick_angles[PITCH]=-(inven.getCurWeapon()->getWeaponInfo()->getKick(1));
|
|
}
|
|
|
|
void EOS(sharedEdict_t &ent, inven_c &inven)
|
|
{
|
|
if(inven.getCurWeapon()->getWeaponInfo()->handleEOS(ent))
|
|
{
|
|
// Special end of sequence stuff handled by weapon specific EOS.
|
|
return;
|
|
}
|
|
|
|
if(inven.getCurWeapon()->getWeaponInfo()->checkReloadAtEOS(ent))
|
|
{
|
|
// Do we need to reload now?
|
|
return;
|
|
}
|
|
|
|
switch(wAnim(ent)->getAnimType())
|
|
{
|
|
case WANIM_NORMAL:
|
|
case WANIM_RELOAD:
|
|
inven.idle();
|
|
break;
|
|
|
|
case WANIM_FIRE:
|
|
if(!(inven.pendingCommand()))
|
|
{
|
|
qboolean doAttack=false;
|
|
|
|
if(!isClient)
|
|
{
|
|
if(!inven.isClientPredicting())
|
|
{
|
|
if(ent.attack)
|
|
doAttack=true;
|
|
}
|
|
else
|
|
{
|
|
if((inven.getCurWeaponID()==SFW_FLAMEGUN)||
|
|
(inven.getCurWeaponID()==SFW_KNIFE)||
|
|
(inven.getCurWeaponID()==SFW_MICROWAVEPULSE))
|
|
{
|
|
// Yuck!! Sigh!!
|
|
|
|
if(ent.attack)
|
|
doAttack=true;
|
|
}
|
|
else
|
|
{
|
|
if(pisv.getFireEvent(inven.getOwner()->edict))
|
|
doAttack=true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(ent.attack)
|
|
doAttack=true;
|
|
}
|
|
|
|
if(doAttack)
|
|
{
|
|
inven.getAnimInfo()->incFireLoop();
|
|
int skipIdle = 0;
|
|
if(!inven.getCurWeapon()->handleAmmo(ent, 0, &skipIdle))
|
|
{
|
|
if(!skipIdle)
|
|
{
|
|
inven.idle();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(!isClient)
|
|
{
|
|
if(inven.isClientPredicting())
|
|
{
|
|
if((inven.getCurWeaponID()==SFW_FLAMEGUN)||
|
|
(inven.getCurWeaponID()==SFW_KNIFE)||
|
|
(inven.getCurWeaponID()==SFW_ASSAULTRIFLE)||
|
|
(inven.getCurWeaponID()==SFW_MACHINEPISTOL)||
|
|
(inven.getCurWeaponID()==SFW_MICROWAVEPULSE))
|
|
{
|
|
// Yuck!! Sigh!!
|
|
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getFireSeq(ent),
|
|
inven.getCurWeapon()->getWeaponInfo()->getLoopType());
|
|
}
|
|
else
|
|
{
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getFireSeq(ent),
|
|
inven.getCurWeapon()->getWeaponInfo()->getLoopType(),
|
|
pisv.getFireEvent(inven.getOwner()->edict));
|
|
}
|
|
|
|
pisv.clearFireEvent(inven.getOwner()->edict);
|
|
}
|
|
else
|
|
{
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getFireSeq(ent),
|
|
inven.getCurWeapon()->getWeaponInfo()->getLoopType());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getFireSeq(ent),
|
|
inven.getCurWeapon()->getWeaponInfo()->getLoopType());
|
|
|
|
fireEvent=1;
|
|
}
|
|
|
|
// Some weapons don't just loop their anim.
|
|
inven.getCurWeapon()->getWeaponInfo()->handleFireLoop(ent);
|
|
|
|
return;
|
|
}
|
|
}
|
|
inven.getAnimInfo()->clearFireLoop();
|
|
inven.idle();
|
|
break;
|
|
|
|
case WANIM_ALTFIRE:
|
|
if(!inven.pendingCommand())
|
|
{
|
|
qboolean doAltAttack=false;
|
|
|
|
if(!isClient)
|
|
{
|
|
if(!inven.isClientPredicting())
|
|
{
|
|
if(ent.altattack)
|
|
doAltAttack=true;
|
|
}
|
|
else
|
|
{
|
|
if(pisv.getAltfireEvent(inven.getOwner()->edict))
|
|
doAltAttack=true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(ent.altattack)
|
|
doAltAttack=true;
|
|
}
|
|
|
|
if(doAltAttack)
|
|
{
|
|
inven.getAnimInfo()->incFireLoop();
|
|
int skipIdle = 0;
|
|
if(!inven.getCurWeapon()->handleAmmo(ent, 1, &skipIdle))
|
|
{
|
|
if(!skipIdle)
|
|
{
|
|
inven.idle();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(!isClient)
|
|
{
|
|
if(inven.isClientPredicting())
|
|
{
|
|
if(inven.getCurWeaponID()==SFW_ROCKET)
|
|
{
|
|
// Yuck!! Sigh!!
|
|
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getAltFireSeq(ent),
|
|
IGhoulInst::Hold);
|
|
}
|
|
else
|
|
{
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getAltFireSeq(ent),
|
|
IGhoulInst::Hold,
|
|
pisv.getAltfireEvent(inven.getOwner()->edict));
|
|
}
|
|
|
|
pisv.clearAltfireEvent(inven.getOwner()->edict);
|
|
}
|
|
else
|
|
{
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getAltFireSeq(ent),
|
|
IGhoulInst::Hold);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RunVWeapAnim(&ent,
|
|
inven.getCurWeapon()->getWeaponInfo()->getAltFireSeq(ent),
|
|
IGhoulInst::Hold);
|
|
|
|
altfireEvent=1;
|
|
}
|
|
|
|
// Some weapons don't just loop their anim!
|
|
inven.getCurWeapon()->getWeaponInfo()->handleAltfireLoop(ent);
|
|
|
|
return;
|
|
}
|
|
}
|
|
inven.getAnimInfo()->clearFireLoop();
|
|
inven.idle();
|
|
break;
|
|
|
|
case WANIM_PUTAWAY:
|
|
// Set new weapon to take out.
|
|
inven.setPendingChange();
|
|
break;
|
|
|
|
case WANIM_LOSE:
|
|
inven.idle();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
bool WeapSoundCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
if(isClient)
|
|
picl.WeapSoundHelper(data);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GunFireCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
Fire(*ent, *ent->edict, *inv);
|
|
|
|
if (data && *((char *)data)=='1')
|
|
{ // Use ammo during this fire.
|
|
if (!inv->getCurWeapon()->getWeaponInfo()->useAmmo1(*ent))
|
|
{
|
|
EOS(*ent, *inv);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AltfireCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
Altfire(*ent, *ent->edict, *inv);
|
|
return true;
|
|
}
|
|
|
|
bool EOSCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
EOS(*ent, *inv);
|
|
return true;
|
|
}
|
|
|
|
bool KnifeCleanCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
inv->getCurWeapon()->getWeaponInfo()->handleSpecialNotes((char *)data, *ent);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MinimiReloadCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
inv->getCurWeapon()->getWeaponInfo()->handleSpecialNotes((char *)data, *ent);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool EffectCallBack::Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
inven_c *inv = (inven_c *)user;
|
|
sharedEdict_t *ent = inv->getOwner();
|
|
|
|
if(isClient)
|
|
picl.WeaponEffectHelper(data);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
class EffectPrecacheCallBack: public IGhoulCallBack
|
|
{
|
|
public:virtual bool Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
char effectstr[256], *effectname;
|
|
|
|
strcpy(effectstr, (char *)data);
|
|
effectname = strtok(effectstr, " ");
|
|
pisv.EffectIndex(effectname);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
EffectPrecacheCallBack effectPrecacher;
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
class SoundPrecacheCallBack: public IGhoulCallBack
|
|
{
|
|
public:virtual bool Execute(IGhoulInst *me,void *user,float now,const void *data)
|
|
{
|
|
char buffer[256], soundname[256], *soundtok, *numtok;
|
|
int i,c;
|
|
|
|
strcpy(soundname, (char *)data);
|
|
soundtok = strtok(soundname, " ");
|
|
numtok = strtok(NULL, " ");
|
|
if (!numtok)
|
|
{
|
|
c=0;
|
|
}
|
|
else
|
|
{
|
|
c=atoi(numtok);
|
|
}
|
|
|
|
if (c>0)
|
|
{
|
|
for (i=1; i<=c; i++)
|
|
{
|
|
picom.Com_Sprintf(buffer, sizeof(buffer), "%s%d.wav", soundtok, i);
|
|
pisv.SoundIndex(buffer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
picom.Com_Sprintf(buffer, sizeof(buffer), "%s.wav", soundtok);
|
|
pisv.SoundIndex(buffer);
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
SoundPrecacheCallBack soundPrecacher;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void W_UncacheViewWeaponModels(void)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < SFW_NUM_WEAPONS; i++)
|
|
{
|
|
if(weapInfo[i]->getGhoulObj())
|
|
{
|
|
weapInfo[i]->setGhoulObj(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void W_PrecacheViewWeaponModels(int types)
|
|
{
|
|
// types is a bitflag of all the weapon types that should be precached
|
|
|
|
char buffer[256];
|
|
|
|
for(int i = SFW_EMPTYSLOT + 1; i < SFW_NUM_WEAPONS; i++)
|
|
{
|
|
if(!(types & (1<<i)))continue;
|
|
|
|
#ifdef _OEM_
|
|
if((i == SFW_MACHINEPISTOL)||(i == SFW_AUTOSHOTGUN)||(i == SFW_MACHINEGUN)
|
|
|| (i == SFW_ROCKET) || (i == SFW_MICROWAVEPULSE) || (i == SFW_FLAMEGUN))
|
|
{ // none of these in the oem
|
|
continue;
|
|
}
|
|
#endif
|
|
#ifdef _DEMO_
|
|
if((i == SFW_MACHINEPISTOL)||(i == SFW_AUTOSHOTGUN)||(i == SFW_MACHINEGUN)
|
|
|| (i == SFW_MICROWAVEPULSE) || (i == SFW_FLAMEGUN))
|
|
{ // none of these in the demo
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
picom.Com_Sprintf(buffer, sizeof(buffer), "Weapon/Inview/%s", extraInfo[i].name);
|
|
|
|
IGhoulObj *obj;
|
|
|
|
if(weapInfo[i]->getGhoulObj())continue;//only need to precache if this weapon isn't already loaded, of course
|
|
|
|
obj = ((IGhoul *)pisv.GetGhoul())->NewObj();
|
|
|
|
if(!obj)
|
|
{
|
|
// This is real bad - should not happen right?
|
|
|
|
assert(obj);
|
|
continue;
|
|
}
|
|
|
|
picom.RegisterGSQSequences(buffer, extraInfo[i].name, obj);
|
|
obj->RegisterEverything();
|
|
obj->PreCache(picom.ghl_specular->value>0.0f);
|
|
|
|
// Precache all the weapon sounds.
|
|
|
|
GhoulID id = obj->FindNoteToken("sound");
|
|
|
|
if(id)
|
|
{
|
|
obj->FireAllNoteCallBacks(&soundPrecacher,id);
|
|
}
|
|
|
|
// Precache all effect calls.
|
|
|
|
id = obj->FindNoteToken("effect");
|
|
|
|
if(id)
|
|
{
|
|
obj->FireAllNoteCallBacks(&effectPrecacher,id);
|
|
}
|
|
|
|
// Precache all other resources.
|
|
|
|
weapInfo[i]->setGhoulObj(obj);
|
|
weapInfo[i]->precacheResources();
|
|
}
|
|
}
|