// render void PlayerOverlaySpecial::Render(unsigned int aId, float aTime, const Transform2 &aTransform) { // get the player Player *player = Database::player.Get(aId); // get the player entity (HACK) unsigned int id = player->GetId(); // get "special" ammo resource (HACK) Resource *specialresource = Database::resource.Get(id).Get(0xd940d530 /* "special" */); if (!specialresource) return; int new_special = xs_FloorToInt(specialresource->GetValue()); // if the special has not changed... if (new_special == cur_special && !wasreset) { // call the existing draw list glCallList(special_handle); return; } // update special cur_special = new_special; // start a new draw list list glNewList(special_handle, GL_COMPILE_AND_EXECUTE); // draw the special ammo icon glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(specialpos.x, specialpos.y, 0.0f); glScalef(4, 4, 1); glCallList(Database::drawlist.Get(0x8cdedbba /* "circle16" */)); glPopMatrix(); // draw remaining special ammo char special[16]; sprintf(special, "x%d", cur_special); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glBegin(GL_QUADS); float w = 8; float h = -8; float x = specialpos.x + 8; float y = specialpos.y - 0.5f * h; float z = 0; OGLCONSOLE_DrawString(special, x, y, w, h, z); glEnd(); glDisable(GL_TEXTURE_2D); glEndList(); }
// 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; } }
// render void PlayerOverlayLevel::Render(unsigned int aId, float aTime, const Transform2 &aTransform) { // get the player Player *player = Database::player.Get(aId); // get the attached entity identifier unsigned int id = player->mAttach; // get level resource Resource *levelresource = Database::resource.Get(id).Get(0x9b99e7dd /* "level" */); if (!levelresource) return; int new_level = xs_FloorToInt(levelresource->GetValue()); float new_part = levelresource->GetValue() - new_level; // if the level has not changed... if (new_part == cur_part && new_level == cur_level && !wasreset) { // call the existing draw list glCallList(level_handle); return; } // update level cur_level = new_level; cur_part = new_part; // start a new draw list list glNewList(level_handle, GL_COMPILE_AND_EXECUTE); // draw level gauge glBegin(GL_QUADS); // background glColor4fv(levelcolor[cur_level]); glVertex2f(levelrect.x, levelrect.y); glVertex2f(levelrect.x + levelrect.w, levelrect.y); glVertex2f(levelrect.x + levelrect.w, levelrect.y + levelrect.h); glVertex2f(levelrect.x, levelrect.y + levelrect.h); // fill gauge glColor4fv(levelcolor[cur_level+1]); glVertex2f(levelrect.x, levelrect.y); glVertex2f(levelrect.x + levelrect.w * cur_part, levelrect.y); glVertex2f(levelrect.x + levelrect.w * cur_part, levelrect.y + levelrect.h); glVertex2f(levelrect.x, levelrect.y + levelrect.h); glEnd(); // draw the level icon glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(levelpos.x, levelpos.y, 0.0f); glScalef(4, 4, 1); glCallList(Database::drawlist.Get(0x8cdedbba /* "circle16" */)); glPopMatrix(); // draw level number char level[16]; sprintf(level, "x%d", cur_level); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glBegin(GL_QUADS); float w = 8; float h = -8; float x = levelpos.x + 8; float y = levelpos.y - 0.5f * h; float z = 0; OGLCONSOLE_DrawString(level, x, y, w, h, z); glEnd(); glDisable(GL_TEXTURE_2D); glEndList(); }
// render void PlayerOverlayAmmo::Render(unsigned int aId, float aTime, const Transform2 &aTransform) { // get the player Player *player = Database::player.Get(aId); // get the attached entity identifier unsigned int id = player->mAttach; // draw player ammo (HACK) Resource *ammoresource = Database::resource.Get(id).Get(0x5b9b0daf /* "ammo" */); if (!ammoresource) return; // get ammo ratio float new_ammo = 0.0f; const ResourceTemplate &ammoresourcetemplate = Database::resourcetemplate.Get(id).Get(0x5b9b0daf /* "ammo" */); if (ammoresourcetemplate.mMaximum > 0) { new_ammo = ammoresource->GetValue() / ammoresourcetemplate.mMaximum; } // get level int new_level = 1; Resource *levelresource = Database::resource.Get(id).Get(0x9b99e7dd /* "level" */); if (levelresource) { new_level = xs_FloorToInt(levelresource->GetValue()); } // if the lives count has not changed... if (new_ammo == cur_ammo && new_level == cur_level && glIsList(ammo_handle)) { // call the existing draw list glCallList(ammo_handle); return; } // update ammo cur_ammo = new_ammo; cur_level = new_level; // start a new draw list list glNewList(ammo_handle, GL_COMPILE_AND_EXECUTE); glBegin(GL_QUADS); // background glColor4fv(ammocolor[cur_level]); glVertex2f(ammorect.x, ammorect.y); glVertex2f(ammorect.x + ammorect.w, ammorect.y); glVertex2f(ammorect.x + ammorect.w, ammorect.y + ammorect.h); glVertex2f(ammorect.x, ammorect.y + ammorect.h); // fill gauge glColor4fv(ammocolor[cur_level+1]); glVertex2f(ammorect.x, ammorect.y); glVertex2f(ammorect.x + ammorect.w * cur_ammo, ammorect.y); glVertex2f(ammorect.x + ammorect.w * cur_ammo, ammorect.y + ammorect.h); glVertex2f(ammorect.x, ammorect.y + ammorect.h); glEnd(); glEndList(); }