PDA

View Full Version : Custom Projectile Problems.



Nero
12-04-2016, 12:18 PM
I'm trying to make a new projectile, along with a ShootWhatever method (like CreateRPGRocket)
Ran into some problems. :[


class PBolt : ScriptBaseEntity
{
void Spawn()
{
self.pev.movetype = MOVETYPE_FLY;
self.pev.solid = SOLID_BBOX;

g_EntityFuncs.SetModel( self, "sprites/custom_weapons/anim_spr10.spr" );
self.pev.rendermode = kRenderTransAdd;
self.pev.renderamt = 255;
self.pev.scale = 1;
self.pev.rendercolor = Vector(220,150,0);
g_EntityFuncs.SetSize( self.pev, g_vecZero, g_vecZero );
}

PBolt@ ShootPBolt( entvars_t@ pevOwner, Vector vecStart, Vector vecVelocity )
{
//CPBolt *pPBolt = GetClassPtr( (CPBolt *)NULL );
PBolt@ pPBolt = g_EntityFuncs.Create( "info_target", g_vecZero, g_vecZero, false );
pPBolt.Spawn();

g_EntityFuncs.SetOrigin( pPBolt, vecStart );
pPBolt.pev.velocity = vecVelocity;
pPBolt.pev.angles = Math.VecToAngles( pPBolt.pev.velocity );
pPBolt.pev.owner = pevOwner;
pPBolt.SetTouch( TouchFunction(this.ExplodeTouch) );
pPBolt.SetThink( ThinkFunction(this.Fly) );
pPBolt.pev.nextthink = 0.001;
pPBolt.pev.dmg = LIGHTSABER_DAMAGE;

return pPBolt;
}

void ExplodeTouch( CBaseEntity@ pOther )
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_SKY )
{
self.SUB_Remove();
return;
}
entvars_t@ pevOwner = self.pev.owner.vars;

if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
//gEngfuncs.pEventAPI->EV_PlaySound( 0, origin, CHAN_VOICE, "weapons/plasma_hitwall.wav", 1, ATTN_NORM, 0, 200 );
//g_pRenderManager->AddSystem(new CPSBlastCone(10, 60, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), 5, 25, 255,255,255, 0.2, -0.05, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_white.spr"), FALSE, PARTICLE_WHITE_0, kRenderTransAdd, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
//g_pRenderManager->AddSystem(new CPSBubbles(30, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), gEngfuncs.pfnRandomFloat(60,120), gEngfuncs.pfnRandomFloat(6,10), gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_white.spr"), PARTICLE_WHITE_11, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
self.SUB_Remove();
return;
}
TraceResult tr;
Vector vecSpot = self.pev.origin - self.pev.velocity.Normalize() * 32;
g_Utility.TraceLine( vecSpot, vecSpot + self.pev.velocity.Normalize() * 64, ignore_monsters, self.edict(), tr );
CBaseEntity@ pEntity = g_EntityFuncs.Instance( tr.pHit );

g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg*2.5, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
//FX_ImpBeam( tr.vecEndPos, tr.vecPlaneNormal, pEntity.IsBSPModel()?1:0, IMPBEAM_PBOLT );
/*
VectorMA (origin, 2, angles, src);
VectorMA (origin, 2, angles, end);
gEngfuncs.pEventAPI->EV_SetTraceHull(2);
gEngfuncs.pEventAPI->EV_PlayerTrace(src, end, PM_STUDIO_BOX, -1, &tr);
EV_DecalTrace(&tr, EV_EgonDecal(CHAR_TEX_CONCRETE));

VectorAngles(angles, exp_angles);
exp_angles[0] = -exp_angles[0];

g_pRenderManager->AddSystem(new CRenderSystem(src, Vector(0,0,0), exp_angles, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_red.spr"), PARTICLE_RED_2, 0, kRenderTransAdd, 255,255,255, 1.0, 0, 10, 25, 0.9));
gEngfuncs.pEventAPI->EV_PlaySound( 0, src, CHAN_STATIC, "weapons/bfg_dryfire.wav", 1, ATTN_LOW_HIGH, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
DynamicLight(origin, 180, 240,170,30, 0.3, 100.0);

if (Surface == SURFACE_WORLDBRUSH || Surface == SURFACE_BREAKABLE || Surface == SURFACE_ARMOR)//hit world
g_pRenderManager->AddSystem(new PSGravityPart(gEngfuncs.pfnRandomLong(6,12), 5, gEngfuncs.pfnRandomFloat(200, 240), src, Vector(0,0,1), Vector(0.2,0.2,0.4), gEngfuncs.pfnRandomFloat(1.3,2.5), 0, 255,255,255, 1, -0.2, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/anim_spr10.spr"), TRUE, -1, kRenderTransAdd, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
*/

