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
00016
00017
00018 inline bool FastEcslent::Move::done() {
00019 return (entity->pos.squaredDistance((target->location)) <= entity->turningRadius);
00020 }
00021
00022 void FastEcslent::Move::init(){
00023 Ogre::Vector3 diff = target->location - entity->pos;
00024 entity->desiredHeading = -atan2(diff.z, diff.x);
00025 entity->desiredSpeed = entity->maxSpeed;
00026 return;
00027 }
00028
00029 inline void FastEcslent::Move::tick(double dt) {
00030 if(!done()) {
00031 relativePos = target->location - entity->pos;
00032 entity->desiredHeading = -atan2(relativePos.z, relativePos.x);
00033 entity->desiredSpeed = entity->maxSpeed;
00034 } else {
00035 entity->desiredSpeed = 0.0f;
00036 }
00037 return;
00038 }
00039
00040
00041 inline void FastEcslent::Wait::init(){
00042 timeLeftToWait = target->waitTime;
00043
00044 }
00045 inline bool FastEcslent::Wait::done(){
00046 return timeLeftToWait < 0.0;
00047 }
00048
00049 inline void FastEcslent::Wait::tick(double dt){
00050 if(timeLeftToWait > 0) {
00051 timeLeftToWait -= dt;
00052 } else {
00053 DEBUG(std::cout << entity->uiname << ": Done waiting" << std::endl;)
00054 }
00055 }
00056
00057
00058
00059
00060
00061 inline bool FastEcslent::PotentialMove::done(){
00062
00063 return (entity->pos.squaredDistance(target->location) <= (entity->turningRadius * entity->turningRadius)*10.0);
00064 }
00065
00066 void FastEcslent::PotentialMove::init(){
00067 Ogre::Vector3 diff = target->location - entity->pos;
00068 entity->desiredSpeed = entity->maxSpeed;
00069
00070 }
00071
00072 inline void FastEcslent::PotentialMove::tick(double dt){
00073 int nEnts = entity->engine->entityMgr->nEnts;
00074
00075 if (!done()){
00076
00077 double repulsivePotential = 0.0f;
00078 entity->potentialVec = Ogre::Vector3::ZERO;
00079 Ogre::Vector3 tmp;
00080 int nInRange = 1;
00081 for (int i = 0; i < nEnts; i++){
00082 if(i != entity->entityId.id){
00083 if (entity->engine->distanceMgr->distance[entity->entityId.id][i] < RepulsionThresholdDistance) {
00084 nInRange += 1;
00085 tmp = (entity->engine->distanceMgr->normalizedDistanceVec[i][entity->entityId.id]);
00086 repulsivePotential = (B * entity->engine->entityMgr->ents[i]->mass) / pow(entity->engine->distanceMgr->distance[entity->entityId.id][i], m);
00087 entity->potentialVec += (tmp * repulsivePotential);
00088 }
00089 }
00090 }
00091
00092
00093 tmp = (entity->pos - target->location);
00094
00095 double targetDistance = tmp.length();
00096 entity->attractivePotential = -(A ) / pow(targetDistance, n);
00097 entity->potentialVec += (tmp.normalisedCopy() * entity->attractivePotential * nInRange);
00098
00099
00100
00101 entity->desiredHeading = atan2(-entity->potentialVec.z, entity->potentialVec.x);
00102 double cosDiffFrac = (1.0 - cos(entity->vel.angleBetween(entity->potentialVec).valueRadians()))/2.0;
00103 entity->desiredSpeed = (entity->maxSpeed - entity->minSpeed) * (1.0 - cosDiffFrac);
00104
00105
00106
00107
00108 } else {
00109 DEBUG(std::cout << "Attractive Potential: " << entity->attractivePotential << std::endl;)
00110 entity->desiredSpeed = 0.0f;
00111 entity->desiredHeading = entity->heading;
00112 }
00113 }
00114
00115
00116
00117
00118 FastEcslent::Maintain::Maintain (Entity *ent, Target *tgt): UnitCommand(ent, MaintainCommand, tgt){
00119 if(valid(tgt->entity)) {
00120 DEBUG(std::cout << "Maintaining with respect to: " << tgt->entity->uiname << std::endl;)
00121 tgt->location = tgt->entity->pos + tgt->offset;
00122 }
00123 }
00124 bool FastEcslent::Maintain::valid(Entity *entity) {
00125 return true;
00126 }
00127
00128 inline bool FastEcslent::Maintain::done() {
00129 return false;
00130 }
00131
00132 void FastEcslent::Maintain::init(){
00133
00134 if (kInvalidFloat == target->offsetDistance) {
00135 Ogre::Quaternion q = Ogre::Vector3(cos(-target->entity->heading) * 100.0f, 0.0f, sin(-target->entity->heading) * 100.0f).getRotationTo(target->offset);
00136 target->offsetYaw = q.getYaw().valueRadians();
00137 target->offsetDistance = (target->entity->pos - target->offset).length();
00138 DEBUG(std::cout << "OffsetYaw: " << target->offsetYaw << " offsetDistance: " << target->offsetDistance << std::endl;)
00139 }
00140 return;
00141 }
00142
00143 inline void FastEcslent::Maintain::tick(double dt) {
00144 target->offset = (target->entity->rot * Ogre::Quaternion(Ogre::Radian(target->offsetYaw), Ogre::Vector3::UNIT_Y)) * (Ogre::Vector3::UNIT_X * target->offsetDistance);
00145 target->location = target->entity->pos + target->offset;
00146
00147 relativePos = target->location - entity->pos;
00148 relativeVel = target->entity->vel - entity->vel;
00149 relativeSpeed = relativeVel.length();
00150 predictedTimeToClose = relativePos.length()/relativeSpeed;
00151 predictedPos = target->location + (target->entity->vel * predictedTimeToClose);
00152 interceptPos = predictedPos - entity->pos;
00153
00154 entity->desiredHeading = -atan2(interceptPos.z, interceptPos.x);
00155 if ((relativeSpeed * predictedTimeToClose) > 30)
00156 entity->desiredSpeed = entity->maxSpeed;
00157 else
00158 entity->desiredSpeed = target->entity->speed;
00159
00160 return;
00161 }
00162
00163
00164 void FastEcslent::Tactic::changeLeadership(LeadershipType selector){
00165
00166 Ogre::Vector3 tpos;
00167 if(this->target->target.location == InvalidLocation){
00168 tpos = this->target->target.entity->pos;
00169 } else {
00170 tpos = this->target->target.location;
00171 }
00172 this->group->leaderIndex = 0;
00173 if (this->group->nEntitiesInGroup > 0) {
00174 switch(selector){
00175 case 0:
00176 this->group->leaderIndex = closestToTarget(true, tpos);
00177 break;
00178 case 2:
00179 this->group->leaderIndex = closestToTarget(false, tpos);
00180 break;
00181 case 3:
00182 this->group->leaderIndex = mostMassive(true);
00183 break;
00184 case 4:
00185 this->group->leaderIndex = mostMassive(true);
00186 break;
00187 case 5:
00188 this->group->leaderIndex = randInt(0, this->group->nEntitiesInGroup);
00189 break;
00190 default:
00191 this->group->leaderIndex = 0;
00192 break;
00193 }
00194 }
00195
00196 }
00197
00198
00199 int FastEcslent::Tactic::mostMassive(bool massest){
00200 float minMass = 0;
00201 int minIndex = INT_MAX;
00202 float maxMass = 0;
00203 int maxIndex = 0;
00204 float mass;
00205 for (int i = 0; i < this->group->nEntitiesInGroup; i++){
00206 mass = this->group->members[i]->mass;
00207 if(mass < minMass){
00208 minMass = mass;
00209 minIndex = i;
00210 }
00211 if (mass > maxMass){
00212 maxMass = mass;
00213 maxIndex = i;
00214 }
00215 }
00216 if(!massest) {
00217 return minIndex;
00218 } else {
00219 return maxIndex;
00220 }
00221
00222 }
00223
00224
00225 int FastEcslent::Tactic::closestToTarget(bool closest, Ogre::Vector3 tpos){
00226
00227
00228
00229 float minDist = 0;
00230 int minIndex = INT_MAX;
00231 float maxDist = 0;
00232 int maxIndex = 0;
00233 float dist;
00234 for (int i = 0; i < this->group->nEntitiesInGroup; i++){
00235 dist = this->group->members[i]->pos.distance(tpos);
00236 if(dist < minDist) {
00237 minDist = dist;
00238 minIndex = i;
00239 }
00240 if (dist > maxDist){
00241 maxDist = dist;
00242 maxIndex = i;
00243 }
00244 }
00245 if(closest) {
00246 return minIndex;
00247 } else {
00248 return maxIndex;
00249 }
00250 }