00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <target/TargetSpace.h>
00022 #include <target/TargetLife.h>
00023 #include <target/TargetShield.h>
00024 #include <target/TargetState.h>
00025 #include <weapons/Accessory.h>
00026 #include <weapons/ShieldRound.h>
00027 #include <weapons/ShieldSquare.h>
00028 #include <engine/ScorchedContext.h>
00029 #include <engine/ActionController.h>
00030 #include <common/OptionsScorched.h>
00031 #include <common/Logger.h>
00032
00033 TargetSpace::TargetSpace() :
00034 spaceX_(-128), spaceY_(-128),
00035 spaceW_(1024), spaceH_(1024),
00036 spaceSq_(4), context_(0)
00037 {
00038 spaceWSq_ = (spaceW_ / spaceSq_);
00039 spaceHSq_ = (spaceH_ / spaceSq_);
00040 noSquares_ = spaceWSq_ * spaceHSq_;
00041 squares_ = new Square[noSquares_];
00042 for (int i=0; i<noSquares_; i++) squares_[i].squarenum = i;
00043 }
00044
00045 TargetSpace::~TargetSpace()
00046 {
00047 delete squares_;
00048 }
00049
00050 void TargetSpace::updateTarget(Target *target)
00051 {
00052 if (!target->getAlive() ||
00053 target->getTargetState().getNoCollision())
00054 {
00055 removeTarget(target);
00056 }
00057 else
00058 {
00059 static std::vector<Square*> squares;
00060 squares.clear();
00061 getSquares(target, squares);
00062
00063 bool same = false;
00064 if (squares.size() == target->getLife().getSpaceContainment().squares.size())
00065 {
00066 same = true;
00067 for (unsigned int i=0; i<squares.size(); i++)
00068 {
00069 if (squares[i]->squarenum != target->getLife().getSpaceContainment().squares[i])
00070 {
00071 same = false;
00072 break;
00073 }
00074 }
00075 }
00076
00077 if (!same)
00078 {
00079 removeTarget(target);
00080 std::vector<Square*>::iterator itor;
00081 for (itor = squares.begin();
00082 itor != squares.end();
00083 itor++)
00084 {
00085 Square *square = *itor;
00086 target->getLife().getSpaceContainment().squares.push_back(square->squarenum);
00087 square->targets.insert(std::pair<unsigned int, Target*>(target->getPlayerId(), target));
00088 }
00089 }
00090 }
00091 }
00092
00093 void TargetSpace::getSquares(Target *target, std::vector<Square*> &squares)
00094 {
00095
00096 int x = target->getLife().getTargetPosition()[0].asInt();
00097 int y = target->getLife().getTargetPosition()[1].asInt();
00098 int w = target->getLife().getAabbSize()[0].asInt();
00099 int h = target->getLife().getAabbSize()[1].asInt();
00100
00101
00102 Accessory *shieldAcc = target->getShield().getCurrentShield();
00103 if (shieldAcc)
00104 {
00105 Shield *shield = (Shield *) shieldAcc->getAction();
00106 if (shield->getRound())
00107 {
00108 ShieldRound *round = (ShieldRound *) shield;
00109
00110 w = MAX(w, (round->getActualRadius() * 2).asInt());
00111 h = MAX(h, (round->getActualRadius() * 2).asInt());
00112 }
00113 else
00114 {
00115 ShieldSquare *square = (ShieldSquare *) shield;
00116
00117 w = MAX(w, (square->getSize()[0] * 2).asInt());
00118 h = MAX(h, (square->getSize()[1] * 2).asInt());
00119 }
00120 }
00121
00122
00123 int halfW = w / 2;
00124 int halfH = h / 2;
00125 int minX = x - halfW - 1;
00126 int minY = y - halfH - 1;
00127 int maxX = x + halfW + 1;
00128 int maxY = y + halfH + 1;
00129
00130
00131 normalizeCoords(minX, minY);
00132 normalizeCoords(maxX, maxY);
00133
00134
00135 for (int b=minY; b<=maxY; b++)
00136 {
00137 for (int a=minX; a<=maxX; a++)
00138 {
00139 int num = spaceHSq_ * b + a;
00140 DIALOG_ASSERT(num >= 0 && num < noSquares_);
00141
00142 Square *square = &squares_[num];
00143 squares.push_back(square);
00144 }
00145 }
00146 }
00147
00148 void TargetSpace::removeTarget(Target *target)
00149 {
00150 std::vector<int> &squares = target->getLife().getSpaceContainment().squares;
00151 while (!squares.empty())
00152 {
00153 int squareNum = squares.back();
00154 squares.pop_back();
00155
00156 Square *square = &squares_[squareNum];
00157 square->targets.erase(target->getPlayerId());
00158 }
00159 }
00160
00161 Target *TargetSpace::getCollision(FixedVector &position)
00162 {
00163 int x = position[0].asInt();
00164 int y = position[1].asInt();
00165
00166
00167 normalizeCoords(x, y);
00168
00169 int num = spaceHSq_ * y + x;
00170 DIALOG_ASSERT(num >= 0 && num < noSquares_);
00171
00172 Square *square = &squares_[num];
00173
00174 Target *result = 0;
00175 std::map<unsigned int, Target *> &potentialTargets = square->targets;
00176 std::map<unsigned int, Target *>::iterator itor;
00177 for (itor = potentialTargets.begin();
00178 itor != potentialTargets.end();
00179 itor++)
00180 {
00181 Target *target = (*itor).second;
00182 if (!target->getAlive())
00183 {
00184 Logger::log(S3D::formatStringBuffer("ERROR: Dead target %u:%s in space",
00185 target->getPlayerId(), target->getCStrName().c_str()));
00186 continue;
00187 }
00188
00189 Accessory *shieldAcc = target->getShield().getCurrentShield();
00190 if (shieldAcc)
00191 {
00192 Shield *shield = (Shield *) shieldAcc->getAction();
00193 FixedVector direction = position - target->getLife().getTargetPosition();
00194 if (shield->inShield(direction))
00195 {
00196 result = target;
00197 break;
00198 }
00199 }
00200
00201 if (target->getLife().collision(position))
00202 {
00203 result = target;
00204 break;
00205 }
00206 }
00207
00208 if (context_->getOptionsGame().getActionSyncCheck())
00209 {
00210 std::string targets;
00211 if (result)
00212 {
00213 targets.append(S3D::formatStringBuffer("%u:%i,%i,%i ",
00214 result->getPlayerId(),
00215 result->getLife().getTargetPosition()[0].getInternal(),
00216 result->getLife().getTargetPosition()[1].getInternal(),
00217 result->getLife().getTargetPosition()[2].getInternal()));
00218 }
00219
00220 context_->getActionController().addSyncCheck(
00221 S3D::formatStringBuffer("CollisionSet : %i,%i,%i %s",
00222 position[0].getInternal(),
00223 position[1].getInternal(),
00224 position[2].getInternal(),
00225 targets.c_str()));
00226 }
00227
00228 return result;
00229 }
00230
00231 void TargetSpace::getCollisionSet(FixedVector &position, fixed radius,
00232 std::map<unsigned int, Target *> &collisionTargets,
00233 bool ignoreHeight)
00234 {
00235 int x = position[0].asInt();
00236 int y = position[1].asInt();
00237 int w = radius.asInt();
00238 int h = radius.asInt();
00239
00240
00241 int halfW = w;
00242 int halfH = h;
00243 int minX = x - halfW - 1;
00244 int minY = y - halfH - 1;
00245 int maxX = x + halfW + 1;
00246 int maxY = y + halfH + 1;
00247
00248
00249 normalizeCoords(minX, minY);
00250 normalizeCoords(maxX, maxY);
00251
00252
00253 std::map<unsigned int, Target *>::iterator itor;
00254 for (int b=minY; b<=maxY; b++)
00255 {
00256 for (int a=minX; a<=maxX; a++)
00257 {
00258 int num = spaceHSq_ * b + a;
00259 DIALOG_ASSERT(num >= 0 && num < noSquares_);
00260
00261 Square *square = &squares_[num];
00262
00263 std::map<unsigned int, Target *> &potentialTargets =
00264 square->targets;
00265 for (itor = potentialTargets.begin();
00266 itor != potentialTargets.end();
00267 itor++)
00268 {
00269 Target *target = (*itor).second;
00270 if (!target->getAlive())
00271 {
00272 Logger::log(S3D::formatStringBuffer("ERROR: Dead target %u:%s in space",
00273 target->getPlayerId(), target->getCStrName().c_str()));
00274 continue;
00275 }
00276
00277 FixedVector checkPos = position;
00278 if (ignoreHeight)
00279 {
00280 FixedVector centerPos = target->getLife().getCenterPosition();
00281 checkPos[2] = centerPos[2];
00282 }
00283 fixed distance = target->getLife().collisionDistance(checkPos);
00284 if (distance < radius)
00285 {
00286 collisionTargets[target->getPlayerId()] = target;
00287 }
00288 }
00289 }
00290 }
00291
00292 if (context_->getOptionsGame().getActionSyncCheck())
00293 {
00294 std::string targets;
00295 std::map<unsigned int, Target *>::iterator itor;
00296 for (itor = collisionTargets.begin();
00297 itor != collisionTargets.end();
00298 itor++)
00299 {
00300 targets.append(S3D::formatStringBuffer("%u:%i,%i,%i ",
00301 itor->second->getPlayerId(),
00302 itor->second->getLife().getTargetPosition()[0].getInternal(),
00303 itor->second->getLife().getTargetPosition()[1].getInternal(),
00304 itor->second->getLife().getTargetPosition()[2].getInternal()));
00305 }
00306
00307 context_->getActionController().addSyncCheck(
00308 S3D::formatStringBuffer("CollisionSet : %i,%i,%i %i \"%s\"",
00309 position[0].getInternal(),
00310 position[1].getInternal(),
00311 position[2].getInternal(),
00312 radius.getInternal(),
00313 targets.c_str()));
00314 }
00315 }
00316
00317 #ifndef S3D_SERVER
00318 #include <GLEXT/GLState.h>
00319 #include <client/ScorchedClient.h>
00320 #include <landscapemap/LandscapeMaps.h>
00321
00322 static void drawBox(Vector &position, Vector &size)
00323 {
00324 float wid = size[0];
00325 float hgt = size[1];
00326 float dep = size[2];
00327 glPushMatrix();
00328 glTranslatef(position[0], position[1], position[2]);
00329 glBegin(GL_LINE_LOOP);
00330
00331 glNormal3f(0,1,0);
00332 glVertex3f(-wid/2,hgt/2,dep/2);
00333 glVertex3f(wid/2,hgt/2,dep/2);
00334 glVertex3f(wid/2,hgt/2,-dep/2);
00335 glVertex3f(-wid/2,hgt/2,-dep/2);
00336 glEnd();
00337 glBegin(GL_LINE_LOOP);
00338
00339 glNormal3f(0,0,1);
00340 glVertex3f(-wid/2,hgt/2,dep/2);
00341 glVertex3f(-wid/2,-hgt/2,dep/2);
00342 glVertex3f(wid/2,-hgt/2,dep/2);
00343 glVertex3f(wid/2,hgt/2,dep/2);
00344 glEnd();
00345 glBegin(GL_LINE_LOOP);
00346
00347 glNormal3f(0,0,-1);
00348 glVertex3f(-wid/2,hgt/2,-dep/2);
00349 glVertex3f(wid/2,hgt/2,-dep/2);
00350 glVertex3f(wid/2,-hgt/2,-dep/2);
00351 glVertex3f(-wid/2,-hgt/2,-dep/2);
00352 glEnd();
00353 glBegin(GL_LINE_LOOP);
00354
00355 glNormal3f(1,0,0);
00356 glVertex3f(wid/2,hgt/2,-dep/2);
00357 glVertex3f(wid/2,hgt/2,dep/2);
00358 glVertex3f(wid/2,-hgt/2,dep/2);
00359 glVertex3f(wid/2,-hgt/2,-dep/2);
00360 glEnd();
00361 glBegin(GL_LINE_LOOP);
00362
00363 glNormal3f(-1,0,0);
00364 glVertex3f(-wid/2,hgt/2,dep/2);
00365 glVertex3f(-wid/2,hgt/2,-dep/2);
00366 glVertex3f(-wid/2,-hgt/2,-dep/2);
00367 glVertex3f(-wid/2,-hgt/2,dep/2);
00368 glEnd();
00369 glBegin(GL_LINE_LOOP);
00370
00371 glNormal3f(0,-1,0);
00372 glVertex3f(-wid/2,-hgt/2,dep/2);
00373 glVertex3f(-wid/2,-hgt/2,-dep/2);
00374 glVertex3f(wid/2,-hgt/2,-dep/2);
00375 glVertex3f(wid/2,-hgt/2,dep/2);
00376 glEnd();
00377 glPopMatrix();
00378 }
00379
00380 void TargetSpace::draw()
00381 {
00382 GLState glState(GLState::TEXTURE_OFF | GLState::LIGHTING_OFF);
00383
00384 for (int b=0; b<spaceHSq_; b++)
00385 {
00386 for (int a=0; a<spaceWSq_; a++)
00387 {
00388 int num = spaceHSq_ * b + a;
00389 DIALOG_ASSERT(num >= 0 && num < noSquares_);
00390
00391 Square *square = &squares_[num];
00392 if (square->targets.empty())
00393 {
00394 continue;
00395 }
00396
00397 Vector position(a * spaceSq_ + spaceX_ + spaceSq_ / 2,
00398 b * spaceSq_ + spaceY_ + spaceSq_ / 2, 0);
00399 position[2] =
00400 ScorchedClient::instance()->getLandscapeMaps().
00401 getGroundMaps().getHeight((int) position[0], (int) position[1]).asFloat() - 7.0f;
00402 Vector size(spaceSq_, spaceSq_, 20);
00403
00404 if (position[0] > ScorchedClient::instance()->getLandscapeMaps().
00405 getGroundMaps().getLandscapeWidth() ||
00406 position[1] > ScorchedClient::instance()->getLandscapeMaps().
00407 getGroundMaps().getLandscapeHeight())
00408 {
00409 continue;
00410 }
00411
00412 glColor3f(1.0f, 0.0f, 0.0f);
00413 drawBox(position, size);
00414
00415 glBegin(GL_LINES);
00416 std::map<unsigned int, Target *>::iterator itor;
00417 for (itor = square->targets.begin();
00418 itor != square->targets.end();
00419 itor++)
00420 {
00421 Target *target = (*itor).second;
00422 glVertex3fv(target->getLife().getFloatPosition());
00423 glVertex3f(position[0], position[1], position[2] + 10.0f);
00424 }
00425 glEnd();
00426 }
00427 }
00428 }
00429 #endif