self.pev.effects |= EF_NODRAW;
self.pev.velocity = g_vecZero;
SetTouch( null );

SetThink( ThinkFunction( this.Nova ) );
self.pev.nextthink = g_Engine.time + 0.9;
}

void Nova()
{
entvars_t@ pevOwner = self.pev.owner.vars;
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg*3, CLASS_NONE, DMG_SONIC );
//FX_Explosion( self.pev.origin, EXPLOSION_PBOLT);
//gEngfuncs.pEventAPI->EV_PlaySound( 0, origin, CHAN_VOICE, "weapons/explode5.wav", 1, ATTN_NORM, 10, 250 );
//DynamicLight(origin, 225, 240,170,30, 0.5, 100.0);
//g_pRenderManager->AddSystem(new CRSCylinder(origin, 20, 2500, 30, 50, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/rings_all.spr"), BLAST_SKIN_ENERGYBOLT, kRenderTransAdd, 255,255,255, 1, -1, 0.07));
//g_pRenderManager->AddSystem(new PSSparkShower(gEngfuncs.pfnRandomLong(2,5), gEngfuncs.pfnRandomFloat(1.5,2.2), gEngfuncs.pfnRandomFloat(300, 360), SPARKSHOWER_ENERGY, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_red.spr"), 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
SetThink( ThinkFunction( this.SUB_Remove ) );
}

void Fly()
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
entvars_t@ pevOwner = self.pev.owner.vars;
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
self.SUB_Remove();
return;
}
self.pev.nextthink = g_Engine.time + 0.001;
}

void SUB_Remove()
{
self.SUB_Remove();
}
}

string GetPBoltName()
{
return "pbolt";
}

void RegisterPBolt()
{
g_CustomEntityFuncs.RegisterCustomEntity( "PBolt", GetPBoltName() );
}


Errors:


proj_pbolt.as (16, 2) : Compiling PBolt@ PBolt::ShootPBolt(entvars_t@, Vector, Vector)
proj_pbolt.as (19, 19) : Can't implicitly convert from 'CBaseEntity@&' to 'PBolt@&'.

proj_pbolt.as (22, 17) : No matching signatures to 'CEntityFuncs::SetOrigin(PBolt@&, Vector&)'
proj_pbolt.as (22, 17) : Candidates are:
proj_pbolt.as (22, 17) : void CEntityFuncs::SetOrigin(CBaseEntity@ entity, const Vector&in vecOrigin)

proj_pbolt.as (25, 22) : Can't implicitly convert from 'entvars_t@&' to 'const edict_t&'.



Can't implicitly convert from 'CBaseEntity@&' to 'PBolt@&'.
The original code is
CPBolt *pPBolt = GetClassPtr( (CPBolt *)NULL );
But I couldn't figure out what that is, so I used this:
PBolt@ pPBolt = g_EntityFuncs.Create( "info_target", g_vecZero, g_vecZero, false );
And if I make pPBolt into a CBaseEntity@ I get No matching signatures to 'CBaseEntity::Spawn()
No matching signatures to 'CEntityFuncs::SetOrigin(PBolt@&, Vector&)'
Related to the above error.
Can't implicitly convert from 'entvars_t@&' to 'const edict_t&'.
pPBolt.pev.owner = pevOwner;
How do you get the edict from an entvar?
Using pPBolt.pev.owner = pevOwner.get_pContainingEntity(); gives me No appropriate opAssign method found in 'edict_t' for value assignment


My back and head hurts ;_; :banghead:
Any help would be greatly appreciated and let me make more custom weapons with custom projectiles. :D <3

EDIT: How do I SetThink to SUB_Remove?
SetThink( ThinkFunction( BaseClass.SUB_Remove ) );
Doesn't work because SUB_Remove is a part of CBaseEntity, but not BaseEntity.
I made my own SUB_Remove function instead SetThink( ThinkFunction( this.SUB_Remove ) ); and it just has self.SUB_Remove(); in it.

w00tguy123
12-04-2016, 12:35 PM
Can't implicitly convert from 'CBaseEntity@&' to 'PBolt@&'.



PBolt@ customEnt = cast<PBolt@>(CastToScriptClass(baseEnt));





No matching signatures to 'CEntityFuncs::SetOrigin(PBolt@&, Vector&)'
Related to the above error.


