Author Topic: fxLight to follow shot projectile  (Read 3811 times)

The default projectile light is loving stuff and i want to attach an FX light onto a projectile or make it follow the projectile until it dies.
So far i've instantiated a new light under the "onFire" action of the weapon like this:
Code: [Select]
%light = new fxlight()
{
dataBlock = BrightLight;
enable = true;
iconsize = 1;
position = %this.projectile.pos;
};
and i know that this doesnt copy the movement of the projectile but i've tried adding this line so it would get destroyed alongside the projectile:
Code: [Select]
%light.attachToObject(%obj);However, this causes new light to instantiate on the blockhead's left hand. This isnt the player flashlight because you can turn that on and off without affecting the other light.
I've also tried using:
Code: [Select]
%this.projectilebut i dont know the syntax for it and wether it even has a position variable.

Any help?

I'm not sure if lights can be attached to projectiles, but if they can.

You'll need to use the variable that references the projectile object being created, which really depends on how your onFire code looks.
If you're just using Parent::onFire to use default behaviour, you'll need to do %projectile = Parent::onFire
If you're not using the parent, assuming you're copy pasting some common code that goes around, you should be able to just use %p instead of %obj.

Just for reference, in a typical ::onFire code you'll find:
%this is the weaponImage datablock.
%obj is the player that is shooting.
%slot is probably 0, 1 if it's a left handed weapon.

%this.projectile will not be the projectile object, but rather the projectile datablock. Which isn't a world object that has properties like position and such, but rather a baseline for projectiles to reference common data from... Such as the model file, damage, base speed, etc.

The on fire method is just that. The item uses T+T so the on fire method is borrowed from T+T
Code: [Select]
function Blabla::onFire(%this,%obj,%slot)The only code thats in the default T+T onFire (apart from ammo system)
 is the recoil projectile that just shakes the screen:
Code: [Select]
%obj.spawnExplosion(TTBigRecoilProjectile,"4 4 4");Referring to the %p parent in:
Code: [Select]
%light.attachToObject(%p);just gives me the error: "couldn't find object to attach to"
« Last Edit: May 07, 2018, 11:19:51 PM by The 1 »

For the onFire function, the first field is the datablock for the weapon image, the second field is the player object (hence why it's attaching to the player instead of the projectile) and the third is the slot the item is in. If you want to attach a light to the projectile you'll have to manually create the projectile and attach the light to it after creating it.

If you want to attach a light to the projectile you'll have to manually create the projectile and attach the light to it after creating it.
How would you do that?

The code is gonna look something like this:
Code: [Select]
%projectile = new Projectile()
{
    dataBlock = %weaponImage.projectile;
    initialVelocity = %velocity;
    initialPosition = %position;
    sourceObject = %obj;
    sourceSlot = %slot;
    client = %client;
};
%projectile.setScale(%obj.getScale); //Increasing the scale of the firing object increases the scale of the projectile (bigger players -> bigger projectiles)
MissionCleanup.add(%projectile); //Make sure that the engine knows that it needs to keep track of this projectile
return %projectile; //Used for callbacks when parenting WeaponImage::onFire

NB: This code will not work if you stick it into your script. I purposefully used generic variable names to avoid spoon-feeding you a solution and encouraging you to learn.

Most of it is pretty self-explanatory, however for WeaponImage::onFire(%image, %player, %slot):
  • You can get the datablock of a projectile from %image.projectile
  • The sourceobject could be for example the player object (second argument for the function)
  • You can get the client object of a player via %player.client, you must define this in case the projectile is used to kill another player. If there is no client defined, it will not show who killed them
  • Once again, I used generic variable names that do not match up with your code, don't just stick these bits of code in.

I apologize beforehand in case making this post this exhaustive comes off as patronizing, I simply wanted to include as much detail as possible for future reference.

The code is gonna look something like this...
I've already tried using the Mission cleanup method:
Code: [Select]
%p = new (%this.projectileType)()
{
dataBlock = %projectile;
initialVelocity = %velocity;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
client = %obj.client;
};
MissionCleanup.add(%p);
                %p.setScale(scalevarsandwhatnot);
When i try to keep the fxLight updated on the projectile's position it only gets the initial position once the projectile is spawned and does nothing after that. Maybe fxLights ren't meant to be moved that way?
« Last Edit: May 08, 2018, 07:05:47 AM by The 1 »

fxLight are static, you have to attach them to an object %light.attachToObject(ID), unfortunately they only attach to players or bricks.

Wll now i got both the custom projectile and the light working.
Now i just need to update the position of the fxLight. Is there any position parameters for the fxLight?

Now that i've succesfully creted a new projectile with:
Code: [Select]
MissionCleanup.add(%p);The line:
Code: [Select]
%light.attachToObject(%p);Doesnt give me any errors anymore.
But like Kyuande said in their post; the light doesnt react to the projectile dying.
So in addition to accessing the fxLight position i need a way to destroy it when the projectile %p is destroyed
« Last Edit: May 08, 2018, 09:28:21 AM by The 1 »

If attatchToObject doesn't work, which apparently it doesn't, then the only way to do this is to set up a loop that constantly updates the position of fxLight to match the position of the projectile, which doesn't seem like a good trade-off for the default projectile light functionality

I haven't been in-game to test this but I believe to update the position of the light you'd use %light.setTransform(<desired position>). Projectiles have a getPosition() method, so you could set the position of the fxLight to the position of the projectile with %light.setTransform(%p.getPosition())
« Last Edit: May 08, 2018, 09:26:50 AM by Rally »

If attatchToObject doesn't work, which apparently it doesn't, then the only way to do this is to set up a loop that constantly updates the position of fxLight to match the position of the projectile, which doesn't seem like a good trade-off for the default projectile light functionality

Yeah, Like the documentation says, attachToObject doesnt change the object position but destroys the object once the object it's attached to no logner exists.

Yeah, Like the documentation says, attachToObject doesnt change the object position but destroys the object once the object it's attached to no logner exists.

If you're worried about deleting the fxLight when the projectile hits something you could define a function called <your projectile datablock>::onCollision(%this, %obj, %col, %fade, %pos, %normal, %velocity) and call %obj.light.delete() in it (I think?). You'd also have to add light = %light to the code block where you instantiate the projectile.

In which method could i constantly update the position?
OnFire is called only once for each fired projectile.
« Last Edit: May 08, 2018, 10:16:44 AM by The 1 »

you'd have to create a separate function that loops and then call it from onFire

for example: (not tested) this would update the position of the light every 100ms to match the position of the projectile
Code: [Select]
function fxLight::updatePositionLoop(%light, %projectile)
{
cancel(%light.updatePositionSchedule);

%light.setTransform(%projectile.getPosition());

%light.updatePositionSchedule = %light.schedule(100, updatePositionLoop);
}

And then call %light.updatePositionLoop(%p); from where you're instantiating the projectile. Might want to throw an isObject check in there somewhere idk

it'll be pritty laggy tho