示例#1
0
void Pickup::Kill(float aFraction)
{
	const PickupTemplate &pickup = Database::pickuptemplate.Get(mId);

	// if spawning on pickup...
	if (pickup.mSpawnOnCollect)
	{
		// get the entity
		Entity *entity = Database::entity.Get(mId);
		if (entity)
		{
			// spawn template at entity location
			unsigned int spawnId = Database::Instantiate(pickup.mSpawnOnCollect, Database::owner.Get(mId), mId,
				entity->GetAngle(), entity->GetPosition(), entity->GetVelocity(), entity->GetOmega());
			if (Renderable *renderable = Database::renderable.Get(spawnId))
				renderable->SetFraction(aFraction);
		}
	}

	// if switching on pickup...
	if (pickup.mSwitchOnCollect)
	{
		// change dynamic type
		unsigned int aId = mId;
		Database::Switch(aId, pickup.mSwitchOnCollect);
		if (Renderable *renderable = Database::renderable.Get(aId))
			renderable->SetFraction(aFraction);
	}
	else
	{
		// delete the entity
		Database::Delete(mId);
	}

	return;
}
示例#2
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;
	}
}
示例#3
0
// Gunner Update
void Gunner::Update(float aStep)
{
	// get the owner
	unsigned int aOwnerId = Database::backlink.Get(mId);

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

	// if the owner does not exist...
	if (!owner)
	{
		// self-destruct
		Database::Delete(mId);
		return;
	}

	// gunner template
	const GunnerTemplate &gunner = Database::gunnertemplate.Get(mId);

	// get owner movement
	const Vector2 &posP = owner->GetPosition();
#ifdef GUNNER_TRACK_DEQUE
	const Vector2 &posL0 = mTrackPos.back();
#else
	const Vector2 &posL0 = mTrackPos[mTrackLast];
#endif
	float movement = posP.DistSq(posL0);

	// if the owner has moved...
	if (movement > FLT_EPSILON)
	{
#ifdef GUNNER_TRACK_DEQUE
		// get the last segment
		const Vector2 &posL1 = mTrackPos[mTrackPos.size()-2];
		float lastsegment = posL0.Dist(posL1);

		// if the last segment isn't long enough...
		if (lastsegment < GUNNER_TRACK_GRANULARITY)
		{
			// replace the last segment
			mTrackPos.pop_back();
			mTrackLength -= lastsegment;
		}

		// add new position
		mTrackPos.push_back(posP);
		mTrackLength += posP.Dist(mTrackPos[mTrackPos.size()-2]);
#else
		// get the last segment
		size_t mTrackPrev = (mTrackLast > 0) ? (mTrackLast - 1) : (mTrackCount - 1);
		const Vector2 &posL1 = mTrackPos[mTrackPrev];
		float lastsegment = posL0.Dist(posL1);

		// if the last segment is long enough...
		if (lastsegment >= GUNNER_TRACK_GRANULARITY)
		{
			// start a new segment
			mTrackPrev = mTrackLast;
			mTrackLast = (mTrackLast < mTrackCount - 1) ? (mTrackLast + 1) : 0;
		}
		else
		{
			// replace the last segment
			mTrackLength -= lastsegment;
		}

		// add new position
		mTrackPos[mTrackLast] = posP;
		mTrackLength += posP.Dist(mTrackPos[mTrackPrev]);
#endif

		// while there is excess track length...
		while (mTrackLength > gunner.mFollowLength)
		{
			// get the excess length
			float excess = mTrackLength - gunner.mFollowLength;

			// get the first segment length
#ifdef GUNNER_TRACK_DEQUE
			Vector2 &pos0 = mTrackPos[0];
			const Vector2 &pos1 = mTrackPos[1];
#else
			size_t mTrackNext = (mTrackFirst < mTrackCount - 1) ? (mTrackFirst + 1) : 0;
			Vector2 &pos0 = mTrackPos[mTrackFirst];
			const Vector2 &pos1 = mTrackPos[mTrackNext];
#endif
			float firstsegment = pos0.Dist(pos1);

			// if the segment is longer than the excess...
			if (firstsegment > excess)
			{
				// shorten the segment
				pos0 += excess / firstsegment * (pos1 - pos0);
				mTrackLength -= excess;
				break;
			}
			else
			{
				// remove the segment
				mTrackLength -= firstsegment;
#ifdef GUNNER_TRACK_DEQUE
				mTrackPos.pop_front();
#else
				mTrackFirst = mTrackNext;
#endif
			}
		}
	}

	// move to new position
	Entity *entity = Database::entity.Get(mId);
	entity->Step();
#ifdef GUNNER_TRACK_DEQUE
	entity->SetPosition(mTrackPos.front());
#else
	entity->SetPosition(mTrackPos[mTrackFirst]);
#endif
	entity->SetAngle(owner->GetAngle());
	entity->SetVelocity(owner->GetVelocity());	// <-- HACK!
	entity->SetOmega(owner->GetOmega());
}
示例#4
0
// cancel
void Cancelable::Cancel(unsigned int aId, unsigned int aSourceId)
{
	const CancelableTemplate &cancelable = Database::cancelabletemplate.Get(mId);

	// set owner to source damage owner
	unsigned int aOwnerId = Database::owner.Get(aSourceId);
	Database::owner.Put(mId, aOwnerId);

	// bump the hit combo counter
	int &combo = Database::hitcombo.Open(mId);
	combo = std::max<int>(combo, Database::hitcombo.Get(aSourceId) + 1);
	Database::hitcombo.Close(mId);

	if (cancelable.mBacklash)
	{
		for (unsigned int creator = Database::creator.Get(aId); creator != 0; creator = Database::backlink.Get(creator))
		{
			if (Damagable *damagable = Database::damagable.Get(creator))
			{
				Damagable::DeathSignal &signal = Database::deathsignal.Open(creator);
				signal.Disconnect(this, &Cancelable::CreatorDeath);
				Database::deathsignal.Close(creator);

//				damagable->Damage(mId, cancelable.mBacklash);

				// burn tether from the cancelable to the creator
				new TetherBurn(creator, mId, aOwnerId, cancelable.mBacklash, combo);
				break;
			}
		}
	}

	// if spawning on cancelable...
	if (cancelable.mSpawn)
	{
		// get the entity
		Entity *entity = Database::entity.Get(mId);
		if (entity)
		{
			// spawn template at the entity location
			Database::Instantiate(cancelable.mSpawn, Database::owner.Get(mId), mId, entity->GetAngle(), entity->GetPosition(), entity->GetVelocity(), entity->GetOmega());
		}
	}

	// if switching on cancelable...
	if (cancelable.mSwitch)
	{
		// get the entity
		Entity *entity = Database::entity.Get(mId);
		if (entity)
		{
			// change dynamic type
			Database::Switch(mId, cancelable.mSwitch);
		}
	}
	else
	{
		// delete the entity
		Database::Delete(mId);
	}
}
示例#5
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;
		}
	}
}
示例#6
0
void Capturable::Capture(void)
{
	const CapturableTemplate &capturable = Database::capturabletemplate.Get(mId);

	// if spawning on capture...
	if (capturable.mSpawnOnCapture)
	{
		// get the entity
		Entity *entity = Database::entity.Get(mId);
		if (entity)
		{
			// instantiate the template
			Database::Instantiate(capturable.mSpawnOnCapture, Database::owner.Get(mId), mId, entity->GetAngle(), entity->GetPosition(), entity->GetVelocity(), entity->GetOmega());
		}
	}

	// if switching on capture...
	if (capturable.mSwitchOnCapture)
	{
		// change dynamic type
		Database::Switch(mId, capturable.mSwitchOnCapture);
	}
	else
	{
		// delete the entity
		Database::Delete(mId);
	}
}