Use a CBaseEntity@ instead. You can cast your custom class to that if you don't have the handle for it already.




Can't implicitly convert from 'entvars_t@&' to 'const edict_t&'.
pPBolt.pev.owner = pevOwner;



@pPBolt.pev.owner = self.edict();

Nero
12-04-2016, 03:54 PM
Thank you! This might actually work :O

But how do I access ShootPBolt from the custom weapon class? I have #include d the projectile class file at the top.

Solokiller
12-04-2016, 04:11 PM
ShootPBolt is a member function, so you can't access it unless you have an object of it. Angelscript doesn't support static member functions, so move it out of the class.


CPBolt *pPBolt = GetClassPtr( (CPBolt *)NULL );

This is how some code in GoldSource creates entities. You have to replace it with g_EntityFuncs.Create or g_EntityFuncs.CreateEntity, since it can't be used in Angelscript.


PBolt@ pPBolt = g_EntityFuncs.Create( "info_target", g_vecZero, g_vecZero, false );[/B]
And if I make pPBolt into a CBaseEntity@ I get [B]No matching signatures to 'CBaseEntity::Spawn()

Replace "info_target" with your entity's name.
Replace pPBolt.Spawn() with g_EntityFuncs.DispatchSpawn( pPBolt.edict() );


No matching signatures to 'CEntityFuncs::SetOrigin(PBolt@&, Vector&)'

PBolt is not a CBaseEntity. use pPBolt.self instead.


Can't implicitly convert from 'entvars_t@&' to 'const edict_t&'.



@pPBolt.pev.owner = pevOwner.pContainingEntity;

Nero
13-04-2016, 04:38 AM
Yay, that solved most problems. Thanks! :D
Had to use g_EntityFuncs.DispatchSpawn( pPBolt.self.edict() ); though.

Down to only two errors! ^^;
I have the ShootPBolt outside of the class now, so it can't find the Touch or Think methods. And if I place those outside of the class, it looses self. :S



PBolt@ ShootPBolt( entvars_t@ pevOwner, Vector vecStart, Vector vecVelocity )
{
//CPBolt *pPBolt = GetClassPtr( (CPBolt *)NULL );
//CBaseEntity@ cbeBolt = null;
//CBaseEntity@ cbeBolt = g_EntityFuncs.Create( "pbolt", g_vecZero, g_vecZero, false );
//CBaseEntity@ cbeBolt = g_EntityFuncs.CreateCustomEntity( "pbolt", null, false);

CBaseEntity@ cbeBolt = g_EntityFuncs.CreateEntity( "pbolt", null, false);
PBolt@ pPBolt = cast<PBolt@>(CastToScriptClass(cbeBolt));
g_EntityFuncs.DispatchSpawn( pPBolt.self.edict() );

g_EntityFuncs.SetOrigin( pPBolt.self, vecStart );
pPBolt.pev.velocity = vecVelocity;
pPBolt.pev.angles = Math.VecToAngles( pPBolt.pev.velocity );
@pPBolt.pev.owner = pevOwner.pContainingEntity;
pPBolt.SetTouch( TouchFunction(ExplodeTouch) );
pPBolt.SetThink( ThinkFunction(Fly) );
pPBolt.pev.nextthink = 0.001;
pPBolt.pev.dmg = LIGHTSABER_DAMAGE;

return pPBolt;
}




'ExplodeTouch' is not declared
'Fly' is not declared


Would I have to pass on the pBolt ?
Something like:


void Fly( PBolt@ or CBaseEntity@ self )
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
entvars_t@ pevOwner = self.pev.owner.vars;
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
self.SUB_Remove();
return;
}
self.pev.nextthink = g_Engine.time + 0.001;
}

And pPBolt.SetTouch( TouchFunction( ExplodeTouch(pPBolt) ) );

Solokiller
13-04-2016, 04:40 AM
Use pPBolt.ExplodeTouch. Same for Fly.

Nero
13-04-2016, 05:05 AM
Doooooooh, sorry ._.

New error though, one that I was sure to be able to fix easily. But noooo.. ;_;
Host_Error: PF_precache_generic_I: 'sprites/custom_weapons/anim_spr10.spr' Precache can only be done in spawn functions

I've tried every way I could think of



const string PBOLT_MODEL = "sprites/custom_weapons/anim_spr10.spr";

