private JobHandle ScheduleWaterWeapon(PlayerShootJobData jobData, JobHandle deps)
    {
        if (!bubbleData.IsCreated)
        {
            bubbleData = new NativeArray <WaterShootData>(
                players.CalculateEntityCount(),
                Allocator.Persistent);
        }

        JobHandle job = new WaterShootJob {
            data                = jobData,
            bubbleData          = bubbleData,
            maxChargeTime       = maxChargeTime,
            bubbleBurstTopSpeed = bubbleBurstTopSpeed
        }.Schedule(players, deps);

        Random rnd = new Random();

        rnd.InitState((uint)(UnityEngine.Random.value * uint.MaxValue));
        job = new WaterShootUpdateBulletJob {
            commandBuffer = jobData.commandBuffer,
            bubbleData    = bubbleData,
            rnd           = rnd,
            effectReqUtil = effectSystem.GetUtility(),
        }.Schedule(waterBullets, job);

        job = new WaterShootPostUpdateJob {
            data       = jobData,
            bubbleData = bubbleData
        }.Schedule(players, job);

        commandBufferSystem.AddJobHandleForProducer(job);
        return(job);
    }
    /*
     *  Basic weapon
     *
     *  Just fires bullets, no special properties
     */

    private JobHandle ScheduleBasicWeapon(PlayerShootJobData jobData, JobHandle deps)
    {
        JobHandle shootJob = new PlayerShootJob {
            data = jobData
        }.Schedule(players, deps);

        // tells buffer systems to wait for the job to finish, then
        //   it will perform the commands buffered
        commandBufferSystem.AddJobHandleForProducer(shootJob);

        return(shootJob);
    }
    /*
     *  Boost Weapon: Basic + Water
     *
     *  Consistently shoots in the same pattern as water's burst
     */

    private JobHandle ScheduleBoostBasicWaterWeapon(PlayerShootJobData jobData, JobHandle deps)
    {
        Random rnd = new Random();

        rnd.InitState((uint)(UnityEngine.Random.value * uint.MaxValue));
        JobHandle shootJob = new BoostBasicWaterJob {
            data = jobData,
            rnd  = rnd
        }.Schedule(players, deps);

        // tells buffer systems to wait for the job to finish, then
        //   it will perform the commands buffered
        commandBufferSystem.AddJobHandleForProducer(shootJob);

        return(shootJob);
    }
    protected override JobHandle OnUpdate(JobHandle deps)
    {
        PlayerShootJobData data = new PlayerShootJobData {
            commandBuffer     = commandBufferSystem.CreateCommandBuffer().ToConcurrent(),
            dt                = Time.deltaTime,
            bulletHeight      = Constants.PLAYER_BULLET_HEIGHT,
            timePassedBuffers = GetBufferFromEntity <TimePassed>(false),
            shooting          = (Input.GetAxis("Fire1") > 0)
        };

        if (Input.GetKeyDown(KeyCode.E) && !data.shooting)
        {
            useFirstWeapon = !useFirstWeapon;
        }
        NativeArray <Entity> player = players.ToEntityArray(Allocator.TempJob);

        PlayerStats.WeaponTypes weapon    = PlayerStats.WeaponTypes.None;
        PlayerStats             currStats = PlayerStats.statsMap[player[0]];

        // start boost mode
        if (currStats.boostCharges == currStats.maxCharges && currStats.remainingBoostDuration == 0)
        {
            if (Input.GetKeyDown(KeyCode.Q))
            {
                currStats.remainingBoostDuration = currStats.boostDuration;
            }
        }

        // pick the relavent weapon
        // in boost mode
        if (currStats.remainingBoostDuration > 0)
        {
            currStats.remainingBoostDuration -= data.dt;
            weapon = currStats.firstWeapon | currStats.secondWeapon;

            // end boost mode
            if (currStats.remainingBoostDuration <= 0)
            {
                currStats.boostCharges           = 0;
                currStats.remainingBoostDuration = 0;
            }
        }
        // out of boost mode
        else if (useFirstWeapon)
        {
            weapon = currStats.firstWeapon;
        }
        else
        {
            weapon = currStats.secondWeapon;
        }

        if (weaponSchedulers.ContainsKey(weapon))
        {
            deps = weaponSchedulers[weapon](data, deps);
        }
        else
        {
            Debug.LogWarning("No job set for " + weapon);
        }
        currStats.activeWeapon = weapon;

        player.Dispose();

        return(deps);
    }