/*! In \a phase 0, increment the missile's age and return if the missile has expired. If not, move the missile based on its current position and velocity. Then get the its list of colliding sprites and traverse the list. When a rock is found in the list, mark both the rock and the missile dead and return. In phase 1, if the missile is marked dead, delete it; \internal */ void KMissile::advance(int phase) { if (phase == 0) { if (dying()) markDead(); else incrementAge(); if (isDead()) return; KSprite::advance(phase); QList<QGraphicsItem*> hits = collidingItems(); QList<QGraphicsItem*>::iterator i; for (i=hits.begin(); i!=hits.end(); ++i) { if ((*i)->type() > ID_Base) { KSprite* sprite = (KSprite*)(*i); if (sprite->isRock()) { sprite->markDead(); markDead(); break; } } } } else if (isDead() || dying()) delete this; }
void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys) { LLViewerObject* source_object = (LLViewerObject*)mSourceObject; if (!source_object) { markDead(); return; } else if (!source_object->isAvatar()) { LL_DEBUGS("HUDEffect")<<"Non-Avatar HUDEffectBeam message for ID: " << source_object->getID().asString()<< LL_ENDL; markDead(); return; } else { LLVOAvatar* source_avatar = (LLVOAvatar*)source_object; if (!source_avatar->isSelf()) { LL_DEBUGS("HUDEffect")<<"Non-self HUDEffectBeam message for ID: " << source_avatar->getID().asString()<< LL_ENDL; markDead(); return; } } // Pack the default data LLHUDEffect::packData(mesgsys); // Pack the type-specific data. Uses a fun packed binary format. Whee! // 16 + 24 + 1 = 41 U8 packed_data[41]; memset(packed_data, 0, 41); if (mSourceObject) { htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16); } if (mTargetObject) { packed_data[16] = 1; } else { packed_data[16] = 0; } if (mTargetObject) { htonmemcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16); } else { htonmemcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24); } mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); }
void LLSpatialBridge::updateDistance(LLCamera& camera_in) { if (mDrawable == NULL) { markDead(); return; } LLCamera camera = transformCamera(camera_in); mDrawable->updateDistance(camera); if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* child = *iter; LLDrawable* drawable = child->mDrawable; if (!drawable) { llwarns << "Corrupt drawable found while updating spatial bridge distance." << llendl; continue; } if (!drawable->isAvatar()) { drawable->updateDistance(camera); } } } }
void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) { if (mDrawable == NULL) { markDead(); return; } LLCamera camera = transformCamera(camera_in); mDrawable->updateDistance(camera, force_update); if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* child = *iter; LLDrawable* drawable = child->mDrawable; if (!drawable) { continue; } if (!drawable->isAvatar()) { drawable->updateDistance(camera, force_update); } } } }
//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::update() { static const LLCachedControl<bool> show_look_at("AscentShowLookAt", false); // If the target object is dead, set the target object to NULL if (!mTargetObject.isNull() && mTargetObject->isDead()) { clearLookAtTarget(); } // if source avatar is null or dead, mark self as dead and return if (mSourceObject.isNull() || mSourceObject->isDead()) { markDead(); return; } // make sure the proper set of avatar attention are currently being used. LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; // for now the first cut will just switch on sex. future development could adjust // timeouts according to avatar age and/or other features. mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); F32 time = mTimer.getElapsedTimeF32(); // clear out the effect if time is up if (mKillTime != 0.f && time > mKillTime) { if (mTargetType != LOOKAT_TARGET_NONE) { clearLookAtTarget(); // look at timed out (only happens on own avatar), so tell everyone setNeedsSendToSim(TRUE); } } if (mTargetType != LOOKAT_TARGET_NONE) { if (calcTargetPosition()) { //LLMotion* head_motion = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->findMotion(ANIM_AGENT_HEAD_ROT); //if (!head_motion || head_motion->isStopped()) // singu: startMotion does basically the same as the above two lines... it starts it, unless it was already started. { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_HEAD_ROT); } } } // Singu note: this displays extra information for look at targets. Due to the bug in llvoavatar.cpp // it was never displayed before and is not something users exect: turning it off for now #if 0 if (show_look_at) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); } #endif }
void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) { if (mDrawable == NULL) { markDead(); return; } if (gShiftFrame) { return; } if (mDrawable->getVObj()) { if (mDrawable->getVObj()->isAttachment()) { LLDrawable* parent = mDrawable->getParent(); if (parent) { LLViewerObject *obj = parent->getVObj(); if (obj && obj->isAvatar() && ((LLVOAvatar*)obj)->isImpostor()) { return; } } else { static const LLCachedControl<bool> draw_orphans("ShyotlDrawOrphanAttachments",false); if(!draw_orphans) return; } } LLCamera camera = transformCamera(camera_in); mDrawable->updateDistance(camera, force_update); LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* child = *iter; LLDrawable* drawable = child->mDrawable; if (!drawable) { continue; } if (!drawable->isAvatar()) { drawable->updateDistance(camera, force_update); } } } }
//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::update() { LLHUDEffectLookAt::sDebugLookAt = gSavedSettings.getBOOL("PersistShowLookAt"); // If the target object is dead, set the target object to NULL if (!mTargetObject.isNull() && mTargetObject->isDead()) { clearLookAtTarget(); } // if source avatar is null or dead, mark self as dead and return if (mSourceObject.isNull() || mSourceObject->isDead()) { markDead(); return; } // make sure the proper set of avatar attention are currently being used. LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; // for now the first cut will just switch on sex. future development could adjust // timeouts according to avatar age and/or other features. mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); F32 time = mTimer.getElapsedTimeF32(); // clear out the effect if time is up if (mKillTime != 0.f && time > mKillTime) { if (mTargetType != LOOKAT_TARGET_NONE) { clearLookAtTarget(); // look at timed out (only happens on own avatar), so tell everyone setNeedsSendToSim(TRUE); } } if (mTargetType != LOOKAT_TARGET_NONE) { if (calcTargetPosition()) { LLMotion* head_motion = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->findMotion(ANIM_AGENT_HEAD_ROT); if (!head_motion || head_motion->isStopped()) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_HEAD_ROT); } } } if (sDebugLookAt) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); } }
/*! This function is called by QGraphicsScene::advance(). It is called twice for each item at each animation step, first with \a phase = 0, and then with \a phase = 1. In phase 0, each item moves itself. In phase 1, each item that is responsible for handling collisions detects its collisions and handles them. Note: Each subclass of this base class must implement advance() and call this function when \a phase == 0. \internal */ void KSprite::advance(int phase) { if (phase == 0) { if (dying()) markDead(); if ((vx_ != 0.0) || (vy_ != 0.0)) { moveBy(vx_,vy_); wrap(); } } }
void LLHUDEffectSpiral::render() { F32 time = mTimer.getElapsedTimeF32(); if ((!mSourceObject.isNull() && mSourceObject->isDead()) || (!mTargetObject.isNull() && mTargetObject->isDead()) || mKillTime < time || (!mPartSourcep.isNull() && !gSavedSettings.getBOOL("ShowSelectionBeam")) ) { markDead(); return; } }
void LLHUDEffectSpiral::render() { F32 time = mTimer.getElapsedTimeF32(); static BOOL* sShowSelectionBeam = rebind_llcontrol<BOOL>("ShowSelectionBeam", &gSavedSettings, true); if ((!mSourceObject.isNull() && mSourceObject->isDead()) || (!mTargetObject.isNull() && mTargetObject->isDead()) || mKillTime < time || (!mPartSourcep.isNull() && !*sShowSelectionBeam) ) { markDead(); return; } }
/*! In phase 0, age the exhaust and mark it dead if it has expired. Also advance the exhaust image and move the exhaust with the ship. In phase 1, if the exhaust has been marked dead, destroy it. \internal */ void KExhaust::advance(int phase) { if (phase == 0) { if (dying()) markDead(); else incrementAge(); if (isDead()) return; advanceImage(); KSprite::advance(phase); } else if (isDead() || dying()) delete this; }
/*! This function is only called by \l QGraphicsScene::advance(). The shield's position is always computed from the ship's position, so the shield is not moved here. Neither is the shield destroyed here, because the shield is meant to exist for as long as the ship exists. The only thing that happens here is that in \a phase 1 the shield is either shown or hidden depending on whether it is marked as being up or not. The shield is created when the ship is created. The shield is deleted when the ship is deleted. \internal */ void KShield::advance(int phase) { if ((phase == 0) && dying()) markDead(); else if (phase == 1) { if (isDead() || dying()) { delete this; return; } if (isUp()) show(); else hide(); } }
void LLHUDEffectSpiral::render() { F32 time = mTimer.getElapsedTimeF32(); static LLCachedControl<bool> showSelectionBeam(gSavedSettings, "ShowSelectionBeam"); // <FS:Ansariel> Performance tweak if ((!mSourceObject.isNull() && mSourceObject->isDead()) || (!mTargetObject.isNull() && mTargetObject->isDead()) || mKillTime < time || // <FS:Ansariel> Performance tweak //(!mPartSourcep.isNull() && !gSavedSettings.getBOOL("ShowSelectionBeam")) ) (!mPartSourcep.isNull() && !showSelectionBeam) ) { markDead(); return; } }
/*! In phase 0, age the powerup sprite and move it based on its current position and velocity. In phase 1, if the powerup has been marked for being applied to the ship, increase the ship's fire power. \internal */ void KShootPowerup::advance(int phase) { if (phase == 0) { if (dying()) markDead(); else incrementAge(); KSprite::advance(phase); } else { if (apply() && ship_) ship_->incrementFirePower(); if (isDead() || dying()) delete this; } }
/*! In phase 0, age the powerup sprite and move it based on its current position and velocity. In phase 1, if the powerup has been marked for being applied to the ship, increase the ship's power level. \internal */ void KEnergyPowerup::advance(int phase) { if (phase == 0) { if (dying()) markDead(); else incrementAge(); KSprite::advance(phase); } else { if (apply() && ship_) ship_->increasePowerLevel(FUEL_POWERUP_BONUS); if (isDead() || dying()) delete this; } }
void Changer::clearBeforeMove_impl() { markDead(); // remove dead eraseElements(remaining_actions_, -1); eraseElements(remaining_pseudo_actions_, -1); eraseElements(completed_commands_, -1); // clear model model_->clearBeforeMove(team_); // resize Changer's private vectors int bacteria = getBacteriaNumber_impl(); remaining_actions_.resize(bacteria, MAX_ACTIONS); remaining_pseudo_actions_.resize(bacteria, MAX_PSEUDO_ACTIONS); completed_commands_.resize(bacteria, 0); // max remaining actions (because of new move) for (int b = 0; b < bacteria; b++) { remaining_actions_[b] = MAX_ACTIONS; remaining_pseudo_actions_[b] = MAX_PSEUDO_ACTIONS; } }
void LLHUDEffectBlob::render() { F32 time = mTimer.getElapsedTimeF32(); if (mDuration < time) { markDead(); } LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(mPositionGlobal); LLVector3 pixel_up, pixel_right; LLViewerCamera::instance().getPixelVectors(pos_agent, pixel_up, pixel_right); LLGLSPipelineAlpha gls_pipeline_alpha; gGL.getTexUnit(0)->bind(mImage->getImage()); LLColor4U color = mColor; color.mV[VALPHA] = (U8)clamp_rescale(time, 0.f, mDuration, 255.f, 0.f); gGL.color4ubv(color.mV); { gGL.pushMatrix(); gGL.translatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]); LLVector3 u_scale = pixel_right * (F32)mPixelSize; LLVector3 v_scale = pixel_up * (F32)mPixelSize; { gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex3fv((v_scale - u_scale).mV); gGL.texCoord2f(0.f, 0.f); gGL.vertex3fv((-v_scale - u_scale).mV); gGL.texCoord2f(1.f, 0.f); gGL.vertex3fv((-v_scale + u_scale).mV); gGL.texCoord2f(1.f, 1.f); gGL.vertex3fv((v_scale + u_scale).mV); } gGL.end(); } gGL.popMatrix(); }
//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- void LLHUDEffectPointAt::update() { // If the target object is dead, set the target object to NULL if (!mTargetObject.isNull() && mTargetObject->isDead()) { clearPointAtTarget(); } if (mSourceObject.isNull() || mSourceObject->isDead()) { markDead(); return; } F32 time = mTimer.getElapsedTimeF32(); // clear out the effect if time is up if (mKillTime != 0.f && time > mKillTime) { mTargetType = POINTAT_TARGET_NONE; } if (mSourceObject->isAvatar()) { if (mTargetType == POINTAT_TARGET_NONE) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint"); } else { if (calcTargetPosition()) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_EDITING); } } } }
void LLHUDEffectBeam::render() { if (!mSourceObject) { markDead(); return; } if (mSourceObject->isDead()) { markDead(); return; } F32 time = mTimer.getElapsedTimeF32(); // Kill us if our time is over... if (mKillTime < time) { markDead(); return; } LLGLSPipelineAlpha gls_pipeline_alpha; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); // Interpolate the global fade alpha mFadeInterp.update(time); if (mTargetObject.notNull() && mTargetObject->mDrawable.notNull()) { // use viewer object position on freshly created objects if (mTargetObject->mDrawable->getGeneration() == -1) { mTargetPos = mTargetObject->getPositionGlobal(); } // otherwise use drawable else { mTargetPos = gAgent.getPosGlobalFromAgent(mTargetObject->mDrawable->getPositionAgent()); } } // Init the color of the particles LLColor4U coloru = mColor; // Draw the particles S32 i; for (i = 0; i < NUM_POINTS; i++) { mInterp[i].update(time); if (!mInterp[i].isActive()) { continue; } mInterpFade[i].update(time); if (mInterp[i].isDone()) { // Reinitialize the particle when the particle has finished its animation. setupParticle(i); } F32 frac = mInterp[i].getCurFrac(); F32 scale = 0.025f + fabs(0.05f*sin(2.f*F_PI*(frac - time))); scale *= mInterpFade[i].getCurVal(); LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(mInterp[i].getCurVal()); F32 alpha = mFadeInterp.getCurVal()*mColor.mV[3]; alpha *= mInterpFade[i].getCurVal(); coloru.mV[3] = (U8)alpha; glColor4ubv(coloru.mV); glPushMatrix(); glTranslatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]); glScalef(scale, scale, scale); gSphere.render(0); glPopMatrix(); } }
TrieadOwner::~TrieadOwner() { markDead(); }
void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum) { const size_t EFFECT_SIZE = 56; U8 packed_data[EFFECT_SIZE]; LLHUDEffect::unpackData(mesgsys, blocknum); LLUUID object_id, target_object_id; S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); if (size != EFFECT_SIZE) { llwarns << "Spiral effect with bad size " << size << llendl; return; } mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE); htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16); htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16); htonmemcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24); LLViewerObject *objp = NULL; if (object_id.isNull()) { setSourceObject(NULL); } else { LLViewerObject *objp = gObjectList.findObject(object_id); if (objp) { setSourceObject(objp); } else { // We don't have this object, kill this effect markDead(); return; } } if (target_object_id.isNull()) { setTargetObject(NULL); } else { objp = gObjectList.findObject(target_object_id); if (objp) { setTargetObject(objp); } else { // We don't have this object, kill this effect markDead(); return; } } triggerLocal(); }
void Connection::markDead(const char* reason) { return markDead(reason, s_retryTimeout); }
/*! The advance function does quite a lot for the ship sprite. In \a phase 0, if the ship is marked dead, just return. If not, move the ship using its current position and velocity. Then get the list of all collisions with the ship and run through the list. If the ship collides with a rock, then if the shield is up, destroy the rock. If the shiled is down (normal), mark the ship dead and return. If the ship collides with a powerup, then if the shield is up, mark the powerup destroyed. If the shield is not up, apply the powerup to the ship. In phase 1, if the ship is marked dead, explode the ship, delete it, and return. Otherwise, handle ship rotation, breaking, ship velocity, an teleporting. also update the image if the ship is rotating, and the exhaust image, if the engine is on. If the shiled is up, handle its image and age. Finally, in phase one, handle the firing of the missiles. \internal */ void KShip::advance(int phase) { if (phase == 0) { if (dying()) markDead(); if (isDead() || teleport_) return; KSprite::advance(phase); QList<QGraphicsItem*> hits = ship_->collidingItems(); QList<QGraphicsItem*>::Iterator i; for (i=hits.begin(); i!=hits.end(); ++i) { if ((*i)->type() <= ID_Base) continue; KSprite* sprite = (KSprite*)(*i); if (sprite->isRock()) { if (shield_->isUp()) { /* The ship hit a rock with the shield up. The rock is marked for death, which will cause it to break up or just disappear in in phase 1. The shield's strength is reduced by an amount commensurate with the rock size. If the strength goes to 0, the shield will be dropped in phase 1. */ sprite->markDead(); int s = 1; if (sprite->isLargeRock()) s = 3; else if (sprite->isMediumRock()) s = 2; int pl = s * (SHIELD_HIT_COST - (shield_->strength()*2)); shield_->reduceStrength(s); reducePowerLevel(pl); } else { /* The ship hit a rock with the shield down. Mark the ship dead and return. The ship will be exploded in phase 1. */ view_->setCanPause(false); markDead(); shield_->markDead(); return; } } else if (sprite->isPowerup()) { if (shield_->isUp()) { sprite->markDead(); } else { /* The ship hit a powerup with the shield down. Mark the powerup for apply. It will be applied to the ship in phase 1, if the ship survives. Also mark the powerup dead, ie consumed. */ sprite->markApply(); sprite->markDead(); return; } } else if (powerLevel() <= EMPTY_SHIP_POWER_LEVEL) { ship_->markDead(); shield_->markDead(); } } } else { // phase 1 if (isDead() || dying()) { explode(); // shatters the ship into spinning fragments. delete this; return; } if (rotateSlow_) rotateSlow_--; if (rotateLeft_) { angleIndex_ -= rotateSlow_ ? 1 : rotationRate_; if (angleIndex_ < 0) angleIndex_ = SHIP_STEPS-1; angle_ = angleIndex_ * PI_X_2 / SHIP_STEPS; cosangle_ = cos(angle_); sinangle_ = sin(angle_); } if (rotateRight_) { angleIndex_ += rotateSlow_ ? 1 : rotationRate_; if (angleIndex_ >= SHIP_STEPS) angleIndex_ = 0; angle_ = angleIndex_ * PI_X_2 / SHIP_STEPS; cosangle_ = cos(angle_); sinangle_ = sin(angle_); } if (isBraking()) { stopEngine(); stopRotation(); if ((fabs(dx_) < 2.5) && (fabs(dy_) < 2.5)) { dx_ = 0.0; dy_ = 0.0; setVelocity(dx_,dy_); releaseBrakes(); } else { double motionAngle = atan2(-dy_,-dx_); if (angle_ > M_PI) angle_ -= PI_X_2; double angleDiff = angle_ - motionAngle; if (angleDiff > M_PI) angleDiff = PI_X_2 - angleDiff; else if (angleDiff < -M_PI) angleDiff = PI_X_2 + angleDiff; double fdiff = fabs(angleDiff); if (fdiff > 0.08) { if (angleDiff > 0) rotateLeft_ = true; else if (angleDiff < 0) rotateRight_ = true; if (fdiff > 0.6) rotationRate_ = brakeForce() + 1; else if (fdiff > 0.4) rotationRate_ = 2; else rotationRate_ = 1; if (rotationRate_ > 5) rotationRate_ = 5; } else if ((fabs(dx_)>1) || (fabs(dy_)>1)) { startEngine(); // we'll make braking a bit faster dx_ += cosangle_/6 * (brakeForce() - 1); dy_ += sinangle_/6 * (brakeForce() - 1); reducePowerLevel(BRAKE_ON_COST); KExhaust::add(ship_->x() + 10 - cosangle_*11, ship_->y() + 10 - sinangle_*11, dx_-cosangle_, dy_-sinangle_, brakeForce()+1); } } } else if (engineIsOn()) { /* The ship has a terminal velocity, but trying to go faster still uses fuel (can go faster diagonally - don't care). */ double thrustx = cosangle_/8; double thrusty = sinangle_/8; if (fabs(dx_ + thrustx) < MAX_SHIP_SPEED) dx_ += thrustx; if (fabs(dy_ + thrusty) < MAX_SHIP_SPEED) dy_ += thrusty; setVelocity(dx_,dy_); reducePowerLevel(5); KExhaust::add(x() + 10 - cosangle_*10, y() + 10 - sinangle_*10, dx_-cosangle_, dy_-sinangle_, 3); } setImage(angleIndex_ >> 1); if (teleport_) { int ra = rand() % 10; if(ra == 0) ra += rand() % 20; int xra = ra * 60 + ((rand() % 20) * (rand() % 20)); int yra = ra * 50 - ((rand() % 20) * (rand() % 20)); setPos(xra,yra); teleport_ = false; if (teleportCount_ > 0) { --teleportCount_; view_->markVitalsChanged(); } wrap(); } if (shield_->isUp()) { /* The shield's position always depends on the ship's position. */ static int sf = 0; sf++; if (sf % 2) shield_->advanceImage(); shield_->setPos(x()-5,y()-5); shield_->show(); } if (isShooting()) { int maxMissiles = firePower_ + 2; if (canShoot() && (KMissile::missiles() < maxMissiles)) { KMissile* missile = new KMissile(); missile->setMaximumAge(12); missile->setPos(11 + x() + cosangle_ * 11, 11 + y() + sinangle_ * 11); missile->setVelocity(dx_ + cosangle_ * MISSILE_SPEED, dy_ + sinangle_ * MISSILE_SPEED); missile->show(); reducePowerLevel(1); view_->reportMissileFired(); int delay = 5 - firePower_; if (delay < 0) delay = 0; delayShooting(delay); // delay firing next missile. } decrementNextShotDelay(); } } }