class PBolt : ScriptBaseEntity
{
void Precache()
{
BaseClass.Precache();
//g_Game.PrecacheGeneric( PBOLT_MODEL );
//g_Game.PrecacheModel( PBOLT_MODEL );
}

void SetupModel()
{
g_Game.PrecacheGeneric( PBOLT_MODEL );
g_Game.PrecacheModel( PBOLT_MODEL );
}

void Spawn()
{
self.pev.movetype = MOVETYPE_FLY;
self.pev.solid = SOLID_BBOX;

SetupModel();

g_EntityFuncs.SetModel( self, PBOLT_MODEL );
self.pev.rendermode = kRenderTransAdd;
self.pev.renderamt = 255;
self.pev.scale = 1;
self.pev.rendercolor = Vector(220,150,0);
g_EntityFuncs.SetSize( self.pev, g_vecZero, g_vecZero );

self.Precache();
}

void ExplodeTouch( CBaseEntity@ pOther )
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_SKY )
{
self.SUB_Remove();
return;
}
entvars_t@ pevOwner = self.pev.owner.vars;

if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
//gEngfuncs.pEventAPI->EV_PlaySound( 0, origin, CHAN_VOICE, "weapons/plasma_hitwall.wav", 1, ATTN_NORM, 0, 200 );
//g_pRenderManager->AddSystem(new CPSBlastCone(10, 60, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), 5, 25, 255,255,255, 0.2, -0.05, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_white.spr"), FALSE, PARTICLE_WHITE_0, kRenderTransAdd, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
//g_pRenderManager->AddSystem(new CPSBubbles(30, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), gEngfuncs.pfnRandomFloat(60,120), gEngfuncs.pfnRandomFloat(6,10), gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_white.spr"), PARTICLE_WHITE_11, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
self.SUB_Remove();
return;
}
TraceResult tr;
Vector vecSpot = self.pev.origin - self.pev.velocity.Normalize() * 32;
g_Utility.TraceLine( vecSpot, vecSpot + self.pev.velocity.Normalize() * 64, ignore_monsters, self.edict(), tr );
CBaseEntity@ pEntity = g_EntityFuncs.Instance( tr.pHit );

g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg*2.5, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
//FX_ImpBeam( tr.vecEndPos, tr.vecPlaneNormal, pEntity.IsBSPModel()?1:0, IMPBEAM_PBOLT );
/*
VectorMA (origin, 2, angles, src);
VectorMA (origin, 2, angles, end);
gEngfuncs.pEventAPI->EV_SetTraceHull(2);
gEngfuncs.pEventAPI->EV_PlayerTrace(src, end, PM_STUDIO_BOX, -1, &tr);
EV_DecalTrace(&tr, EV_EgonDecal(CHAR_TEX_CONCRETE));

VectorAngles(angles, exp_angles);
exp_angles[0] = -exp_angles[0];

g_pRenderManager->AddSystem(new CRenderSystem(src, Vector(0,0,0), exp_angles, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_red.spr"), PARTICLE_RED_2, 0, kRenderTransAdd, 255,255,255, 1.0, 0, 10, 25, 0.9));
gEngfuncs.pEventAPI->EV_PlaySound( 0, src, CHAN_STATIC, "weapons/bfg_dryfire.wav", 1, ATTN_LOW_HIGH, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
DynamicLight(origin, 180, 240,170,30, 0.3, 100.0);

if (Surface == SURFACE_WORLDBRUSH || Surface == SURFACE_BREAKABLE || Surface == SURFACE_ARMOR)//hit world
g_pRenderManager->AddSystem(new PSGravityPart(gEngfuncs.pfnRandomLong(6,12), 5, gEngfuncs.pfnRandomFloat(200, 240), src, Vector(0,0,1), Vector(0.2,0.2,0.4), gEngfuncs.pfnRandomFloat(1.3,2.5), 0, 255,255,255, 1, -0.2, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/anim_spr10.spr"), TRUE, -1, kRenderTransAdd, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
*/

self.pev.effects |= EF_NODRAW;
self.pev.velocity = g_vecZero;
SetTouch( null );

SetThink( ThinkFunction( this.Nova ) );
self.pev.nextthink = g_Engine.time + 0.9;
}

