float RadarRenderer::transScale(const Obstacle& o) { float scaleColor; const LocalPlayer* myTank = LocalPlayer::getMyTank(); // Scale color so that objects that are close to tank's level are opaque const float zTank = myTank->getPosition()[2]; const float zObstacle = o.getPosition()[2]; const float hObstacle = o.getHeight(); if (zTank >= (zObstacle + hObstacle)) scaleColor = 1.0f - (zTank - (zObstacle + hObstacle)) / colorFactor; else if (zTank <= zObstacle) scaleColor = 1.0f - (zObstacle - zTank) / colorFactor; else scaleColor = 1.0f; if (scaleColor < 0.5f) scaleColor = 0.5f; return scaleColor; }
void SegmentedShotStrategy::makeSegments(ObstacleEffect e) { // compute segments of shot until total length of segments exceeds the // lifetime of the shot. const ShotPath& path = getPath(); const float* v = path.getVelocity(); TimeKeeper startTime = path.getStartTime(); float timeLeft = path.getLifetime(); float minTime = BZDB.eval(StateDatabase::BZDB_MUZZLEFRONT) / hypotf(v[0], hypotf(v[1], v[2])); // if all shots ricochet and obstacle effect is stop, then make it ricochet if (e == Stop && World::getWorld()->allShotsRicochet()) e = Reflect; // prepare first segment float o[3], d[3]; d[0] = v[0]; d[1] = v[1]; d[2] = v[2]; // use v[2] to have jumping affect shot velocity o[0] = path.getPosition()[0]; o[1] = path.getPosition()[1]; o[2] = path.getPosition()[2]; segments.clear(); ShotPathSegment::Reason reason = ShotPathSegment::Initial; int i; const int maxSegment = 100; for (i = 0; (i < maxSegment) && (timeLeft > Epsilon); i++) { // construct ray and find the first building, teleporter, or outer wall float o2[3]; o2[0] = o[0] - minTime * d[0]; o2[1] = o[1] - minTime * d[1]; o2[2] = o[2] - minTime * d[2]; Ray r(o2, d); Ray rs(o, d); float t = timeLeft + minTime; int face; bool hitGround = getGround(r, Epsilon, t); Obstacle* building = (Obstacle*)((e != Through) ? getFirstBuilding(r, Epsilon, t) : NULL); const Teleporter* teleporter = getFirstTeleporter(r, Epsilon, t, face); t -= minTime; minTime = 0.0f; // if hit outer wall with ricochet and hit is above top of wall // then ignore hit. if (!teleporter && building && e == Reflect && building->getType() == WallObstacle::getClassName() && o[2] + t * d[2] > building->getHeight()) t = timeLeft; // construct next shot segment and add it to list TimeKeeper endTime(startTime); if (t < 0.0f) endTime += Epsilon; else endTime += t; ShotPathSegment segment(startTime, endTime, rs, reason); segments.push_back(segment); startTime = endTime; // used up this much time in segment if (t < 0.0f) timeLeft -= Epsilon; else timeLeft -= t; // check in reverse order to see what we hit first reason = ShotPathSegment::Through; if (teleporter) { // entered teleporter -- teleport it int source = World::getWorld()->getTeleporter(teleporter, face); int target = World::getWorld()->getTeleportTarget(source); if (target == randomTeleporter) { unsigned int tmp = path.getShotId() + i; tmp = (tmp * 1103515245 + 12345) >> 8; // from POSIX rand() example tmp = tmp % (2 * World::getWorld()->getTeleporters().size()); target = tmp; } int outFace; const Teleporter* outTeleporter = World::getWorld()->getTeleporter(target, outFace); o[0] += t * d[0]; o[1] += t * d[1]; o[2] += t * d[2]; teleporter->getPointWRT(*outTeleporter, face, outFace, o, d, 0.0f, o, d, NULL); reason = ShotPathSegment::Teleport; } else if (building) {