00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <tank/TankLib.h>
00022 #include <tank/TankContainer.h>
00023 #include <tank/TankPosition.h>
00024 #include <tank/TankState.h>
00025 #include <common/RandomGenerator.h>
00026 #include <common/OptionsTransient.h>
00027 #include <common/Defines.h>
00028 #include <landscapemap/LandscapeMaps.h>
00029 #ifndef S3D_SERVER
00030 #include <GLEXT/GLState.h>
00031 #endif
00032 #include <math.h>
00033
00034 fixed TankLib::getDistanceToTank(FixedVector &position, Tank *targetTank)
00035 {
00036 FixedVector currentdirection =
00037 targetTank->getPosition().getTankPosition() - position;
00038 fixed maxdistance2D = (currentdirection[0] *
00039 currentdirection[0] + currentdirection[1] * currentdirection[1]).sqrt();
00040 return maxdistance2D;
00041 }
00042
00043 void TankLib::getTanksSortedByDistance(ScorchedContext &context,
00044 FixedVector &position,
00045 std::list<std::pair<fixed, Tank *> > &result,
00046 unsigned int teams,
00047 fixed maxDistance)
00048 {
00049 std::list<std::pair<fixed, Tank *> > tankDistList;
00050 std::map<unsigned int, Tank *> &allCurrentTanks =
00051 context.getTankContainer().getAllTanks();
00052 std::map<unsigned int, Tank *>::iterator itor;
00053 for (itor = allCurrentTanks.begin();
00054 itor != allCurrentTanks.end();
00055 itor++)
00056 {
00057 Tank *targetTank = (*itor).second;
00058 if (targetTank->getState().getState() == TankState::sNormal)
00059 {
00060 if (teams > 0 && teams == targetTank->getTeam()) continue;
00061
00062 fixed maxdistance2D = getDistanceToTank(position, targetTank);
00063 tankDistList.push_back(std::pair<fixed, Tank*>(maxdistance2D, targetTank));
00064 }
00065 }
00066
00067 while (!tankDistList.empty())
00068 {
00069 std::list<std::pair<fixed, Tank *> >::iterator removeItor = tankDistList.begin();
00070 std::list<std::pair<fixed, Tank *> >::iterator itor = tankDistList.begin(); itor++;
00071 for (;itor != tankDistList.end(); itor++)
00072 {
00073 if ((*itor).first < (*removeItor).first)
00074 {
00075 removeItor = itor;
00076 }
00077 }
00078
00079 if ((*removeItor).first <= maxDistance || maxDistance == -1) result.push_back(*removeItor);
00080 tankDistList.erase(removeItor);
00081 }
00082 }
00083
00084 bool TankLib::intersection(ScorchedContext &context,
00085 FixedVector position, fixed xy, fixed yz, fixed power,
00086 int dist)
00087 {
00088 FixedVector startPosition = position;
00089 FixedVector velocity = getVelocityVector(xy, yz) * power / fixed(250);
00090
00091 do
00092 {
00093 if (position[2] < context.getLandscapeMaps().getGroundMaps().getInterpHeight(
00094 position[0], position[1]))
00095 {
00096 return true;
00097 }
00098 position += velocity;
00099 velocity += FixedVector(0, 0, fixed(true, -0002));
00100 } while ((position - startPosition).Magnitude() < dist);
00101
00102 return false;
00103 }
00104
00105 bool TankLib::getSniperShotTowardsPosition(ScorchedContext &context,
00106 FixedVector &position, FixedVector &shootAt, fixed distForSniper,
00107 fixed &angleXYDegs, fixed &angleYZDegs, fixed &power,
00108 bool checkIntersection)
00109 {
00110
00111 power = fixed(1000);
00112
00113
00114 FixedVector direction = shootAt - position;
00115 fixed angleXYRads = atan2x(direction[1], direction[0]);
00116 angleXYDegs = (angleXYRads / fixed::XPI) * fixed(180) - fixed(90);
00117 if (angleXYDegs > 88) angleXYDegs = 0;
00118
00119 fixed distance2D = (direction[0] * direction[0] +
00120 direction[1] * direction[1]).sqrt();
00121 fixed angleYZRads = atan2x(distance2D, direction[2]);
00122 angleYZDegs = fixed(90) - ((angleYZRads /fixed::XPI) * fixed(180));
00123
00124
00125
00126
00127 bool useSniper = ((distance2D < distForSniper) && (shootAt[2] >= position[2] - fixed(2))) ||
00128 (distForSniper == fixed(-1));
00129 if (!useSniper) return false;
00130
00131
00132 if (checkIntersection)
00133 {
00134
00135
00136 int allowedIntersectDist = (direction.Magnitude() - fixed(10)).asInt();
00137 if (intersection(context, position - FixedVector(0, 0, 1),
00138 angleXYDegs, angleYZDegs, power, allowedIntersectDist))
00139 {
00140 return false;
00141 }
00142 }
00143
00144 return true;
00145 }
00146
00147 void TankLib::getShotTowardsPosition(ScorchedContext &context,
00148 RandomGenerator &random,
00149 FixedVector &position, FixedVector &shootAt,
00150 fixed &angleXYDegs, fixed &angleYZDegs, fixed &power)
00151 {
00152
00153 FixedVector direction = shootAt - position;
00154 fixed angleXYRads = atan2x(direction[1], direction[0]);
00155 angleXYDegs = (angleXYRads / fixed::XPI) * fixed(180) - fixed(90);
00156 fixed distance2D = (direction[0] * direction[0] +
00157 direction[1] * direction[1]).sqrt();
00158
00159
00160 power = fixed(1000);
00161 if (distance2D < 200)
00162 {
00163 power = 750;
00164 if (distance2D < 100)
00165 {
00166 power = 550;
00167 if (distance2D < 5)
00168 {
00169 power = 350;
00170 }
00171 }
00172 }
00173
00174
00175 power += (random.getRandFixed() * 200) - 100;
00176 if (power < 100) power = 100;
00177
00178 if (context.getOptionsTransient().getWindOn())
00179 {
00180
00181 fixed windMag = context.getOptionsTransient().getWindSpeed() / 5;
00182
00183
00184 FixedVector ndirection = direction;
00185 ndirection[2] = 0;
00186 ndirection = ndirection.Normalize();
00187 ndirection = ndirection.get2DPerp();
00188 fixed windoffsetLR = context.getOptionsTransient().getWindDirection().dotP(ndirection);
00189 angleXYDegs += windoffsetLR * distance2D * (fixed(true, 1200) + random.getRandFixed()) * fixed(true, 400) * windMag;
00190
00191 fixed windoffsetFB = context.getOptionsTransient().getWindDirection().dotP(direction.Normalize());
00192 windoffsetFB /= 10;
00193 windoffsetFB *= windMag;
00194 windoffsetFB += 1;
00195
00196 power *= windoffsetFB;
00197 }
00198
00199
00200 angleYZDegs = 45;
00201 }
00202
00203 FixedVector &TankLib::getVelocityVector(fixed xy, fixed yz)
00204 {
00205 static FixedVector diff;
00206 diff = FixedVector(
00207 (-xy / fixed(180) * fixed::XPI).sin() * (yz / fixed(180) * fixed::XPI).cos(),
00208 (-xy / fixed(180) * fixed::XPI).cos() * (yz / fixed(180) * fixed::XPI).cos(),
00209 ( yz / fixed(180) * fixed::XPI).sin());
00210 diff /= 20;
00211 diff *= fixed(true, 12000);
00212 return diff;
00213 }
00214
00215 FixedVector &TankLib::getGunPosition(fixed xy, fixed yz)
00216 {
00217 static FixedVector pos;
00218 fixed gunLength = 1;
00219 fixed degToRad = fixed(180) * fixed::XPI;
00220 pos[0] = gunLength * (xy / degToRad).sin() *
00221 ((fixed(90) - yz) / degToRad).sin();
00222 pos[1] = gunLength * (xy / degToRad).cos() *
00223 ((fixed(90) - yz) / degToRad).sin();
00224 pos[2] = gunLength * ((fixed(90) - yz) / degToRad).cos();
00225
00226 return pos;
00227 }
00228