Page 1 of 1

Scripting 08 - Projectile manipulation

Posted: Fri Jul 26, 2019 12:20 pm
by Gurt
Scripting 08 - Projectile manipulation

Scripting in SFD assumes you have a fair knowledge of C#.

The following code demonstrates how to manipulate projectiles and listen on projectile hit events in v.1.3.0 (OnProjectileCreated event in v.1.3.1).

Code: Select all

// Example script to manipulate projectiles
public void OnStartup()
{
	Events.UpdateCallback.Start(OnUpdate, 0);
	Events.ProjectileCreatedCallback.Start(OnProjectileCreated);
	Events.ProjectileHitCallback.Start(OnProjectileHit);
}

public void OnProjectileCreated(IProjectile[] projectiles)
{
	// Created projectiles, not yet run their first update cycle.
	foreach(IProjectile projectile in projectiles) {
		Game.WriteToConsole(string.Format("Projectile {0} created", projectile.InstanceID));
	}
}

public void OnProjectileHit(IProjectile projectile, ProjectileHitArgs args)
{
	Game.WriteToConsole(string.Format("Projectile {0} hit {1} {2} for {3} damage", projectile.InstanceID, (args.IsPlayer ? "player" : "object"), args.HitObjectID, args.Damage));

}

public void OnUpdate(float ms)
{	
	foreach (IProjectile proj in Game.GetProjectiles())
	{
		// lower velocity for bazooka rockets to 300
		if (proj.ProjectileItem == ProjectileItem.BAZOOKA) 
		{
			if (proj.Velocity.Length() > 301f)
			{
				proj.Velocity = proj.Direction * 300f;
			}
		}
		// shotguns can only reach 200 world units
		if (proj.ProjectileItem == ProjectileItem.SHOTGUN || proj.ProjectileItem == ProjectileItem.DARK_SHOTGUN)
		{
			if (proj.TotalDistanceTraveled > 200f) 
			{
				proj.FlagForRemoval();
			}
		}
		
		// pistols rounds affected by gravity
		if (proj.ProjectileItem == ProjectileItem.PISTOL) 
		{
			proj.Velocity = new Vector2(proj.Velocity.X, proj.Velocity.Y - 0.3f * ms);
		}

	}
}

You can do all kinds of interesting things with projectiles. But changing position and velocity too often and too suddenly can make the projectiles look jittery and buggy on clients if the client have a fluctuating ping (which makes the client-side prediction fail - it can't predict what you want to do in your code :P). It's just how it is. Keep that in mind when testing your code in the editor vs a public game.

Note: If you only want to listen on player damage you could use the PlayerDamageCallback event instead. See viewtopic.php?f=22&t=3771

IProjectile Implementation
► Show Spoiler

Re: Scripting 08 - Projectile manipulation

Posted: Fri Jul 26, 2019 1:43 pm
by NearHuscarl
Does IProjectile have the ID of the player who shot it? I want to know if player B is shot by player A, but it can't be implemented cleanly with the current version of the script API

Re: Scripting 08 - Projectile manipulation

Posted: Fri Jul 26, 2019 2:30 pm
by Gurt
NearHuscarl wrote:
Fri Jul 26, 2019 1:43 pm
Does IProjectile have the ID of the player who shot it? I want to know if player B is shot by player A, but it can't be implemented cleanly with the current version of the script API
You have the properties for initialOwnerPlayerID and ownerPlayerID. The initialOwnerPlayerID is the original owner of the projectile while ownerPlayerID is updated with each bounce/deflection of the projectile.

You will have to refer to the full ScriptAPI after the update is released for more details.

Re: Scripting 08 - Projectile manipulation

Posted: Fri Aug 02, 2019 8:32 am
by Danger Ross
Very cool update!

but is there any way to detect whether or not the projectile hit callback event is of the projectile hitting an object that stops it?
As in, a way to filter detection of objects that the projectile ignores in its trajectory.
I'm asking this because I want the projectile to leave behind something after being removed, but it's uncertain when that will happen when relying on the event call.

also a small suggestion: could you make the Game.SpawnProjectile() method return an IProjectile object instead of void? thanks!

Re: Scripting 08 - Projectile manipulation

Posted: Fri Aug 02, 2019 12:15 pm
by Gurt
Good suggestions. Adding it after v.1.3.0b.
ScriptAPI: Updated IGame.SpawnProjectile(). It now returns the created IProjectile instance (can return null).
ScriptAPI: Updated ProjectileHitArgs with new property bool RemoveFlag to determine if the projectile is going to be removed by the hit or not.