void Nova()
{
entvars_t@ pevOwner = self.pev.owner.vars;
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg*3, CLASS_NONE, DMG_SONIC );
//FX_Explosion( self.pev.origin, EXPLOSION_PBOLT);
//gEngfuncs.pEventAPI->EV_PlaySound( 0, origin, CHAN_VOICE, "weapons/explode5.wav", 1, ATTN_NORM, 10, 250 );
//DynamicLight(origin, 225, 240,170,30, 0.5, 100.0);
//g_pRenderManager->AddSystem(new CRSCylinder(origin, 20, 2500, 30, 50, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/rings_all.spr"), BLAST_SKIN_ENERGYBOLT, kRenderTransAdd, 255,255,255, 1, -1, 0.07));
//g_pRenderManager->AddSystem(new PSSparkShower(gEngfuncs.pfnRandomLong(2,5), gEngfuncs.pfnRandomFloat(1.5,2.2), gEngfuncs.pfnRandomFloat(300, 360), SPARKSHOWER_ENERGY, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_red.spr"), 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
SetThink( ThinkFunction( this.SUB_Remove ) );
}

void Fly()
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
entvars_t@ pevOwner = self.pev.owner.vars;
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
self.SUB_Remove();
return;
}
self.pev.nextthink = g_Engine.time + 0.001;
}

void SUB_Remove()
{
self.SUB_Remove();
}
}

PBolt@ ShootPBolt( entvars_t@ pevOwner, Vector vecStart, Vector vecVelocity )
{
//CPBolt *pPBolt = GetClassPtr( (CPBolt *)NULL );
//CBaseEntity@ cbeBolt = null;
//CBaseEntity@ cbeBolt = g_EntityFuncs.Create( "pbolt", g_vecZero, g_vecZero, false );
//CBaseEntity@ cbeBolt = g_EntityFuncs.CreateCustomEntity( "pbolt", null, false);

CBaseEntity@ cbeBolt = g_EntityFuncs.CreateEntity( "pbolt", null, false);
PBolt@ pPBolt = cast<PBolt@>(CastToScriptClass(cbeBolt));
g_EntityFuncs.DispatchSpawn( pPBolt.self.edict() );

g_EntityFuncs.SetOrigin( pPBolt.self, vecStart );
pPBolt.pev.velocity = vecVelocity;
pPBolt.pev.angles = Math.VecToAngles( pPBolt.pev.velocity );
@pPBolt.pev.owner = pevOwner.pContainingEntity;
pPBolt.SetTouch( TouchFunction(pPBolt.ExplodeTouch) );
pPBolt.SetThink( ThinkFunction(pPBolt.Fly) );
pPBolt.pev.nextthink = 0.001;
pPBolt.pev.dmg = LIGHTSABER_DAMAGE;

return pPBolt;
}

string GetPBoltName()
{
return "pbolt";
}

void RegisterPBolt()
{
g_CustomEntityFuncs.RegisterCustomEntity( "PBolt", GetPBoltName() );
}


I don't get it ;_;

Solokiller
13-04-2016, 05:11 AM
Add this to MapInit, after registering the entity:



g_Game.PrecacheOther( "pbolt" );


This is necessary because the bolt is created later on, so when it tries to precache anything, it's too late. This precaches the bolt when the map starts, when precaching is still allowed.
Note that if your entity precaches resources that are determined by keyvalues or conditions, all of those resources must be precached ahead of time. You can't just magically precache the right one.

Nero
13-04-2016, 05:18 AM
I stepped away from the computer to brush my teeth, when it struck me that I should probably precache the model in the weapon class instead.
I will try this instead, though. Thank you so much O_O <3

Solokiller
13-04-2016, 05:23 AM
That also works. That's actually how game code does it, and it's less of a hassle than precaching it in MapInit. Weapons are precached automatically, so you won't have to worry about them.

Nero
13-04-2016, 05:27 AM
It works! :D Thank you than kyou tahnkt oyuo! <3

Now I just need to fix all the stuff the projectile is supposed to do.
At the moment it just flies and travels along the wall (it's supposed to remove itself if it hits something o.O )




void ExplodeTouch( CBaseEntity@ pOther )
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_SKY )
{
self.SUB_Remove();
return;
}
entvars_t@ pevOwner = self.pev.owner.vars;

if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
//gEngfuncs.pEventAPI->EV_PlaySound( 0, origin, CHAN_VOICE, "weapons/plasma_hitwall.wav", 1, ATTN_NORM, 0, 200 );
//g_pRenderManager->AddSystem(new CPSBlastCone(10, 60, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), 5, 25, 255,255,255, 0.2, -0.05, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_white.spr"), FALSE, PARTICLE_WHITE_0, kRenderTransAdd, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
//g_pRenderManager->AddSystem(new CPSBubbles(30, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), gEngfuncs.pfnRandomFloat(60,120), gEngfuncs.pfnRandomFloat(6,10), gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_white.spr"), PARTICLE_WHITE_11, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
self.SUB_Remove();
return;
}
TraceResult tr;
Vector vecSpot = self.pev.origin - self.pev.velocity.Normalize() * 32;
g_Utility.TraceLine( vecSpot, vecSpot + self.pev.velocity.Normalize() * 64, ignore_monsters, self.edict(), tr );
CBaseEntity@ pEntity = g_EntityFuncs.Instance( tr.pHit );

