00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <tankgraph/TargetRendererImplTank.h>
00022 #include <tank/TankLib.h>
00023 #include <tank/TankContainer.h>
00024 #include <tank/TankModelStore.h>
00025 #include <tank/TankModelContainer.h>
00026 #include <tank/TankState.h>
00027 #include <tank/TankPosition.h>
00028 #include <tank/TankAvatar.h>
00029 #include <target/TargetLife.h>
00030 #include <target/TargetShield.h>
00031 #include <target/TargetState.h>
00032 #include <tankgraph/TankMesh.h>
00033 #include <tankgraph/TankMeshStore.h>
00034 #include <landscape/Landscape.h>
00035 #include <landscapemap/LandscapeMaps.h>
00036 #include <landscape/ShadowMap.h>
00037 #include <landscape/Smoke.h>
00038 #include <actions/TankFalling.h>
00039 #include <engine/ActionController.h>
00040 #include <client/ScorchedClient.h>
00041 #include <client/ClientState.h>
00042 #include <graph/OptionsDisplay.h>
00043 #include <graph/ModelRenderer.h>
00044 #include <common/Defines.h>
00045 #include <graph/ModelRendererStore.h>
00046 #include <graph/ModelRendererSimulator.h>
00047 #include <weapons/Shield.h>
00048 #include <weapons/Accessory.h>
00049 #include <dialogs/TutorialDialog.h>
00050 #include <GLEXT/GLCameraFrustum.h>
00051 #include <image/ImageFactory.h>
00052 #include <GLEXT/GLTexture.h>
00053 #include <GLW/GLWFont.h>
00054
00055 float TargetRendererImplTankHUD::timeLeft_ = -1.0f;
00056 float TargetRendererImplTankHUD::percentage_ = -1.0f;
00057 std::string TargetRendererImplTankHUD::textA_ = "";
00058 std::string TargetRendererImplTankHUD::textB_ = "";
00059
00060 Vector TargetRendererImplTankAIM::aimPosition_;
00061 float TargetRendererImplTankAIM::timeLeft_ = -1.0f;
00062
00063 ModelRendererSimulator *TargetRendererImplTankAIM::getAutoAimModel()
00064 {
00065 static ModelRendererSimulator *modelRenderer = 0;
00066 if (!modelRenderer)
00067 {
00068 ModelID id;
00069 id.initFromString("ase", "data/meshes/autoaim.ase", "none");
00070 modelRenderer = new ModelRendererSimulator(
00071 ModelRendererStore::instance()->loadModel(id));
00072 }
00073 return modelRenderer;
00074 }
00075
00076 TargetRendererImplTank::TargetRendererImplTank(Tank *tank) :
00077 TargetRendererImpl(tank),
00078 tank_(tank), tankTips_(tank),
00079 model_(0), mesh_(0),
00080 smokeTime_(0.0f), smokeWaitForTime_(0.0f),
00081 fireOffSet_(0.0f), shieldHit_(0.0f),
00082 totalTime_(0.0f)
00083 {
00084 frame_ = (float) rand();
00085 }
00086
00087 TargetRendererImplTank::~TargetRendererImplTank()
00088 {
00089 }
00090
00091 TankModel *TargetRendererImplTank::getModel()
00092 {
00093 if (!model_)
00094 {
00095
00096 model_ = ScorchedClient::instance()->getTankModels().getModelByName(
00097 tank_->getModelContainer().getTankOriginalModelName(),
00098 tank_->getTeam(),
00099 tank_->isTemp());
00100 if (0 != strcmp(model_->getName(),
00101 tank_->getModelContainer().getTankOriginalModelName()))
00102 {
00103
00104 model_ = ScorchedClient::instance()->getTankModels().getModelByName(
00105 tank_->getModelContainer().getTankModelName(),
00106 tank_->getTeam(),
00107 tank_->isTemp());
00108 }
00109 }
00110 return model_;
00111 }
00112
00113 TankMesh *TargetRendererImplTank::getMesh()
00114 {
00115 if (!mesh_)
00116 {
00117 mesh_ = TankMeshStore::instance()->getMesh(getModel()->getTankModelID());
00118 }
00119 return mesh_;
00120 }
00121
00122 void TargetRendererImplTank::render(float distance)
00123 {
00124 if (TargetRendererImplTankAIM::drawAim())
00125 {
00126 GLState texState(GLState::TEXTURE_OFF);
00127 Vector &pos = TargetRendererImplTankAIM::getAimPosition();
00128
00129 glPushMatrix();
00130 glTranslatef(pos[0], pos[1], pos[2]);
00131 TargetRendererImplTankAIM::getAutoAimModel()->draw();
00132 glPopMatrix();
00133 }
00134
00135 float size = getTargetSize();
00136 float fade = getTargetFade(distance,
00137 size * 2.5f * float(OptionsDisplay::instance()->getTankModelSize()) / 100.0f);
00138
00139 createParticle();
00140 storeTarget2DPos();
00141
00142 bool currentTank =
00143 (tank_ == ScorchedClient::instance()->getTankContainer().getCurrentTank() &&
00144 ScorchedClient::instance()->getGameState().getState() == ClientState::StatePlaying);
00145 if (fade > 0.0f)
00146 {
00147
00148 if (tank_->getTargetState().getDisplayShadow() &&
00149 Landscape::instance()->getShadowMap().shouldAddShadow())
00150 {
00151 float modelSize = float(OptionsDisplay::instance()->getTankModelSize()) / 100.0f;
00152 Landscape::instance()->getShadowMap().addCircle(
00153 tank_->getLife().getFloatPosition()[0],
00154 tank_->getLife().getFloatPosition()[1],
00155 (tank_->getLife().getSize().Max().asFloat() + 2.0f) * modelSize,
00156 fade);
00157 }
00158
00159
00160 TankMesh *mesh = getMesh();
00161 if (mesh)
00162 {
00163 float modelSize = float(OptionsDisplay::instance()->getTankModelSize()) / 100.0f;
00164 mesh->draw(frame_,
00165 currentTank,
00166 tank_->getLife().getFloatRotMatrix(),
00167 tank_->getLife().getFloatPosition(),
00168 fireOffSet_,
00169 tank_->getPosition().getRotationGunXY().asFloat(),
00170 tank_->getPosition().getRotationGunYZ().asFloat(),
00171 false, modelSize, fade, true);
00172 }
00173 }
00174
00175 GLState lightingOff(GLState::LIGHTING_OFF);
00176
00177
00178 if (currentTank &&
00179 OptionsDisplay::instance()->getDrawPlayerSight() &&
00180 !OptionsDisplay::instance()->getOldSightPosition())
00181 {
00182 drawSight();
00183 }
00184
00185
00186 drawLife();
00187 }
00188
00189 void TargetRendererImplTank::renderShadow(float distance)
00190 {
00191 TankMesh *mesh = getMesh();
00192 if (mesh)
00193 {
00194 float modelSize = float(OptionsDisplay::instance()->getTankModelSize()) / 100.0f;
00195 mesh->draw(frame_,
00196 false,
00197 tank_->getLife().getFloatRotMatrix(),
00198 tank_->getLife().getFloatPosition(),
00199 fireOffSet_,
00200 tank_->getPosition().getRotationGunXY().asFloat(),
00201 tank_->getPosition().getRotationGunYZ().asFloat(),
00202 false, modelSize, 1.0f, false);
00203 }
00204 }
00205
00206 void TargetRendererImplTank::drawParticle(float distance)
00207 {
00208 if (!getVisible()) return;
00209
00210 drawParachute();
00211 drawShield(shieldHit_, totalTime_);
00212
00213 if (!tank_->isTemp()) drawInfo();
00214 }
00215
00216 void TargetRendererImplTank::drawInfo()
00217 {
00218
00219 drawArrow();
00220
00221 Vector &position = tank_->getPosition().getTankPosition().asVector();
00222 float height = position[2];
00223 float groundHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().
00224 getHeight((int) position[0], (int) position[1]).asFloat();
00225 if (height < groundHeight)
00226 {
00227 height = groundHeight;
00228 }
00229
00230
00231 if (OptionsDisplay::instance()->getDrawPlayerNames())
00232 {
00233 Vector &bilX = GLCameraFrustum::instance()->getBilboardVectorX();
00234 bilX *= 0.5f * GLWFont::instance()->getGameFont()->getWidth(
00235 1, tank_->getTargetName());
00236
00237 glDepthMask(GL_FALSE);
00238 GLWFont::instance()->getGameFont()->drawBilboard(
00239 tank_->getColor(), 1.0f, 1,
00240 (float) tank_->getLife().getFloatPosition()[0] - bilX[0],
00241 (float) tank_->getLife().getFloatPosition()[1] - bilX[1],
00242 (float) height + 8.0f,
00243 tank_->getTargetName());
00244 glDepthMask(GL_TRUE);
00245 }
00246
00247 if (OptionsDisplay::instance()->getDrawPlayerIcons())
00248 {
00249 Vector &bilX = GLCameraFrustum::instance()->getBilboardVectorX();
00250 if (OptionsDisplay::instance()->getDrawPlayerNames())
00251 {
00252 bilX *= 0.5f * GLWFont::instance()->getGameFont()->getWidth(
00253 1, tank_->getTargetName());
00254 bilX += bilX.Normalize() * 1.0f;
00255 }
00256 else
00257 {
00258 bilX *= 0.0f;
00259 }
00260
00261 Vector position =
00262 tank_->getPosition().getTankPosition().asVector() - bilX;
00263 position[2] = height + 8.5f;
00264
00265 tank_->getAvatar().getTexture()->draw();
00266 static Vector white(1.0f, 1.0f, 1.0f);
00267 GLCameraFrustum::instance()->drawBilboard(
00268 position, white, 0.8f, 0.5f, 0.5f, false, 0);
00269 }
00270 }
00271
00272 void TargetRendererImplTank::drawSight()
00273 {
00274 glPushMatrix();
00275 glTranslatef(
00276 tank_->getPosition().getTankGunPosition()[0].asFloat(),
00277 tank_->getPosition().getTankGunPosition()[1].asFloat(),
00278 tank_->getPosition().getTankGunPosition()[2].asFloat());
00279
00280 glRotatef(tank_->getPosition().getRotationGunXY().asFloat(),
00281 0.0f, 0.0f, 1.0f);
00282 glRotatef(tank_->getPosition().getRotationGunYZ().asFloat(),
00283 1.0f, 0.0f, 0.0f);
00284
00285 TankMesh::drawSight();
00286 glPopMatrix();
00287 }
00288
00289 void TargetRendererImplTank::fired()
00290 {
00291 fireOffSet_ = -0.25f;
00292 }
00293
00294 void TargetRendererImplTank::shieldHit()
00295 {
00296 shieldHit_ = 0.25f;
00297 }
00298
00299 void TargetRendererImplTank::simulate(float frameTime)
00300 {
00301 totalTime_ += frameTime;
00302 frame_ += frameTime * 20.0f;
00303
00304 if (fireOffSet_ < 0.0f)
00305 {
00306 fireOffSet_ += frameTime / 25.0f;
00307 if (fireOffSet_ > 0.0f) fireOffSet_ = 0.0f;
00308 }
00309 if (shieldHit_ > 0.0f)
00310 {
00311 shieldHit_ -= frameTime / 25.0f;
00312 if (shieldHit_ < 0.0f) shieldHit_ = 0.0f;
00313 }
00314 if (tank_->getLife().getLife() < tank_->getLife().getMaxLife())
00315 {
00316 smokeTime_ += frameTime;
00317 if (smokeTime_ >= smokeWaitForTime_)
00318 {
00319 const float randOff = 1.0f;
00320 const float randOffDiv = 0.5f;
00321 float randX = RAND * randOff - randOffDiv;
00322 float randY = RAND * randOff - randOffDiv;
00323 Landscape::instance()->getSmoke().addSmoke(
00324 tank_->getPosition().getTankTurretPosition()[0].asFloat() + randX,
00325 tank_->getPosition().getTankTurretPosition()[1].asFloat() + randY,
00326 tank_->getPosition().getTankTurretPosition()[2].asFloat());
00327
00328 smokeWaitForTime_ = (
00329 (RAND * float(tank_->getLife().getLife().asFloat()) * 10.0f) + 250.0f)
00330 / 3000.0f;;
00331 smokeTime_ = 0.0f;
00332 }
00333 }
00334 }
00335
00336 void TargetRendererImplTank::drawArrow()
00337 {
00338 if (!OptionsDisplay::instance()->getDrawPlayerColor())
00339 {
00340 return;
00341 }
00342
00343 GLState currentState(GLState::TEXTURE_OFF | GLState::BLEND_OFF);
00344 Vector &bilX = GLCameraFrustum::instance()->getBilboardVectorX();
00345 bilX /= 2.0f;
00346
00347 Vector &position = tank_->getPosition().getTankPosition().asVector();
00348 float height = position[2];
00349 float groundHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().
00350 getHeight((int) position[0], (int) position[1]).asFloat();
00351 if (height < groundHeight)
00352 {
00353 height = groundHeight;
00354 }
00355
00356
00357 {
00358 static GLTexture arrowTexture;
00359 static bool createdTexture = false;
00360 if (!createdTexture)
00361 {
00362 createdTexture = true;
00363
00364 std::string file1 = S3D::getDataFile("data/windows/arrow.bmp");
00365 std::string file2 = S3D::getDataFile("data/windows/arrowi.bmp");
00366 ImageHandle bitmap =
00367 ImageFactory::loadImageHandle(file1.c_str(), file2.c_str(), true);
00368 arrowTexture.create(bitmap);
00369 }
00370
00371 GLState currentState(GLState::TEXTURE_ON | GLState::BLEND_ON);
00372 arrowTexture.draw(true);
00373
00374 glDepthMask(GL_FALSE);
00375 glColor3fv(tank_->getColor());
00376 glBegin(GL_QUADS);
00377 glTexCoord2f(0.0f, 0.0f);
00378 glVertex3f(position[0] - bilX[0],
00379 position[1] - bilX[1], height + 4.0f);
00380 glTexCoord2f(1.0f, 0.0f);
00381 glVertex3f(position[0] + bilX[0],
00382 position[1] + bilX[1], height + 4.0f);
00383 glTexCoord2f(1.0f, 1.0f);
00384 glVertex3f(position[0] + bilX[0],
00385 position[1] + bilX[1], height + 7.0f);
00386 glTexCoord2f(0.0f, 1.0f);
00387 glVertex3f(position[0] - bilX[0],
00388 position[1] - bilX[1], height + 7.0f);
00389 glEnd();
00390 glDepthMask(GL_TRUE);
00391 }
00392
00393 }
00394
00395 void TargetRendererImplTank::drawLife()
00396 {
00397 if (!OptionsDisplay::instance()->getDrawPlayerHealth())
00398 {
00399 return;
00400 }
00401
00402 GLState currentState(GLState::TEXTURE_OFF | GLState::BLEND_OFF);
00403 Vector &bilX = GLCameraFrustum::instance()->getBilboardVectorX();
00404 bilX /= 2.0f;
00405
00406 Vector &position = tank_->getPosition().getTankPosition().asVector();
00407 float height = position[2];
00408 float groundHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().
00409 getHeight((int) position[0], (int) position[1]).asFloat();
00410 if (height < groundHeight)
00411 {
00412 height = groundHeight;
00413 }
00414 {
00415 float shieldLife = 0.0f;
00416 Accessory *currentShield =
00417 tank_->getShield().getCurrentShield();
00418 if (currentShield)
00419 {
00420 Shield *shield = (Shield *)
00421 tank_->getShield().getCurrentShield()->getAction();
00422 shieldLife = tank_->getShield().getShieldPower().asFloat() /
00423 shield->getPower().asFloat() * 100.0f;
00424 }
00425
00426 drawLifeBar(bilX,
00427 tank_->getLife().getLife().asFloat() /
00428 tank_->getLife().getMaxLife().asFloat() * 100.0f,
00429 height, 3.3f);
00430 drawLifeBar(bilX, shieldLife, height, 3.7f);
00431 }
00432 }
00433
00434 void TargetRendererImplTank::drawLifeBar(Vector &bilX, float value,
00435 float height, float barheight)
00436 {
00437 Vector &position = tank_->getPosition().getTankPosition().asVector();
00438 glBegin(GL_QUADS);
00439 if (value == 100.0f || value == 0.0f)
00440 {
00441 if (value == 100.0f) glColor3f(0.0f, 1.0f, 0.0f);
00442 else glColor3f(0.0f, 0.0f, 0.0f);
00443
00444 glVertex3f(position[0] + bilX[0],
00445 position[1] + bilX[1], height + barheight);
00446 glVertex3f(position[0] + bilX[0],
00447 position[1] + bilX[1], height + barheight + 0.2f);
00448 glVertex3f(position[0] - bilX[0],
00449 position[1] - bilX[1], height + barheight + 0.2f);
00450 glVertex3f(position[0] - bilX[0],
00451 position[1] - bilX[1], height + barheight);
00452 }
00453 else
00454 {
00455 float lifePer = value / 50.0f;
00456 static Vector newBilX;
00457 newBilX = -bilX;
00458 newBilX += bilX * lifePer;
00459
00460 glColor3f(0.0f, 1.0f, 0.0f);
00461 glVertex3f(position[0] + newBilX[0],
00462 position[1] + newBilX[1], height + barheight);
00463 glVertex3f(position[0] + newBilX[0],
00464 position[1] + newBilX[1], height + barheight + 0.2f);
00465 glVertex3f(position[0] - bilX[0],
00466 position[1] - bilX[1], height + barheight + 0.2f);
00467 glVertex3f(position[0] - bilX[0],
00468 position[1] - bilX[1], height + barheight);
00469
00470 glColor3f(1.0f, 0.0f, 0.0f);
00471
00472 glVertex3f(position[0] + bilX[0],
00473 position[1] + bilX[1], height + barheight);
00474 glVertex3f(position[0] + bilX[0],
00475 position[1] + bilX[1], height + barheight + 0.2f);
00476 glVertex3f(position[0] + newBilX[0],
00477 position[1] + newBilX[1], height + barheight + 0.2f);
00478 glVertex3f(position[0] + newBilX[0],
00479 position[1] + newBilX[1], height + barheight);
00480 }
00481 glEnd();
00482 }
00483
00484 void TargetRendererImplTank::render2D(float distance)
00485 {
00486
00487 GLWToolTip::instance()->addToolTip(&tankTips_.tankTip,
00488 float(posX_) - 10.0f, float(posY_) - 10.0f, 20.0f, 20.0f);
00489
00490
00491 bool currentTank =
00492 (tank_ == ScorchedClient::instance()->getTankContainer().getCurrentTank() &&
00493 ScorchedClient::instance()->getGameState().getState() == ClientState::StatePlaying);
00494 if (currentTank)
00495 {
00496 GLState firstState(GLState::DEPTH_OFF);
00497 if (TargetRendererImplTankHUD::drawText())
00498 {
00499 Vector yellow(0.7f, 0.7f, 0.0f);
00500 GLWFont::instance()->getGameFont()->draw(
00501 yellow, 10,
00502 (float) posX_ + 47.0f, (float) posY_ - 4.0f, (float) posZ_,
00503 TargetRendererImplTankHUD::getTextA());
00504 GLWFont::instance()->getGameFont()->draw(
00505 yellow, 10,
00506 (float) posX_ + 47.0f, (float) posY_ - 15.0f, (float) posZ_,
00507 TargetRendererImplTankHUD::getTextB());
00508
00509 if (TargetRendererImplTankHUD::getPercentage() >= 0.0f)
00510 {
00511 float totalHeight = 40.0f;
00512 float halfHeight = totalHeight / 2.0f;
00513 float height = totalHeight * TargetRendererImplTankHUD::getPercentage() / 100.0f;
00514
00515 GLState state2(GLState::TEXTURE_OFF);
00516 glBegin(GL_QUADS);
00517 glColor3f(1.0f, 0.0f, 0.0f);
00518 glVertex2f((float) posX_ + 42.0f, (float) posY_ -halfHeight);
00519 glVertex2f((float) posX_ + 45.0f, (float) posY_ -halfHeight);
00520 glVertex2f((float) posX_ + 45.0f, (float) posY_ -halfHeight + height);
00521 glVertex2f((float) posX_ + 42.0f, (float) posY_ -halfHeight + height);
00522
00523 glColor3f(0.0f, 0.0f, 0.0f);
00524 glVertex2f((float) posX_ + 42.0f, (float) posY_ -halfHeight + height);
00525 glVertex2f((float) posX_ + 45.0f, (float) posY_ -halfHeight + height);
00526 glVertex2f((float) posX_ + 45.0f, (float) posY_ -halfHeight + totalHeight);
00527 glVertex2f((float) posX_ + 42.0f, (float) posY_ -halfHeight + totalHeight);
00528 glEnd();
00529 glBegin(GL_LINES);
00530 glColor3f(1.0f, 0.0f, 0.0f);
00531 glVertex2f((float) posX_ + 40.0f, (float) posY_ -halfHeight);
00532 glVertex2f((float) posX_ + 47.0f, (float) posY_ -halfHeight);
00533
00534 glVertex2f((float) posX_ + 40.0f, (float) posY_ +halfHeight);
00535 glVertex2f((float) posX_ + 47.0f, (float) posY_ +halfHeight);
00536 glEnd();
00537 }
00538 }
00539
00540 GLState newState(GLState::TEXTURE_OFF | GLState::BLEND_ON);
00541
00542 glColor4f(0.9f, 0.9f, 1.0f, 0.5f);
00543 static GLuint listNo = 0;
00544 if (!listNo)
00545 {
00546 glNewList(listNo = glGenLists(1), GL_COMPILE);
00547 glBegin(GL_QUADS);
00548 for (float a=0; a<6.25f ;a+=0.25f)
00549 {
00550 const float skip = 0.2f;
00551 glVertex2d(sin(a + skip) * 40.0,
00552 cos(a + skip) * 40.0);
00553 glVertex2d(sin(a) * 40.0,
00554 cos(a) * 40.0);
00555 glVertex2d(sin(a) * 35.0,
00556 cos(a) * 35.0);
00557 glVertex2d(sin(a + skip) * 35.0,
00558 cos(a + skip) * 35.0);
00559 }
00560 glEnd();
00561 glEndList();
00562 }
00563
00564 glPushMatrix();
00565 glTranslated(posX_, posY_, 0.0);
00566 glCallList(listNo);
00567 glPopMatrix();
00568 }
00569
00570
00571 if ((highlightType_ == ePlayerHighlight && tank_->getDestinationId()) ||
00572 (highlightType_ == eOtherHighlight && !tank_->getDestinationId() ))
00573 {
00574 TutorialDialog::instance()->drawHighlight(
00575 float(posX_) - 10.0f, float(posY_) - 10.0f, 20.0f, 20.0f);
00576 }
00577 }