00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009 #include <ent.h>
00010 #include <group.h>
00011 #include <target.h>
00012 #include <engine.h>
00013 #include <OgreVector3.h>
00014 #include "DEBUG.h"
00015 #include "buildings.h"
00016 #include "command.h"
00017
00018
00019 inline bool FastEcslent::Move::done() {
00020 return (entity->pos.squaredDistance((target->location)) <= entity->turningRadius);
00021 }
00022
00023 void FastEcslent::Move::init(){
00024 Ogre::Vector3 diff = target->location - entity->pos;
00025 entity->desiredHeading = -atan2(diff.z, diff.x);
00026 entity->desiredSpeed = entity->maxSpeed;
00027 return;
00028 }
00029
00030 inline void FastEcslent::Move::tick(double dt) {
00031 if(!done()) {
00032 relativePos = target->location - entity->pos;
00033 entity->desiredHeading = -atan2(relativePos.z, relativePos.x);
00034 entity->desiredSpeed = entity->maxSpeed;
00035 } else {
00036 entity->desiredSpeed = 0.0f;
00037 }
00038 return;
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 inline void FastEcslent::BuildCommand::init()
00067 {
00068 if(entity != NULL && entity->getAspect(BUILDER) != NULL)
00069 {
00070
00071
00072
00073 Builder* builder = dynamic_cast<Builder *> (entity->getAspect(BUILDER));
00074
00075
00076 builder->enqueue(entType);
00077
00078 }
00079 isDone = true;
00080
00081
00082 }
00083 inline bool FastEcslent::BuildCommand::done(){
00084 return isDone;
00085 }
00086
00087 inline void FastEcslent::BuildCommand::tick(double dt){
00088
00089
00090 }
00091
00092
00093 inline void FastEcslent::Wait::init(){
00094 timeLeftToWait = target->waitTime;
00095
00096 }
00097 inline bool FastEcslent::Wait::done(){
00098 return timeLeftToWait < 0.0;
00099 }
00100
00101 inline void FastEcslent::Wait::tick(double dt){
00102 if(timeLeftToWait > 0) {
00103 timeLeftToWait -= dt;
00104 } else {
00105 DEBUG(std::cout << entity->uiname << ": Done waiting" << std::endl;)
00106 }
00107 }
00108
00109
00110
00111 inline void FastEcslent::GasFieldCommand::init(){
00112
00113 }
00114 inline bool FastEcslent::GasFieldCommand::done(){
00115 return false;
00116 }
00117
00118 inline void FastEcslent::GasFieldCommand::tick(double dt){
00119 if(((FastEcslent::Gas*)this->entity)->refinary != NULL && ((FastEcslent::Gas*)this->entity)->refinary->entityState != FastEcslent::DEAD)
00120 {
00121 this->entity->selectable = false;
00122 this->entity->isSelected = false;
00123 ((FastEcslent::Gas*)this->entity)->refinary= NULL;
00124 }
00125 else
00126 {
00127 this->entity->selectable = true;
00128 }
00129 }
00130
00131
00132
00133
00134
00135 inline bool FastEcslent::PotentialMove::done(){
00136
00137 return (entity->pos.squaredDistance(target->location) <= (entity->turningRadius * entity->turningRadius)*10.0);
00138 }
00139
00140 void FastEcslent::PotentialMove::init(){
00141 Ogre::Vector3 diff = target->location - entity->pos;
00142 entity->desiredSpeed = entity->maxSpeed;
00143
00144 }
00145
00146 inline void FastEcslent::PotentialMove::tick(double dt){
00147 int nEnts = entity->engine->entityMgr->nEnts;
00148
00149 if (!done()){
00150
00151 double repulsivePotential = 0.0f;
00152 entity->potentialVec = Ogre::Vector3::ZERO;
00153 Ogre::Vector3 tmp;
00154 int nInRange = 1;
00155 for (int i = 0; i < nEnts; i++){
00156 if(i != entity->entityId.id){
00157 if (entity->engine->distanceMgr->distance[entity->entityId.id][i] < RepulsionThresholdDistance) {
00158 nInRange += 1;
00159 tmp = (entity->engine->distanceMgr->normalizedDistanceVec[i][entity->entityId.id]);
00160 repulsivePotential = (B * entity->engine->entityMgr->ents[i]->mass) / pow(entity->engine->distanceMgr->distance[entity->entityId.id][i], m);
00161 if(repulsivePotential > INT_MAX){
00162 repulsivePotential = INT_MAX;
00163 }
00164 entity->potentialVec += (tmp * repulsivePotential);
00165 }
00166 }
00167 }
00168
00169 tmp = (entity->pos - target->location);
00170
00171 double targetDistance = tmp.length();
00172 entity->attractivePotential = -(A ) / pow(targetDistance, n);
00173 entity->potentialVec += (tmp.normalisedCopy() * entity->attractivePotential * nInRange);
00174
00175
00176 entity->desiredHeading = atan2(-entity->potentialVec.z, entity->potentialVec.x);
00177
00178 double cosDiffFrac = (1.0 - cos(entity->vel.angleBetween(entity->potentialVec).valueRadians()))/2.0;
00179 entity->desiredSpeed = (entity->maxSpeed - entity->minSpeed) * (1.0 - cosDiffFrac);
00180
00181
00182
00183
00184 } else {
00185 DEBUG(std::cout << "Attractive Potential: " << entity->attractivePotential << std::endl;)
00186 entity->desiredSpeed = 0.0f;
00187 entity->desiredHeading = entity->heading;
00188 }
00189 }
00190
00191
00192
00193
00194 FastEcslent::Maintain::Maintain (Entity *ent, Target *tgt): UnitCommand(ent, MaintainCommand, tgt){
00195 if(valid(tgt->entity)) {
00196 DEBUG(std::cout << "Maintaining with respect to: " << tgt->entity->uiname << std::endl;)
00197 tgt->location = tgt->entity->pos + tgt->offset;
00198 }
00199 }
00200 bool FastEcslent::Maintain::valid(Entity *entity) {
00201 return true;
00202 }
00203
00204 inline bool FastEcslent::Maintain::done() {
00205 return false;
00206 }
00207
00208 void FastEcslent::Maintain::init(){
00209
00210 if (kInvalidFloat == target->offsetDistance) {
00211 Ogre::Quaternion q = Ogre::Vector3(cos(-target->entity->heading) * 100.0f, 0.0f, sin(-target->entity->heading) * 100.0f).getRotationTo(target->offset);
00212 target->offsetYaw = q.getYaw().valueRadians();
00213 target->offsetDistance = (target->entity->pos - target->offset).length();
00214 DEBUG(std::cout << "OffsetYaw: " << target->offsetYaw << " offsetDistance: " << target->offsetDistance << std::endl;)
00215 }
00216 return;
00217 }
00218
00219 inline void FastEcslent::Maintain::tick(double dt) {
00220 target->offset = (target->entity->rot * Ogre::Quaternion(Ogre::Radian(target->offsetYaw), Ogre::Vector3::UNIT_Y)) * (Ogre::Vector3::UNIT_X * target->offsetDistance);
00221 target->location = target->entity->pos + target->offset;
00222
00223 relativePos = target->location - entity->pos;
00224 relativeVel = target->entity->vel - entity->vel;
00225 relativeSpeed = relativeVel.length();
00226 predictedTimeToClose = relativePos.length()/relativeSpeed;
00227 predictedPos = target->location + (target->entity->vel * predictedTimeToClose);
00228 interceptPos = predictedPos - entity->pos;
00229
00230 entity->desiredHeading = -atan2(interceptPos.z, interceptPos.x);
00231 if ((relativeSpeed * predictedTimeToClose) > 30)
00232 entity->desiredSpeed = entity->maxSpeed;
00233 else
00234 entity->desiredSpeed = target->entity->speed;
00235
00236 return;
00237 }
00238
00239
00240 void FastEcslent::Tactic::changeLeadership(LeadershipType selector){
00241
00242 Ogre::Vector3 tpos;
00243 if(this->target->target.location == InvalidLocation){
00244 tpos = this->target->target.entity->pos;
00245 } else {
00246 tpos = this->target->target.location;
00247 }
00248 this->group->leaderIndex = 0;
00249 if (this->group->nEntitiesInGroup > 0) {
00250 switch(selector){
00251 case 0:
00252 this->group->leaderIndex = closestToTarget(true, tpos);
00253 break;
00254 case 2:
00255 this->group->leaderIndex = closestToTarget(false, tpos);
00256 break;
00257 case 3:
00258 this->group->leaderIndex = mostMassive(true);
00259 break;
00260 case 4:
00261 this->group->leaderIndex = mostMassive(true);
00262 break;
00263 case 5:
00264 this->group->leaderIndex = randInt(0, this->group->nEntitiesInGroup);
00265 break;
00266 default:
00267 this->group->leaderIndex = 0;
00268 break;
00269 }
00270 }
00271
00272 }
00273
00274
00275 int FastEcslent::Tactic::mostMassive(bool massest){
00276 float minMass = 0;
00277 int minIndex = INT_MAX;
00278 float maxMass = 0;
00279 int maxIndex = 0;
00280 float mass;
00281 for (int i = 0; i < this->group->nEntitiesInGroup; i++){
00282 mass = this->group->members[i]->mass;
00283 if(mass < minMass){
00284 minMass = mass;
00285 minIndex = i;
00286 }
00287 if (mass > maxMass){
00288 maxMass = mass;
00289 maxIndex = i;
00290 }
00291 }
00292 if(!massest) {
00293 return minIndex;
00294 } else {
00295 return maxIndex;
00296 }
00297
00298 }
00299
00300
00301 int FastEcslent::Tactic::closestToTarget(bool closest, Ogre::Vector3 tpos){
00302
00303
00304
00305 float minDist = 0;
00306 int minIndex = INT_MAX;
00307 float maxDist = 0;
00308 int maxIndex = 0;
00309 float dist;
00310 for (int i = 0; i < this->group->nEntitiesInGroup; i++){
00311 dist = this->group->members[i]->pos.distance(tpos);
00312 if(dist < minDist) {
00313 minDist = dist;
00314 minIndex = i;
00315 }
00316 if (dist > maxDist){
00317 maxDist = dist;
00318 maxIndex = i;
00319 }
00320 }
00321 if(closest) {
00322 return minIndex;
00323 } else {
00324 return maxIndex;
00325 }
00326 }