g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg*2.5, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
//FX_ImpBeam( tr.vecEndPos, tr.vecPlaneNormal, pEntity.IsBSPModel()?1:0, IMPBEAM_PBOLT );
/*
VectorMA (origin, 2, angles, src);
VectorMA (origin, 2, angles, end);
gEngfuncs.pEventAPI->EV_SetTraceHull(2);
gEngfuncs.pEventAPI->EV_PlayerTrace(src, end, PM_STUDIO_BOX, -1, &tr);
EV_DecalTrace(&tr, EV_EgonDecal(CHAR_TEX_CONCRETE));

VectorAngles(angles, exp_angles);
exp_angles[0] = -exp_angles[0];

g_pRenderManager->AddSystem(new CRenderSystem(src, Vector(0,0,0), exp_angles, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_red.spr"), PARTICLE_RED_2, 0, kRenderTransAdd, 255,255,255, 1.0, 0, 10, 25, 0.9));
gEngfuncs.pEventAPI->EV_PlaySound( 0, src, CHAN_STATIC, "weapons/bfg_dryfire.wav", 1, ATTN_LOW_HIGH, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
DynamicLight(origin, 180, 240,170,30, 0.3, 100.0);

if (Surface == SURFACE_WORLDBRUSH || Surface == SURFACE_BREAKABLE || Surface == SURFACE_ARMOR)//hit world
g_pRenderManager->AddSystem(new PSGravityPart(gEngfuncs.pfnRandomLong(6,12), 5, gEngfuncs.pfnRandomFloat(200, 240), src, Vector(0,0,1), Vector(0.2,0.2,0.4), gEngfuncs.pfnRandomFloat(1.3,2.5), 0, 255,255,255, 1, -0.2, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/anim_spr10.spr"), TRUE, -1, kRenderTransAdd, 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
*/

self.pev.effects |= EF_NODRAW;
self.pev.velocity = g_vecZero;
SetTouch( null );

SetThink( ThinkFunction( this.Nova ) );
self.pev.nextthink = g_Engine.time + 0.9;
}

void Nova()
{
entvars_t@ pevOwner = self.pev.owner.vars;
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg*3, CLASS_NONE, DMG_SONIC );
//FX_Explosion( self.pev.origin, EXPLOSION_PBOLT);
//gEngfuncs.pEventAPI->EV_PlaySound( 0, origin, CHAN_VOICE, "weapons/explode5.wav", 1, ATTN_NORM, 10, 250 );
//DynamicLight(origin, 225, 240,170,30, 0.5, 100.0);
//g_pRenderManager->AddSystem(new CRSCylinder(origin, 20, 2500, 30, 50, gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/rings_all.spr"), BLAST_SKIN_ENERGYBOLT, kRenderTransAdd, 255,255,255, 1, -1, 0.07));
//g_pRenderManager->AddSystem(new PSSparkShower(gEngfuncs.pfnRandomLong(2,5), gEngfuncs.pfnRandomFloat(1.5,2.2), gEngfuncs.pfnRandomFloat(300, 360), SPARKSHOWER_ENERGY, origin, Vector(0,0,1), Vector(0.2,0.2,0.5), gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/particles_red.spr"), 0.1), RENDERSYSTEM_FLAG_SIMULTANEOUS, -1);
SetThink( ThinkFunction( this.SUB_Remove ) );
}

void Fly()
{
if( g_EngineFuncs.PointContents( self.pev.origin ) == CONTENTS_WATER )
{
entvars_t@ pevOwner = self.pev.owner.vars;
//FX_Explosion( self.pev.origin, EXPLOSION_ENERGY_INWATER_S);
g_WeaponFuncs.RadiusDamage( self.pev.origin, self.pev, pevOwner, self.pev.dmg, self.pev.dmg, CLASS_NONE, DMG_ENERGYBEAM | DMG_NEVERGIB );
self.SUB_Remove();
return;
}
self.pev.nextthink = g_Engine.time + 0.001;
}

void SUB_Remove()
{
self.SUB_Remove();
}


Looking at this, I say it should work. But what do I know ;_;
It doesn't get removed when hitting sky or water.
SUB_Remove doesn't seem to ever be called, neither the thinkfunctionI made ( void SUB_Remove() ) nor the base one (self.SUB_Remove())
They just stick around forever. :S

