PDA

View Full Version : Question about weapon scripts



Zorbos
28-01-2016, 03:35 AM
I was fiddling with some of the HLSP weapon scripts (weapon_hlcrowbar specifically) and noticed that my custom weapons are unselectable through the HUD. They actually work perfectly fine, but I just can't use my number keys or the scrollwheel to equip them. The only way to do it is to drop a weapon and force it to switch.

My first guess was that it was stemming from this part of the code:


int GetItemInfo( ItemInfo& out info )
{
info.iMaxAmmo1 = -1;
info.iMaxAmmo2 = -1;
info.iMaxClip = WEAPON_NOCLIP;
info.iSlot = 0;
info.iPosition = 2;
info.iWeight = 0;
return 1;
}

Is it something to do with info.iSlot and info.iPosition? I tried some different values but no dice. Or is this handled from another part of the code altogether? I'm sure this is a really easy answer, but I'm pretty new with scripting/coding in general. Just trying to get the hang of AS by modifying some of the existing scripts and seeing the results it produces.

Solokiller
28-01-2016, 06:05 AM
The game currently cannot handle multiple weapons using the same position. Slot 0, position 2 is the wrench.
Also make sure there is a sprite defined for the weapon so the HUD can load it.

S. H. Lynx
28-01-2016, 07:28 AM
The game currently cannot handle multiple weapons using the same position. Slot 0, position 2 is the wrench.
Also make sure there is a sprite defined for the weapon so the HUD can load it.

Is this the reason why we can't create server-specific weapon mods?

Solokiller
28-01-2016, 09:29 AM
That's only one of the problems.
There is a maximum of 64 weapons that can be networked, so having plugins use up all of the IDs would break maps if they had their own custom weapons.
There's no client side prediction, making weapons appear laggy. When we do get that implemented, plugins won't be able to use it anyway, because they're server side only.

Also, plugins can't define custom entities of any kind because their lifetime isn't bound to the current map like a map script is. Even if we did add that, having to support weapons defined in many different modules would cause even more problems.
One plugin would define weapon_m4a1, using a new ammo type. Another plugin would define its own weapon_m4a1, but using a different ammo type. Which plugin gets to use their weapon, and which ammo type will it be? What happens when 2 plugins define an ammo type with the same name, but with different settings?
What happens when the plugin that doesn't get to use its version tries to create it? What happens when it tries to access its class, defined in the plugin?
The list of problems goes on really. When you solve one problem, you create another.

Plugins can't use it, and they will never be able to. Map authors can define their own weapons, and define the gameplay as they see fit. Plugins cannot and will not be allowed to change that.

Additionally, in case anybody was thinking of trying it, Metamod's server side weapon support no longer works. It relied on the weapons bitmask, which is no longer used. It was limiting the number of weapons to 32, and since we already used most of those 32 IDs, we had no way of continuing to use it.

