PDA

View Full Version : Problems with schedules



Heaveny
22-04-2016, 01:55 PM
Hello Svencoop forums, I have some problems with scheduled functions, not being able to stop them.


void DisplacingDisplace( const CCommand@ args )
{
CBasePlayer@ pPlayer = g_ConCommandSystem.GetCurrentPlayer();
TraceResult tr;
Vector trStart = pPlayer.GetGunPosition();
Math.MakeVectors( pPlayer.pev.v_angle );
g_Utility.TraceLine( trStart, trStart + g_Engine.v_forward * 8192, dont_ignore_monsters, pPlayer.edict(), tr );
CBaseEntity@ Portal=g_EntityFuncs.CreateDisplacerPortal(pPlayer.pev.origi n,(tr.vecEndPos-pPlayer.pev.origin)/2,@pPlayer.edict(),1000,250);
Portal.pev.scale=2;
g_Scheduler.SetInterval("Portalchecker",0.2,256,@Portal,@pPlayer);
}


void Portalchecker(CBaseEntity@ Portal,CBasePlayer@ pPlayer)
{
if(Portal !is null){DisplacerShotter(@Portal,@pPlayer);}
}


void DisplacerShotter(CBaseEntity@ E,CBasePlayer@ pPlayer)
{
TraceResult tr;
Vector trStart = pPlayer.GetGunPosition();
Math.MakeVectors( pPlayer.pev.v_angle );
g_Utility.TraceLine( trStart, trStart + g_Engine.v_forward * 8192, dont_ignore_monsters, pPlayer.edict(), tr );
g_EntityFuncs.CreateDisplacerPortal(E.pev.origin,(tr.vecEndP os-E.pev.origin)*3,pPlayer.edict(),1000,250);
}



What happens is that after the giant 2x sized Portal entity hits an entity/wall or disappears, new displacer shots are spawned from map's origin, or from a different displacer shot.
I tried different conditions, different structuring of the functions, but I just can't get it to work. Anyone has any idea?
Also, can I get a CBaseEntity@ out of an edict_t@?

Solokiller
22-04-2016, 02:29 PM
You should change Portalchecker to use an EHandle:


void Portalchecker(EHandle& in Portal,CBasePlayer@ pPlayer)


By using a handle directly, you're accessing an object that no longer exists, which causes undefined behavior.

To remove a scheduled function, pass the return value from a SetInterval call to g_Scheduler.RemoveTimer.
If you can't do this, use SetTimeout instead and keep setting a timeout until the function should no longer be called:


void Portalchecker(EHandle& in Portal,CBasePlayer@ pPlayer)
{
if(Portal.IsValid())
{
DisplacerShotter(@Portal,@pPlayer);
g_Scheduler.SetTimeout( "Portalchecker", 0.2, Portal, pPlayer );
}
}


To get a CBaseEntity@ out of an edict_t@, use g_EntityFuncs.Instance:


//pEnt should be identical to pPlayer.
CBaseEntity@ pEnt = g_EntityFuncs.Instance( pPlayer.edict() );

Heaveny
23-04-2016, 03:10 PM
Ah, thanks!

I got a few more questions though, I want to take all the entities in a map-sized circle into an array, and then use the scheduler to do things to all of the entities at the same time (ex: rotating all of them at same time)

Here's what I tried:


uint J=0;
array<CBaseEntity@>Li (0);
CBaseEntity@ pEnt = null;
while((@pEnt=g_EntityFuncs.FindEntityByTargetname(pEnt,"rotator_x")) !is null )
{
Li[J]=@pEnt;
J++;
}

Can't implicitly convert from 'CBaseEntity@' to 'const CBaseEntity&'.

Later on, I will need to somehow take all entities again, and give them all one targetname, and then all entities with said targetname to do things. (since I don't know how to work with arrays) I also think there will be difficulties, if one of the entities gets removed/killed...


Also, can I create a CBasePlayerWeapon@ with a command, set its model to a model with bones, and attach it to the player? If not, how do I utilize the bone controller and attachments?

Solokiller
23-04-2016, 03:17 PM
Assigning handles is done like this:


@Li[J]=@pEnt;


That should do the trick.

Regarding your second question, what exactly do you want to do? Create a weapon that the player can pick up, or attach a model to a player?

Heaveny
25-04-2016, 03:46 AM
I was thinking of creating a "pseudo-weapon" to attach models to a player, such as combining richard boderman's model with the player.

In addition, I now keep trying to make an array with all of the entities in the map. I've tied all of these, but none of them seems to work properly:


// while((@pEnt=g_EntityFuncs.FindEntityByTargetname(pEnt,"rotator_x")) !is null )
// while((@pEnt=g_EntityFuncs.FindEntityInSphere(Player,Player. pev.origin,99999,"","*")) !is null)
g_EntityFuncs.EntitiesInBox(Lis,Vector(9999,9999,9999),Vecto r(-9999,-9999,-9999),0);

Also, I have no idea what flagmask is

Solokiller
25-04-2016, 04:15 AM
Why do you want to store all entities in the map in an array? If you want to access all of them, it's better to just enumerate them by index. The way you're doing it would be very unsafe because you'd be storing entity handles directly, so when an entity is destroyed, the handle points to freed memory.

To enumerate all entities (note: very slow):



for( int iIndex = 0; iIndex < g_Engine.maxEntities; ++iIndex )
{
CBaseEntity@ pEntity = g_EntityFuncs.Instance( iIndex );

if( pEntity is null )
continue;

//Do stuff here
}


If you do want to use EntitiesInBox, you'll have to reserve space in the array. The reserve method does this: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes_arrays.html

Note that the bounds you're using will not catch all of the entities in the map. You need to use the WORLD_BOUNDARY constant for a range that includes the entire grid. (Note: this constant is defined as only half of the actual range, i reported this a while ago, it might be fixed in the next version. Not too big of a deal, considering the engine can't actually render the world past its current value).
See Propeties.htm in the documentation for a list of all constants.

Flagmask is an integer containing FL_* constants. typically this is used to filter out non-player and/or non-monster entities. If set to 0, all entities are used. See EdictFlags.htm for a list of all flags.
To add multiple flags, use bitwise OR:


int flagMask = FL_CLIENT | FL_MONSTER;


If you really want to store all entities in an array, use an array of EHandles, and use the above code to populate it. Note that this will be a snapshot of the entities in the world, it will not update automatically.

Heaveny
25-04-2016, 04:32 AM
Thanks for the flagmask info!
I just don't know what to do with this error:


(165, 3):Angelscript: Function Angelscript: Disco:
Angelscript: Message: Index out of bounds
WARNING: Angelscript: CASBaseCallable::Call: Execution of function '::Disco' failed!
Unknown command: .disco



uint J=0;
array<EHandle>Li (0);
for( int iIndex = 0; iIndex < g_Engine.maxEntities; ++iIndex )
{
CBaseEntity@ pEntity = g_EntityFuncs.Instance( iIndex );

if( pEntity is null )
continue;

Li[J]=EHandle(@pEntity);
J++;
}


(165, 3) being Li[J]=EHandle(@pEntity);
I'm trying to make an array of EHandles and send them over to other functions, but I don't know what to do with that error

Solokiller
25-04-2016, 04:41 AM
You've created an array of 0 elements. Using the index operator ([]) will not add elements. You have to use insertLast for that.

Heaveny
25-04-2016, 04:51 AM
Well, how dumb of me!
It works now, thanks!
I'll probably gonna be asking soon some questions regarding custom weapons, later, maybe