示例#1
0
// Weapon Update
void Weapon::Update(float aStep)
{
	// get controller
	const Controller *controller = Database::controller.Get(mControlId);
	if (!controller)
		return;

	// advance fire timer
	mTimer += aStep;

	// get template data
	const WeaponTemplate &weapon = Database::weapontemplate.Get(mId);

	// get trigger value
	float fire = controller->mFire[mChannel];
	bool trigger;
	switch (weapon.mTrigger)
	{
	default:
	case WeaponTemplate::TRIGGER_HOLD: trigger = fire != 0; break;
	case WeaponTemplate::TRIGGER_PRESS: trigger = fire != 0 && mPrevFire == 0; break;
	case WeaponTemplate::TRIGGER_RELEASE: trigger = fire == 0 && mPrevFire != 0; break;
	}
	mPrevFire = fire;

	// if triggered...
	if (trigger)
	{
		// if not busy
		if (mBurst <= 0 && mTimer > -0.001f && (!weapon.mTrack || mTrack < weapon.mTrack))
		{
			// if firing on this phase...
			if (mPhase == 0)
			{
				Resource *resource = NULL;

				// if using ammo
				if (weapon.mCost)
				{
					// ammo resource (if any)
					resource = Database::resource.Get(mAmmo).Get(weapon.mType);
				}

				// if enough ammo...
				if (!resource || weapon.mCost <= resource->GetValue())
				{
					// deduct ammo
					if (resource)
						resource->Add(mId, -weapon.mCost);

					// start a new burst
					mTimer -= weapon.mBurstStart;
					mBurst = weapon.mBurstLength;
				}
				else
				{
					// start "empty" sound cue
					PlaySoundCue(mId, 0x18a7beee /* "empty" */);
				}

				// wrap around
				mPhase = weapon.mCycle - 1;
			}
			else
			{
				// advance phase
				--mPhase;

				// wait for next phase
				mTimer -= weapon.mDelay / weapon.mCycle;
			}
		}
	}

	// if ready to fire...
	while (mBurst > 0 && mTimer > -0.001f && (!weapon.mTrack || mTrack < weapon.mTrack))
	{
		// deduct a burst
		--mBurst;

		// get the entity
		Entity *entity = Database::entity.Get(mId);

		// start the "fire" sound cue
		PlaySoundCue(mId, 0x8eab16d9 /* "fire" */);

		// interpolated transform
		Transform2 basetransform(entity->GetInterpolatedTransform(mTimer / aStep));

		for (int salvo = 0; salvo < weapon.mSalvoShots; ++salvo)
		{
			// get local position
			Transform2 position(weapon.mOffset);

			// apply transform offset
			Transform2 transform(position * basetransform);

			if (weapon.mRecoil)
			{
				// apply recoil force
				for (unsigned int id = mId; id != 0; id = Database::backlink.Get(id))
				{
					if (Collidable *collidable = Database::collidable.Get(id))
					{
						collidable->GetBody()->ApplyImpulse(transform.Rotate(Vector2(0, -weapon.mRecoil)), transform.p);
						break;
					}
				}
			}

			if (weapon.mFlash)
			{
				// instantiate a flash
				unsigned int flashId = Database::Instantiate(weapon.mFlash, Database::owner.Get(mId), mId,
					transform.Angle(), transform.p, entity->GetVelocity(), entity->GetOmega());

				// set fractional turn
				if (Renderable *renderable = Database::renderable.Get(flashId))
					renderable->SetFraction(mTimer / aStep);

				// link it (HACK)
				LinkTemplate linktemplate;
				linktemplate.mOffset = weapon.mOffset;
				linktemplate.mSub = flashId;
				linktemplate.mSecondary = flashId;
				Link *link = new Link(linktemplate, mId);
				Database::Typed<Link *> &links = Database::link.Open(mId);
				links.Put(flashId, link);
				Database::link.Close(mId);
				link->Activate();
			}

			if (weapon.mOrdnance)
			{
				// TO DO: consolidate this with similar spawn patterns (Graze, Spawner)

				// apply position scatter
				position.a += Random::Value(0.0f, weapon.mScatter.a);
				position.p.x += Random::Value(0.0f, weapon.mScatter.p.x);
				position.p.y += Random::Value(0.0f, weapon.mScatter.p.y);

				// get world position
				position *= basetransform;

				// get local velocity
				Transform2 velocity(entity->GetOmega(), position.Unrotate(entity->GetVelocity()));

				// apply velocity inherit
				velocity.a *= weapon.mInherit.a;
				velocity.p.x *= weapon.mInherit.p.x;
				velocity.p.y *= weapon.mInherit.p.y;

				// apply velocity add
				velocity.a += weapon.mVelocity.a;
				velocity.p.x += weapon.mVelocity.p.x;
				velocity.p.y += weapon.mVelocity.p.y;

				// apply velocity variance
				velocity.a += Random::Value(0.0f, weapon.mVariance.a);
				velocity.p.x += Random::Value(0.0f, weapon.mVariance.p.x);
				velocity.p.y += Random::Value(0.0f, weapon.mVariance.p.y);

				// apply velocity aim
				velocity.p.x += controller->mAim.x * weapon.mAim.x;
				velocity.p.y += controller->mAim.y * weapon.mAim.y;

				// get world velocity
				velocity.p = position.Rotate(velocity.p);

				// instantiate a bullet
				unsigned int ordId = Database::Instantiate(weapon.mOrdnance, Database::owner.Get(mId), mId, position.a, position.p, velocity.p, velocity.a);
#ifdef DEBUG_WEAPON_CREATE_ORDNANCE
				DebugPrint("ordnance=\"%s\" owner=\"%s\"\n",
					Database::name.Get(ordId).c_str(),
					Database::name.Get(Database::owner.Get(ordId)).c_str());
#endif

				// set fractional turn
				if (Renderable *renderable = Database::renderable.Get(ordId))
					renderable->SetFraction(mTimer / aStep);

				// if tracking....
				if (weapon.mTrack)
				{
					// add a tracker
					Database::weapontracker.Put(ordId, WeaponTracker(mId));
				}
			}
		}

		// update weapon delay
		if (mBurst > 0)
			mTimer -= weapon.mBurstDelay;
		else
			mTimer -= (weapon.mDelay - weapon.mBurstStart - weapon.mBurstDelay * (weapon.mBurstLength - 1)) / weapon.mCycle;
	}

	if (mTimer > 0.0f)
	{
		// clamp fire delay
		mTimer = 0.0f;
	}
}
示例#2
0
// spawner update
void Spawner::Update(float aStep)
{
	// get the spawner template
	const SpawnerTemplate &spawner = Database::spawnertemplate.Get(mId);

	// skip if limit reached
	if (spawner.mTrack && mTrack >= spawner.mTrack)
		return;

	// advance the timer
	mTimer += aStep;

	// if the timer elapses...
	while (mTimer > 0.0f)
	{
		// get the spawner entity
		Entity *entity = Database::entity.Get(mId);
		if (!entity)
			return;

		// TO DO: consolidate this with similar spawn patterns (Graze, Weapon)

		// interpolated transform
		Transform2 transform(entity->GetInterpolatedTransform(mTimer / aStep));

		// apply transform offset
		transform = spawner.mOffset * transform;

		// apply transform scatter
		if (spawner.mScatter.a)
			transform.a += Random::Value(0.0f, spawner.mScatter.a);
		if (spawner.mScatter.p.x)
			transform.p.x += Random::Value(0.0f, spawner.mScatter.p.x);
		if (spawner.mScatter.p.y)
			transform.p.y += Random::Value(0.0f, spawner.mScatter.p.y);

		// get local velocity
		Transform2 velocity(entity->GetOmega(), transform.Unrotate(entity->GetVelocity()));

		// apply velocity inherit
		velocity.a *= spawner.mInherit.a;
		velocity.p.x *= spawner.mInherit.p.x;
		velocity.p.y *= spawner.mInherit.p.y;

		// apply velocity add
		velocity.a += spawner.mVelocity.a;
		velocity.p.x += spawner.mVelocity.p.x;
		velocity.p.y += spawner.mVelocity.p.y;

		// apply velocity variance
		if (spawner.mVariance.a)
			velocity.a += Random::Value(0.0f, spawner.mVariance.a);
		if (spawner.mVariance.p.x)
			velocity.p.x += Random::Value(0.0f, spawner.mVariance.p.x);
		if (spawner.mVariance.p.y)
			velocity.p.y += Random::Value(0.0f, spawner.mVariance.p.y);

		// get world velocity
		velocity.p = transform.Rotate(velocity.p);

		// apply fractional turn (HACK)
		transform.a += velocity.a * (aStep - mTimer);
		transform.p += velocity.p * (aStep - mTimer);

		// instantiate the spawn entity
		if (unsigned int spawnId = Database::Instantiate(spawner.mSpawn, Database::owner.Get(mId), mId, transform.a, transform.p, velocity.p, velocity.a, false))
		{
			// if the spawner has a team...
			unsigned int team = Database::team.Get(mId);
			if (team)
			{
				// propagate team to spawned item
				Database::team.Put(spawnId, team);
			}

			// activate
			Database::Activate(spawnId);

			// set fractional turn
			if (Renderable *renderable = Database::renderable.Get(spawnId))
				renderable->SetFraction(mTimer / aStep);

			// if tracking....
			if (spawner.mTrack)
			{
				// add a tracker
				Database::spawnertracker.Put(spawnId, SpawnerTracker(mId));
			}
		}

		// set the timer
		mTimer -= spawner.mCycle;

		// if tracking....
		if (spawner.mTrack)
		{
			// stop if out of slots
			if (mTrack >= spawner.mTrack)
				break;
		}
	}
}