All that bitmask does now is tell clients whether the player has a suit or not (it's weapon ID 32). Please don't mess with that, use CBasePlayer's HasSuit and SetHasSuit methods. We might change that at some point in the future, so don't go writing scripts that could break.

EDIT: If there is enough demand for it, we'll attempt to implement custom entities for plugins. If we can get weapons to work properly, they'll be allowed, IF the map script isn't against it. We'll add the option for the map script to block it, to prevent maps from being unbalanced due to plugins that allow weapons to be given freely, e.g. a buy plugin.

Zorbos
29-01-2016, 02:45 AM
Thanks for all the info Solokiller.
I got the weapons to show up on the HUD and they don't override the SC weapons :)

I am having a different issue now though. Sometimes when my Crowbar gibs enemies, I crash and get the error "SV_ModelIndex: Model 0 not precached". I tried it many times to make sure it only happens when I gib enemies and it's definitely the case. Although it doesn't crash EVERY time something gibs, just sometimes..

Any idea what could be causing this?

Solokiller
29-01-2016, 05:41 AM
That error means that you're setting an entity's model to the name "0", and it isn't precached. Show me your script so i can see if the problem is on your end. If not, it might be a problem in the map, or the game itself.

Zorbos
29-01-2016, 11:46 AM
That's strange. I know there isn't anything in the script itself that's setting a models name to 0... but maybe I missed something. I loaded it up on stadium4 and tried it and I haven't crashed yet, so maybe its the map? But I don't have anything in the map that tries to load a model named 0 either.. strange indeed.

Here's my script:

// Afraid of Monsters: Director's Cut Script
// Weapon Script: Axe
// Author: Zorbos

enum axe_e
{
AXE_IDLE = 0,
AXE_DRAW,
AXE_HOLSTER,
AXE_ATTACK1HIT,
AXE_ATTACK1MISS,
AXE_ATTACK2MISS,
AXE_ATTACK2HIT,
AXE_ATTACK3MISS,
AXE_ATTACK3HIT
};

class weapon_dcaxe : ScriptBasePlayerWeaponEntity
{
int m_iSwing;
TraceResult m_trHit;

void Spawn()
{
self.Precache();
g_EntityFuncs.SetModel( self, self.GetW_Model( "models/AoMDC/weapons/axe/w_axe.mdl") );
self.m_iClip = -1;
self.m_flCustomDmg = self.pev.dmg;

self.FallInit();// get ready to fall down.
}

void Precache()
{
self.PrecacheCustomModels();

g_Game.PrecacheModel( "models/AoMDC/weapons/axe/v_axe.mdl" );
g_Game.PrecacheModel( "models/AoMDC/weapons/axe/w_axe.mdl" );
g_Game.PrecacheModel( "models/AoMDC/weapons/axe/p_axe.mdl" );

g_SoundSystem.PrecacheSound( "AoMDC/weapons/axe/axe_hit.wav" );
g_SoundSystem.PrecacheSound( "AoMDC/weapons/axe/axe_hitbody.wav" );
g_SoundSystem.PrecacheSound( "AoMDC/weapons/axe/axe_swing.wav" );
}

int GetItemInfo( ItemInfo& out info )
{
info.iMaxAmmo1 = -1;
info.iMaxAmmo2 = -1;
info.iMaxClip = WEAPON_NOCLIP;
info.iSlot = 0;
info.iPosition = 7;
info.iWeight = 0;
return 1;
}

BOOL Deploy()
{
return self.DefaultDeploy( self.GetV_Model( "models/AoMDC/weapons/axe/v_axe.mdl" ), self.GetP_Model( "models/AoMDC/weapons/axe/p_axe.mdl" ), AXE_ATTACK3MISS, "crowbar" );
}

void Holster( int skiplocal /* = 0 */ )
{
self.m_fInReload = FALSE;// cancel any reload in progress.

self.m_pPlayer.m_flNextAttack = g_WeaponFuncs.WeaponTimeBase() + 0.5;

self.m_pPlayer.pev.viewmodel = 0;
}

void PrimaryAttack()
{
if( Swing( 1 ) == FALSE )
{
SetThink( ThinkFunction( this.SwingAgain ) );
self.pev.nextthink = g_Engine.time + 0.1;
}
}

void Smack()
{
g_WeaponFuncs.DecalGunshot( m_trHit, BULLET_PLAYER_CROWBAR );
}


void SwingAgain()
{
Swing( 0 );
}

int Swing( int fFirst )
{
int fDidHit = FALSE;

TraceResult tr;

Math.MakeVectors( self.m_pPlayer.pev.v_angle );
Vector vecSrc = self.m_pPlayer.GetGunPosition();
Vector vecEnd = vecSrc + g_Engine.v_forward * 32;

g_Utility.TraceLine( vecSrc, vecEnd, dont_ignore_monsters, self.m_pPlayer.edict(), tr );

if ( tr.flFraction >= 1.0 )
{
g_Utility.TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, self.m_pPlayer.edict(), tr );
if ( tr.flFraction < 1.0 )
{
// Calculate the point of intersection of the line (or hull) and the object we hit
// This is and approximation of the "best" intersection
CBaseEntity@ pHit = g_EntityFuncs.Instance( tr.pHit );
if ( pHit is null || pHit.IsBSPModel() == TRUE )
g_Utility.FindHullIntersection( vecSrc, tr, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, self.m_pPlayer.edict() );
vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space)
}
}

if ( tr.flFraction >= 1.0 )
{
if( fFirst != 0 )
{
// miss
switch( ( m_iSwing++ ) % 3 )
{
case 0:
self.SendWeaponAnim( AXE_ATTACK1MISS ); break;
case 1:
self.SendWeaponAnim( AXE_ATTACK2MISS ); break;
case 2:
self.SendWeaponAnim( AXE_ATTACK2MISS ); break;
}
self.m_flNextPrimaryAttack = g_Engine.time + 1.0;
// play wiff or swish sound
g_SoundSystem.EmitSoundDyn( self.m_pPlayer.edict(), CHAN_WEAPON, "AoMDC/weapons/axe/axe_swing.wav", 1, ATTN_NORM, 0, 94 + Math.RandomLong( 0,0xF ) );

// player "shoot" animation
self.m_pPlayer.SetAnimation( PLAYER_ATTACK1 );
}
}
else
{
// hit
fDidHit = TRUE;

CBaseEntity@ pEntity = g_EntityFuncs.Instance( tr.pHit );

switch( ( ( m_iSwing++ ) % 2 ) + 1 )
{
case 0:
self.SendWeaponAnim( AXE_ATTACK1HIT ); break;
case 1:
self.SendWeaponAnim( AXE_ATTACK2HIT ); break;
case 2:
self.SendWeaponAnim( AXE_ATTACK3HIT ); break;
}

// player "shoot" animation
self.m_pPlayer.SetAnimation( PLAYER_ATTACK1 );

// AdamR: Custom damage option
float flDamage = 30.0;
if ( self.m_flCustomDmg > 0 )
flDamage = self.m_flCustomDmg;
// AdamR: End

g_WeaponFuncs.ClearMultiDamage();
if ( self.m_flNextPrimaryAttack + 1 < g_Engine.time )
{
// first swing does full damage
pEntity.TraceAttack( self.m_pPlayer.pev, flDamage, g_Engine.v_forward, tr, DMG_CLUB );
}
else
{
// subsequent swings do 50% (Changed -Sniper) (Half)
pEntity.TraceAttack( self.m_pPlayer.pev, flDamage * 0.5, g_Engine.v_forward, tr, DMG_CLUB );
}
g_WeaponFuncs.ApplyMultiDamage( self.m_pPlayer.pev, self.m_pPlayer.pev );

//m_flNextPrimaryAttack = gpGlobals->time + 1.0; //0.25

// play thwack, smack, or dong sound
float flVol = 1.0;
int fHitWorld = TRUE;

if( pEntity !is null )
{
self.m_flNextPrimaryAttack = g_Engine.time + 1.0; //0.25

if( pEntity.Classify() != CLASS_NONE && pEntity.Classify() != CLASS_MACHINE && pEntity.BloodColor() != DONT_BLEED )
{
// aone
if( pEntity.IsPlayer() == TRUE ) // lets pull them
{
pEntity.pev.velocity = pEntity.pev.velocity + ( self.pev.origin - pEntity.pev.origin ).Normalize() * 120;
}
// end aone
g_SoundSystem.EmitSound( self.m_pPlayer.edict(), CHAN_WEAPON, "AoMDC/weapons/axe/axe_hitbody.wav", 1, ATTN_NORM );

self.m_pPlayer.m_iWeaponVolume = 128;
if( pEntity.IsAlive() == FALSE )
return TRUE;
else
flVol = 0.1;


fHitWorld = FALSE;
}
}

// play texture hit sound
// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line

if( fHitWorld == TRUE )
{
float fvolbar = g_SoundSystem.PlayHitSound( tr, vecSrc, vecSrc + ( vecEnd - vecSrc ) * 2, BULLET_PLAYER_CROWBAR );

self.m_flNextPrimaryAttack = g_Engine.time + 1.0; //0.25

// override the volume here, cause we don't play texture sounds in multiplayer,
// and fvolbar is going to be 0 from the above call.

fvolbar = 1;

g_SoundSystem.EmitSoundDyn( self.m_pPlayer.edict(), CHAN_WEAPON, "AoMDC/weapons/axe/axe_hit.wav", fvolbar, ATTN_NORM, 0, 98 + Math.RandomLong( 0, 3 ) );
}

// delay the decal a bit
m_trHit = tr;
SetThink( ThinkFunction( this.Smack ) );
self.pev.nextthink = g_Engine.time + 0.20;

self.m_pPlayer.pev.punchangle.x = -5.0;

self.m_pPlayer.m_iWeaponVolume = int( flVol * 512 );
}
return fDidHit;
}
}

string GetDCAxeName()
{
return "weapon_dcaxe";
}

void RegisterDCAxe()
{
g_CustomEntityFuncs.RegisterCustomEntity( "weapon_dcaxe", GetDCAxeName() );
g_ItemRegistry.RegisterWeapon( GetDCAxeName(), "dc_weapons" );
}

Solokiller
29-01-2016, 11:55 AM
Does the game shut down if you gib monsters using another weapon?

Zorbos
29-01-2016, 04:12 PM
This crash is really intermittent. I tried it with the rest of my scripted weapons and no, none of them seem to cause any crashes. Just to be sure though, I went back and tried using the axe again on the same map as before and it didn't crash after almost 30 minutes of gibbing enemies with it. I tried it under different conditions too, first with a high enough damage value that it will insta-gib, and the second where it takes multiple strikes to gib. So far I haven't crashed yet, so maybe it was a fluke..?

EDIT: Wait a second, maybe it's this line under Holster():


self.m_pPlayer.pev.viewmodel = 0;

EDIT2: Yeah that was it. This line is actually in weapon_hlcrowbar.as too but that weapon wasn't used as far as I remember.