Modding/DamagePacket/Projectile

## Implementation

```
declare interface ProjectileTemplate extends DamagePacketTemplate {
 damage: number;

 partialDamage?: PartialDamageParameters; // Scale damage over time
 partialDetonateRadius?: PartialDamageParameters; // Scale detonate radius over time, only useful if detonate set
 partialDetonateImpulse?: PartialDamageParameters; // Scale detonate impulse over time, only useful if detonate set
 partialBuffDuration?: PartialDamageParameters; // Scale buff durations over time, only useful if buffs set

 ccd?: boolean; // Performance improvement: Whether to apply continuous collision detection to this projectile. Small and fast projectiles will tunnel through other objects unless CCD is on. Defaults to true.
 density: number;
 radius: number;
 square?: boolean; // A square projectile will push things directly backwards, not to the side

 speed: number;
 fixedSpeed?: boolean; // if true or undefined, the projectile's speed will be corrected according to ProjectileSpeedDecayFactorPerTick if it becomes faster or slower due to collisions
 speedDecayPerTick?: number; // if set, the projectile's speed will be corrected according to this proportion per tick if it becomes faster or slower due to collisions
 speedDamping?: number; // Controls how quickly the projectile loses speed (does not work if the projectile speeds itself back up again using fixedSpeed or speedDecayPerTick)

 restitution?: number; // 1 means very bouncy, 0 means not bouncy

 attractable?: AttractableTemplate; // Whether the "attract" behaviour (e.g. a whirlwind) can affect this projectile
 swappable?: boolean; // Whether this projectile can be swapped with
 bumpable?: boolean; // Whether this projectile gets knocked back by a bumper obstacle
 conveyable?: boolean; // Whether this projectile is moved by a conveyor belt. (Collision flags must allow the projectile collide with obstacles to work.)
 linkable?: boolean; // Whether a link can attach to this projectile
 destroying?: boolean; // Whether to destroy any projectiles marked as destructible on contact

 hitInterval?: number; // If set, the projectile is allowed to hit enemies multiple times, as long as the ticks between hits is at least this number
 bounce?: BounceParameters;
 link?: LinkParameters;
 horcrux?: HorcruxParameters;
 detonate?: DetonateParametersTemplate;
 gravity?: GravityParameters; // Trap a hero
 swapWith?: number; // Category flags of what types of objects to swap with
 lifeSteal?: number; // 1.0 means all damage is returned as health to the owner of the projectile

 projectileBuffs?: BuffTemplate[]; // Apply these buffs to the owner as long as the projectile is alive
 buffs?: BuffTemplate[]; // Apply these buffs to whatever the projectile hits
 behaviours?: BehaviourTemplate[];

 minTicks?: number; // The minimum number of ticks that a projectile will live for. The main purpose of this is to work around a quirk in the physics engine where if projectiles doesn't live for more than 1 tick, it doesn't affect the physics.
 maxTicks: number; // The maximum number of ticks that a projectile will live for. The maximum range can be determined by speed \* maxTicks / TicksPerSecond.
 categories?: number; // Collision flags: What flags this object has
 collideWith?: number; // Collision flags: Which other objects to collide with
 expireOn?: number; // Collision flags: The projectile will expire if it hits any of these objects
 expireAgainstHeroes?: number; // Alliance flags: Whether to expire against enemies only, etc
 expireAgainstObjects?: number; // Alliance flags: Whether to expire against enemies only, etc
 expireOnMirror?: boolean; // Whether to hit mirrors or not
 sensor?: boolean; // A sensor will just pass through all objects and report what it would have collided with
 sense?: number; // Collision flags: Detect when we pass over these objects - different from sensor in that the object can still collide with some things while sensing others
 selfPassthrough?: boolean; // Whether the projectile just passes through its owner
 destructible?: DestructibleParameters; // Whether this projectile is destroyed by a detonate (like a Supernova)
 expireAfterCursorTicks?: number; // Expire this many ticks after the cursor is reached
 shieldTakesOwnership?: boolean; // If the projectile hits a shield, does it switch owner?

 color: string;
 renderers: RenderParams[]; // Which render function to use
 sound?: string;
 soundHit?: string;

 spawnAtCursor?: boolean;
 cursorMaxDistance?: number; // Max distance the cursor can be to spawn at cursor
}

```