Solokiller
13-04-2016, 05:34 AM
Add alerts to all functions so you can see what's going on. Add the current time so you know when it's all happening.

Also, if you're going to remove the entity right away, just call g_EntityFuncs.Remove( self );
That's essentially the same as calling SUB_Remove. SUB_Remove is supposed to be used when you want to delay the removal.

Nero
13-04-2016, 05:36 AM
Ooooh, good idea :O

Aha, thanks! <3


I sort of figured out why they're not getting removed.
I used a custom command .fun_shoot to launch them, which caused the projectiles to not be removed.
But when I fired the gun, they do get removed when hitting something. :o

Solokiller
13-04-2016, 05:58 AM
What's the difference between the command and the weapon's firing code?

Nero
13-04-2016, 06:46 AM
Sorry, had to catch the bus to do important stuff down-town :S

Uhm, the command is:


void FunShoot( const CCommand@ args )
{
CBasePlayer@ pPlayer = g_ConCommandSystem.GetCurrentPlayer();

if( args.ArgC() == 1 ) //If no arguments are supplied
{
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[AdminFuckery] .fun_shoot [name] <velocity> - Attempts to launch the named entity at the specified velocity multiplier.\n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Valid entities: bmortar, controller_energy_ball, crossbow_bolt, displacer_portal, \n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "garg_stomp, gonomespit, grenade, hornet, hvr_rocket, kingpin_plasma_ball, pitdronespike, \n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "playerhornet, rpg_rocket, shock_beam, spark_shower, sporegrenade, squidspit, voltigoreshock\n" );

return;
}
else if( args.ArgC() == 2 ) //If one argument is supplied
{
const string szEntity = args.Arg( 1 );

if( pValidProjectiles.find( szEntity ) != -1 )
{
CBaseEntity@ pEnt;
Vector vecSrc = pPlayer.GetGunPosition() + g_Engine.v_forward * 16 + g_Engine.v_right * 8 + g_Engine.v_up * -12;
Vector vecAiming = pPlayer.pev.v_angle;

Math.MakeVectors( pPlayer.pev.v_angle );

@pEnt = g_EntityFuncs.Create( szEntity, vecSrc, vecAiming, false, pPlayer.edict() );
pEnt.pev.velocity = vecAiming.Normalize() + g_Engine.v_forward * 400;
}
else
{
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Valid entities: bmortar, controller_energy_ball, crossbow_bolt, displacer_portal, \n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "garg_stomp, gonomespit, grenade, hornet, hvr_rocket, kingpin_plasma_ball, pitdronespike, \n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "playerhornet, rpg_rocket, shock_beam, spark_shower, sporegrenade, squidspit, voltigoreshock\n" );

return;
}
}
else if( args.ArgC() == 3 ) //If two arguments are supplied
{
const string szEntity = args.Arg( 1 );
int iVelocity = atoi( args.Arg( 2 ) );
if( iVelocity < 100 )
iVelocity = 100;

if( pValidProjectiles.find( szEntity ) != -1 )
{
CBaseEntity@ pEnt;
Vector vecSrc = pPlayer.GetGunPosition() + g_Engine.v_forward * 16 + g_Engine.v_right * 8 + g_Engine.v_up * -12;
Vector vecAiming = pPlayer.pev.v_angle;

Math.MakeVectors( pPlayer.pev.v_angle );

@pEnt = g_EntityFuncs.Create( szEntity, vecSrc, vecAiming, false, pPlayer.edict() );
pEnt.pev.velocity = vecAiming.Normalize() + g_Engine.v_forward * iVelocity;
}
else
{
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Valid entities: bmortar, controller_energy_ball, crossbow_bolt, displacer_portal, \n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "garg_stomp, gonomespit, grenade, hornet, hvr_rocket, kingpin_plasma_ball, pitdronespike, \n" );
g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "playerhornet, rpg_rocket, shock_beam, spark_shower, sporegrenade, squidspit, voltigoreshock\n" );

return;
}
}
}

Spawn code in bold
pValidProjectiles is just an array with valid entities to spawn, of which pbolt is a member.

And the weapon calls FireBall(); in WeaponIdle (for delayed shot purposes)


void FireBall()
{
if( m_fInAttack == 0 )
{
self.m_pPlayer.m_flNextAttack = WeaponTimeBase() + 1;
return;
}

//--self.m_iClip;
self.m_pPlayer.SetAnimation( PLAYER_ATTACK1 );

Math.MakeVectors( self.m_pPlayer.pev.v_angle + self.m_pPlayer.pev.punchangle );
Vector vecSrc = self.m_pPlayer.GetGunPosition( ) + g_Engine.v_forward * 10 + g_Engine.v_right * -8 + g_Engine.v_up * -5;
ShootPBolt( self.m_pPlayer.pev, vecSrc, g_Engine.v_forward * 1600 );
//FX_FireGun(m_pPlayer.pev.v_angle, m_pPlayer.entindex(), 200, 0, FIREGUN_EPISTOL );

self.m_pPlayer.set_m_szAnimExtension( "crowbar" );
self.m_pPlayer.m_flNextAttack = WeaponTimeBase() + 1.0;
//m_flRechargeTime = g_Engine.time + 2;
}

Solokiller
13-04-2016, 07:01 AM
You're not doing any of the things that are done in ShootPBolt. I'd suggest moving all of that into the Spawn method so it can be handled there.

Nero
13-04-2016, 08:23 AM
Aye, it's not as important because it's just a command to fire off various projectiles.

Thanks a billion! ^^<3

Nero
14-04-2016, 07:38 AM
Heya, g_Game.PrecacheOther won't work when put in the Precache of the weaponclass, will it?
I'll have to precache each projectile resource individually?

Solokiller
14-04-2016, 07:42 AM
The entity you're precaching must be registered (or a built-in entity) if you're going to use PrecacheOther on it. It should work when used in the weapon's Precache.

Nero
14-04-2016, 07:49 AM
Hmm hmm hmm.
Well the projectile "biomass" is registered in my map script, and I have g_Game.PrecacheOther( "biomass" ); in the weapon's Precache, and I have all the necessary resources in the projectile's.
But when shooting I get this spammed:

Tried to link edict 11 without model

edit: Works fine when placed in MapInit of my map script :o

Solokiller
14-04-2016, 09:07 AM
Is the entity's Precache being called? What's it doing exactly?

Nero
14-04-2016, 09:52 AM
Oh, I thought PrecacheOther called the Precache of the entity :o
That's how I interpreted the description in the docs anyway.

"Precaches an entity.This effectively instances an entity with the given class name, calls precache on it, and removes the entity."

So I just made a void Precache() but I don't call it in the entity.

Nero
14-04-2016, 10:03 AM
The entity:



class CBiomass : ScriptBaseMonsterEntity
{
...
...
...
void Spawn()
{
Precache();
g_EntityFuncs.SetModel( self, BIOMASS_MODEL );
self.ResetSequenceInfo();
self.pev.movetype = MOVETYPE_BOUNCE;
self.pev.solid = SOLID_BBOX;
self.pev.rendermode = kRenderTransTexture;
self.pev.renderamt = 150;
self.pev.scale = 1.5;
@self.pev.enemy = null;
dist = g_vecZero;
angl_x = angl_y = 0;
b_attached = false;
g_EntityFuncs.SetSize( self.pev, g_vecZero, g_vecZero );
}

void Precache()
{
g_Game.PrecacheModel( BIOMASS_MODEL );
g_Game.PrecacheGeneric( "sound/" + BIOMASS_SOUND_HIT1 );
g_Game.PrecacheGeneric( "sound/" + BIOMASS_SOUND_HIT2 );
g_Game.PrecacheGeneric( "sound/" + BIOMASS_SOUND_EXPL );
g_SoundSystem.PrecacheSound( BIOMASS_SOUND_HIT1 );
g_SoundSystem.PrecacheSound( BIOMASS_SOUND_HIT2 );
g_SoundSystem.PrecacheSound( BIOMASS_SOUND_EXPL );
}
...
...
...
}


And in the Precache() of the weapon
g_Game.PrecacheOther( "biomass" );

edit: I removed the call to Precache(); and added g_Game.PrecacheOther( "biomass" ); to the MapInit, which works. So PrecacheOther obviously calls the Precache() of the entity?

Solokiller
14-04-2016, 10:11 AM
Add an alert in its Precache and see if it gets called on map start (when using PrecacheOther in the weapon). If not, something's wrong.
Note that you must always call Precache in Spawn. That's how it's done in GoldSource.

Nero
14-04-2016, 11:10 AM
Aye, the entity's precache gets called on map start, and when firing the weapon.

Nero
14-04-2016, 11:13 AM
Ok I don't get it, it seems to be working now for some reason... o.O

Nero
14-04-2016, 11:46 AM
The fruits of our labour!

https://www.youtube.com/watch?v=0IRgOqIsMRg
:D