Changeset 8939 for code/branches/formation/src
- Timestamp:
- Nov 16, 2011, 4:08:23 PM (13 years ago)
- Location:
- code/branches/formation/src/orxonox/controllers
- Files:
-
- 2 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/formation/src/orxonox/controllers/ArtificialController.cc
r8908 r8939 30 30 31 31 #include <vector> 32 #include <climits> 32 33 33 34 34 #include "util/Math.h" … … 41 41 #include "gametypes/TeamDeathmatch.h" 42 42 #include "gametypes/Dynamicmatch.h" 43 #include "controllers/WaypointPatrolController.h" 44 #include "controllers/NewHumanController.h" 45 #include "controllers/DroneController.h" 43 46 44 47 45 namespace orxonox 48 46 { 49 SetConsoleCommand("ArtificialController", "formationflight", &ArtificialController::formationflight);50 SetConsoleCommand("ArtificialController", "masteraction", &ArtificialController::masteraction);51 SetConsoleCommand("ArtificialController", "followme", &ArtificialController::followme);52 SetConsoleCommand("ArtificialController", "passivebehaviour", &ArtificialController::passivebehaviour);53 SetConsoleCommand("ArtificialController", "formationsize", &ArtificialController::formationsize);54 47 55 static const unsigned int STANDARD_MAX_FORMATION_SIZE = 7; 56 static const int RADIUS_TO_SEARCH_FOR_MASTERS = 5000; 57 static const int FORMATION_LENGTH = 130; 58 static const int FORMATION_WIDTH = 110; 59 static const int FREEDOM_COUNT = 4; //seconds the slaves in a formation will be set free when master attacks an enemy 60 static const float SPEED_MASTER = 0.6f; 61 static const float ROTATEFACTOR_MASTER = 0.2f; 62 static const float SPEED_FREE = 0.8f; 63 static const float ROTATEFACTOR_FREE = 0.8f; 64 65 66 ArtificialController::ArtificialController(BaseObject* creator) : Controller(creator) 48 ArtificialController::ArtificialController(BaseObject* creator) : Masterable(creator) 67 49 { 68 RegisterObject(ArtificialController); 69 70 this->target_ = 0; 71 this->formationFlight_ = false; 72 this->passive_ = false; 73 this->maxFormationSize_ = STANDARD_MAX_FORMATION_SIZE; 74 this->myMaster_ = 0; 75 this->freedomCount_ = 0; 76 this->team_ = -1; 77 this->state_ = FREE; 78 this->specificMasterAction_ = NONE; 79 this->specificMasterActionHoldCount_ = 0; 80 this->bShooting_ = false; 81 this->bHasTargetPosition_ = false; 82 this->bHasTargetOrientation_=false; 83 this->speedCounter_ = 0.2f; 84 this->targetPosition_ = Vector3::ZERO; 85 86 this->target_.setCallback(createFunctor(&ArtificialController::targetDied, this)); 50 87 51 } 88 52 89 53 ArtificialController::~ArtificialController() 90 54 { 91 if (this->isInitialized()) 92 { 93 this->removeFromFormation(); 94 95 for (ObjectList<ArtificialController>::iterator it = ObjectList<ArtificialController>::begin(); it; ++it) 96 { 97 if (*it != this) 98 { 99 if (it->myMaster_ == this) 100 { 101 orxout(internal_error) << this << " is still master in " << (*it) << endl; 102 it->myMaster_ = 0; 103 } 104 105 while (true) 106 { 107 std::vector<ArtificialController*>::iterator it2 = std::find(it->slaves_.begin(), it->slaves_.end(), this); 108 if (it2 != it->slaves_.end()) 109 { 110 orxout(internal_error) << this << " is still slave in " << (*it) << endl; 111 it->slaves_.erase(it2); 112 } 113 else 114 break; 115 } 116 } 117 } 118 } 55 119 56 } 120 57 121 void ArtificialController::XMLPort(Element& xmlelement, XMLPort::Mode mode)122 {123 SUPER(ArtificialController, XMLPort, xmlelement, mode);124 125 XMLPortParam(ArtificialController, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);126 XMLPortParam(ArtificialController, "formationFlight", setFormationFlight, getFormationFlight, xmlelement, mode).defaultValues(false);127 XMLPortParam(ArtificialController, "formationSize", setFormationSize, getFormationSize, xmlelement, mode).defaultValues(STANDARD_MAX_FORMATION_SIZE);128 XMLPortParam(ArtificialController, "passive", setPassive, getPassive, xmlelement, mode).defaultValues(false);129 }130 131 // Documentation only here to get a faster overview for creating a useful documentation...132 133 /**134 @brief Activates / deactivates formationflight behaviour135 @param form activate formflight if form is true136 */137 void ArtificialController::formationflight(const bool form)138 {139 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)140 {141 Controller* controller = 0;142 143 if (it->getController())144 controller = it->getController();145 else if (it->getXMLController())146 controller = it->getXMLController();147 148 if (!controller)149 continue;150 151 ArtificialController *aiController = orxonox_cast<ArtificialController*>(controller);152 153 if (aiController)154 {155 aiController->formationFlight_ = form;156 if (!form)157 {158 aiController->removeFromFormation();159 }160 }161 }162 }163 164 /**165 @brief Get all masters to do a "specific master action"166 @param action which action to perform (integer, so it can be called with a console command (tmp solution))167 */168 void ArtificialController::masteraction(const int action)169 {170 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)171 {172 Controller* controller = 0;173 174 if (it->getController())175 controller = it->getController();176 else if (it->getXMLController())177 controller = it->getXMLController();178 179 if (!controller)180 continue;181 182 ArtificialController *aiController = orxonox_cast<ArtificialController*>(controller);183 184 if(aiController && aiController->state_ == MASTER)185 {186 if (action == 1)187 aiController->spinInit();188 if (action == 2)189 aiController->turn180Init();190 }191 }192 }193 194 /**195 @brief A human player gets followed by its nearest master. Initiated by console command, so far intended for demonstration puproses (possible future pickup).196 */197 void ArtificialController::followme()198 {199 200 Pawn *humanPawn = NULL;201 NewHumanController *currentHumanController = NULL;202 std::vector<ArtificialController*> allMasters;203 204 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)205 {206 Controller* controller = 0;207 208 if (it->getController())209 controller = it->getController();210 else if (it->getXMLController())211 controller = it->getXMLController();212 213 if (!controller)214 continue;215 216 currentHumanController = orxonox_cast<NewHumanController*>(controller);217 218 if(currentHumanController) humanPawn = *it;219 220 ArtificialController *aiController = orxonox_cast<ArtificialController*>(controller);221 222 if(aiController && aiController->state_ == MASTER)223 allMasters.push_back(aiController);224 225 }226 227 if((humanPawn != NULL) && (allMasters.size() != 0))228 {229 float posHuman = humanPawn->getPosition().length();230 float distance = 0.0f;231 float minDistance = FLT_MAX;232 int index = 0;233 int i = 0;234 235 for(std::vector<ArtificialController*>::iterator it = allMasters.begin(); it != allMasters.end(); it++, i++)236 {237 if (!ArtificialController::sameTeam((*it)->getControllableEntity(), humanPawn, (*it)->getGametype())) continue;238 distance = posHuman - (*it)->getControllableEntity()->getPosition().length();239 if(distance < minDistance) index = i;240 }241 allMasters[index]->followInit(humanPawn);242 }243 244 }245 246 /**247 @brief Sets shooting behaviour of pawns.248 @param passive if true, bots won't shoot.249 */250 void ArtificialController::passivebehaviour(const bool passive)251 {252 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)253 {254 Controller* controller = 0;255 256 if (it->getController())257 controller = it->getController();258 else if (it->getXMLController())259 controller = it->getXMLController();260 261 if (!controller)262 continue;263 264 ArtificialController *aiController = orxonox_cast<ArtificialController*>(controller);265 266 if(aiController)267 {268 aiController->passive_ = passive;269 }270 }271 }272 273 274 /**275 @brief Sets maximal formation size276 @param size maximal formation size.277 */278 void ArtificialController::formationsize(const int size)279 {280 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)281 {282 Controller* controller = 0;283 284 if (it->getController())285 controller = it->getController();286 else if (it->getXMLController())287 controller = it->getXMLController();288 289 if (!controller)290 continue;291 292 ArtificialController *aiController = orxonox_cast<ArtificialController*>(controller);293 294 if(aiController)295 {296 aiController->maxFormationSize_ = size;297 }298 }299 }300 58 301 59 /** … … 308 66 } 309 67 310 void ArtificialController::removeFromFormation()311 {312 if (this->state_ == SLAVE || this->myMaster_) // slaves can also be temporary free, so check if myMaster_ is set313 this->unregisterSlave();314 else if (this->state_ == MASTER)315 this->setNewMasterWithinFormation();316 }317 318 void ArtificialController::moveToPosition(const Vector3& target)319 {320 if (!this->getControllableEntity())321 return;322 323 // Slave uses special movement if its master is in FOLLOW mode324 if(this->state_ == SLAVE && this->myMaster_ && this->myMaster_->specificMasterAction_ == FOLLOW)325 {326 // this->followForSlaves(target);327 // return;328 }329 330 Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);331 float distance = (target - this->getControllableEntity()->getPosition()).length();332 333 334 if(this->state_ == FREE)335 {336 if (this->target_ || distance > 10)337 {338 // Multiply with ROTATEFACTOR_FREE to make them a bit slower339 this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * sgn(coord.x) * coord.x*coord.x);340 this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * sgn(coord.y) * coord.y*coord.y);341 }342 343 if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())344 {345 this->getControllableEntity()->moveFrontBack(-0.05f); // They don't brake with full power to give the player a chance346 } else this->getControllableEntity()->moveFrontBack(SPEED_FREE);347 }348 349 350 351 if(this->state_ == MASTER)352 {353 if (this->target_ || distance > 10)354 {355 this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);356 this->getControllableEntity()->rotatePitch(ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);357 }358 359 if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())360 {361 this->getControllableEntity()->moveFrontBack(-0.05f);362 } else this->getControllableEntity()->moveFrontBack(SPEED_MASTER);363 }364 365 366 367 if(this->state_ == SLAVE)368 {369 370 this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);371 this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);372 373 if (distance < 300)374 {375 if (bHasTargetOrientation_)376 {377 copyTargetOrientation();378 }379 if (distance < 40)380 {381 this->getControllableEntity()->moveFrontBack(0.8f*SPEED_MASTER);382 383 } else this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);384 385 } else {386 this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);387 }388 }389 390 if (distance < 10)391 {392 this->positionReached();393 bHasTargetOrientation_=false;394 }395 }396 397 void ArtificialController::moveToTargetPosition()398 {399 this->moveToPosition(this->targetPosition_);400 }401 402 void ArtificialController::copyOrientation(const Quaternion& orient)403 {404 //roll angle in radian, difference between master and slave405 float diff=orient.getRoll().valueRadians()-(this->getControllableEntity()->getOrientation().getRoll().valueRadians());406 if ((diff<math::twoPi && diff>math::pi) || diff>(math::pi)*3)407 {408 diff=diff-math::twoPi;409 }410 this->getControllableEntity()->rotateRoll(1.0f*ROTATEFACTOR_MASTER*diff);411 }412 413 void ArtificialController::copyTargetOrientation()414 {415 if (bHasTargetOrientation_)416 {417 copyOrientation(targetOrientation_);418 }419 }420 421 /**422 @brief Unregisters a slave from its master. Initiated by a slave.423 */424 void ArtificialController::unregisterSlave()425 {426 if (this->myMaster_)427 {428 std::vector<ArtificialController*>::iterator it = std::find(this->myMaster_->slaves_.begin(), this->myMaster_->slaves_.end(), this);429 if (it != this->myMaster_->slaves_.end())430 this->myMaster_->slaves_.erase(it);431 }432 433 this->myMaster_ = 0;434 this->state_ = FREE;435 }436 437 void ArtificialController::searchNewMaster()438 {439 440 if (!this->getControllableEntity())441 return;442 443 this->targetPosition_ = this->getControllableEntity()->getPosition();444 this->forgetTarget();445 int teamSize = 0;446 //go through all pawns447 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)448 {449 //same team?450 if (!ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))451 continue;452 453 //has it an ArtificialController?454 Controller* controller = 0;455 456 if (it->getController())457 controller = it->getController();458 else if (it->getXMLController())459 controller = it->getXMLController();460 461 if (!controller)462 continue;463 464 //is pawn oneself?465 if (orxonox_cast<ControllableEntity*>(*it) == this->getControllableEntity())466 continue;467 468 teamSize++;469 470 ArtificialController *newMaster = orxonox_cast<ArtificialController*>(controller);471 472 //is it a master?473 if (!newMaster || newMaster->state_ != MASTER)474 continue;475 476 float distance = (it->getPosition() - this->getControllableEntity()->getPosition()).length();477 478 // is pawn in range?479 if (distance < RADIUS_TO_SEARCH_FOR_MASTERS)480 {481 if(newMaster->slaves_.size() > this->maxFormationSize_) continue;482 483 for(std::vector<ArtificialController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)484 {485 (*itSlave)->myMaster_ = newMaster;486 newMaster->slaves_.push_back(*itSlave);487 }488 this->slaves_.clear();489 this->state_ = SLAVE;490 491 this->myMaster_ = newMaster;492 newMaster->slaves_.push_back(this);493 494 break;495 }496 }497 498 if (this->state_ != SLAVE && teamSize != 0)499 {500 this->state_ = MASTER;501 this->myMaster_ = 0;502 }503 }504 /**505 @brief Commands the slaves of a master into a formation. Sufficiently fast not to be called within tick. Initiated by a master.506 */507 508 void ArtificialController::commandSlaves()509 {510 if(this->state_ != MASTER) return;511 512 Quaternion orient = this->getControllableEntity()->getOrientation();513 Vector3 dest = this->getControllableEntity()->getPosition();514 515 // 1 slave: follow516 if (this->slaves_.size() == 1)517 {518 dest += 4*orient*WorldEntity::BACK;519 this->slaves_.front()->setTargetPosition(dest);520 }521 else522 // formation:523 {524 dest += 1.0f*orient*WorldEntity::BACK;525 Vector3 pos = Vector3::ZERO;526 bool left=true;527 int i = 1;528 529 for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)530 {531 pos = Vector3::ZERO;532 if (left)533 {534 pos+=dest+i*FORMATION_WIDTH*(orient*WorldEntity::LEFT);535 } else536 {537 pos+=dest+i*FORMATION_WIDTH*(orient*WorldEntity::RIGHT);538 i++;539 dest+=FORMATION_LENGTH*(orient*WorldEntity::BACK);540 }541 (*it)->setTargetOrientation(orient);542 (*it)->setTargetPosition(pos);543 left=!left;544 }545 }546 }547 548 /**549 @brief Sets a new master within the formation. Called by a master.550 */551 void ArtificialController::setNewMasterWithinFormation()552 {553 if(this->state_ != MASTER) return;554 555 if (!this->slaves_.empty())556 {557 ArtificialController *newMaster = this->slaves_.back();558 this->slaves_.pop_back();559 560 newMaster->state_ = MASTER;561 newMaster->slaves_ = this->slaves_;562 newMaster->myMaster_ = 0;563 564 for(std::vector<ArtificialController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)565 {566 (*it)->myMaster_ = newMaster;567 }568 }569 570 this->slaves_.clear();571 this->specificMasterAction_ = NONE;572 this->state_ = FREE;573 }574 575 /**576 @brief Frees all slaves form a master. Initiated by a master.577 */578 void ArtificialController::freeSlaves()579 {580 if(this->state_ != MASTER) return;581 582 for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)583 {584 (*it)->state_ = FREE;585 (*it)->myMaster_ = 0;586 }587 this->slaves_.clear();588 }589 590 /**591 @brief Master sets its slaves free for @ref FREEDOM_COUNT seconds.592 */593 void ArtificialController::forceFreeSlaves()594 {595 if(this->state_ != MASTER) return;596 597 for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)598 {599 (*it)->state_ = FREE;600 (*it)->forceFreedom();601 (*it)->targetPosition_ = this->targetPosition_;602 (*it)->bShooting_ = true;603 // (*it)->getControllableEntity()->fire(0);// fire once for fun604 }605 }606 607 void ArtificialController::loseMasterState()608 {609 this->freeSlaves();610 this->state_ = FREE;611 }612 613 614 void ArtificialController::forceFreedom()615 {616 this->freedomCount_ = FREEDOM_COUNT;617 }618 619 /**620 @brief Checks wether caller has been forced free, decrements time to stay forced free.621 @return true if forced free.622 */623 bool ArtificialController::forcedFree()624 {625 if(this->freedomCount_ > 0)626 {627 this->freedomCount_--;628 return true;629 } else return false;630 }631 632 /**633 @brief Used to continue a "specific master action" for a certain time and resuming normal behaviour after.634 */635 void ArtificialController::specificMasterActionHold()636 {637 if(this->state_ != MASTER) return;638 639 if (specificMasterActionHoldCount_ == 0)640 {641 this->specificMasterAction_ = NONE;642 this->searchNewTarget();643 }644 else specificMasterActionHoldCount_--;645 }646 647 /**648 @brief Master initializes a 180 degree turn. Leads to a "specific master action".649 */650 void ArtificialController::turn180Init()651 {652 if(this->state_ != MASTER) return;653 654 Quaternion orient = this->getControllableEntity()->getOrientation();655 656 this->setTargetPosition(this->getControllableEntity()->getPosition() + 1000.0f*orient*WorldEntity::BACK);657 658 this->specificMasterActionHoldCount_ = 4;659 660 this->specificMasterAction_ = TURN180;661 }662 663 /**664 @brief Execute the 180 degree turn. Called within tick.665 */666 void ArtificialController::turn180()667 {668 Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);669 670 this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);671 this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);672 673 this->getControllableEntity()->moveFrontBack(SPEED_MASTER);674 }675 676 /**677 @brief Master initializes a spin around its looking direction axis. Leads to a "specific master action".678 */679 void ArtificialController::spinInit()680 {681 if(this->state_ != MASTER) return;682 this->specificMasterAction_ = SPIN;683 this->specificMasterActionHoldCount_ = 10;684 }685 686 /**687 @brief Execute the spin. Called within tick.688 */689 void ArtificialController::spin()690 {691 this->moveToTargetPosition();692 this->getControllableEntity()->rotateRoll(0.8f);693 }694 695 /**696 @brief Master begins to follow a pawn. Is a "specific master action".697 @param pawn pawn to follow.698 @param always follows pawn forever if true (false if omitted).699 @param secondsToFollow seconds to follow the pawn if always is false. Will follow pawn 100 seconds if omitted (set in header).700 */701 void ArtificialController::followInit(Pawn* pawn, const bool always, const int secondsToFollow)702 {703 if (pawn == NULL || this->state_ != MASTER)704 return;705 this->specificMasterAction_ = FOLLOW;706 707 this->setTarget(pawn);708 if (!always)709 this->specificMasterActionHoldCount_ = secondsToFollow;710 else711 this->specificMasterActionHoldCount_ = INT_MAX; //for now...712 713 }714 715 716 /**717 @brief Master begins to follow a randomly chosen human player of the same team. Is a "specific master action".718 */719 void ArtificialController::followRandomHumanInit()720 {721 722 Pawn *humanPawn = NULL;723 NewHumanController *currentHumanController = NULL;724 725 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)726 {727 if (!it->getController())728 continue;729 730 currentHumanController = orxonox_cast<NewHumanController*>(it->getController());731 if(currentHumanController)732 {733 if (!ArtificialController::sameTeam(this->getControllableEntity(), *it, this->getGametype())) continue;734 humanPawn = *it;735 break;736 }737 }738 739 if((humanPawn != NULL))740 this->followInit(humanPawn);741 }742 743 /**744 @brief Master follows target with adjusted speed. Called within tick.745 */746 void ArtificialController::follow()747 {748 if (this->target_)749 this->moveToPosition(this->target_->getPosition());750 else751 this->specificMasterActionHoldCount_ = 0;752 /*753 if (!this->getControllableEntity())754 return;755 756 float distance = (this->target_->getPosition() - this->getControllableEntity()->getPosition()).length();757 758 Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->target_->getPosition());759 760 761 this->getControllableEntity()->rotateYaw(-0.8f * sgn(coord.x) * coord.x*coord.x);762 this->getControllableEntity()->rotatePitch(0.8f * sgn(coord.y) * coord.y*coord.y);763 764 float speedDiv = this->getControllableEntity()->getVelocity().squaredLength() - this->target_->getVelocity().squaredLength();765 766 orxout() << "~follow distance: " << distance << "SpeedCounter: " << this->speedCounter_ << "~speedDiv: " << speedDiv << endl;767 if (distance < 800)768 {769 if (distance < 200)770 {771 this->speedCounter_ -= 0.5f;772 if(this->speedCounter_ < 0) this->speedCounter_ = 0.0f;773 this->getControllableEntity()->moveFrontBack(speedCounter_);774 } else {775 if(speedDiv < 0)776 this->speedCounter_ += 0.01f;777 else778 this->speedCounter_ -= 0.05f;779 this->getControllableEntity()->moveFrontBack(speedCounter_);780 }781 782 } else {783 this->speedCounter_ += 0.05f;784 this->getControllableEntity()->moveFrontBack(speedCounter_ + distance/300.0f);785 }786 // if (this->getControllableEntity()->getVelocity().squaredLength() > 50.0f) this->speedCounter_ = 0;787 788 */789 }790 791 792 /**793 @brief Slave moving behaviour when master is following a pawn, gets redirected from moveToPosition(const Vector3& target)). Called within tick.794 */795 void ArtificialController::followForSlaves(const Vector3& target)796 {797 798 /*799 if (!this->getControllableEntity() && !this->myMaster_ && this->myMaster_->state_ != FOLLOW && !this->myMaster_->target_)800 return;801 802 float distance = (target - this->getControllableEntity()->getPosition()).length();803 804 Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);805 806 807 this->getControllableEntity()->rotateYaw(-0.8f * sgn(coord.x) * coord.x*coord.x);808 this->getControllableEntity()->rotatePitch(0.8f * sgn(coord.y) * coord.y*coord.y);809 810 811 float speedDiv = this->getControllableEntity()->getVelocity().squaredLength() - this->myMaster_->target_->getVelocity().squaredLength();812 813 814 if (distance < 800)815 {816 if (distance < 200)817 {818 this->speedCounter_ -= 5.0f;819 if(this->speedCounter_ < 0) this->speedCounter_ = 0.0f;820 this->getControllableEntity()->moveFrontBack(speedCounter_);821 } else {822 if(speedDiv < 0)823 this->speedCounter_ += 0.01f;824 else825 this->speedCounter_ -= 0.05f;826 this->getControllableEntity()->moveFrontBack(speedCounter_);827 }828 829 } else {830 this->speedCounter_ += 0.05f;831 this->getControllableEntity()->moveFrontBack(speedCounter_ + distance/300.0f);832 }833 // if (this->getControllableEntity()->getVelocity().squaredLength() > 50.0f) this->speedCounter_ = 0;834 */835 }836 837 838 void ArtificialController::setTargetPosition(const Vector3& target)839 {840 this->targetPosition_ = target;841 this->bHasTargetPosition_ = true;842 }843 844 void ArtificialController::searchRandomTargetPosition()845 {846 this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));847 this->bHasTargetPosition_ = true;848 }849 850 void ArtificialController::setTargetOrientation(const Quaternion& orient)851 {852 this->targetOrientation_=orient;853 this->bHasTargetOrientation_=true;854 }855 856 void ArtificialController::setTargetOrientation(Pawn* target)857 {858 if (target)859 setTargetOrientation(target->getOrientation());860 }861 862 void ArtificialController::setTarget(Pawn* target)863 {864 this->target_ = target;865 866 if (target)867 this->targetPosition_ = target->getPosition();868 }869 870 void ArtificialController::searchNewTarget()871 {872 if (!this->getControllableEntity())873 return;874 875 this->targetPosition_ = this->getControllableEntity()->getPosition();876 this->forgetTarget();877 878 for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)879 {880 if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))881 continue;882 883 /* So AI won't choose invisible Spaceships as target */884 if (!it->getRadarVisibility())885 continue;886 887 if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())888 {889 float speed = this->getControllableEntity()->getVelocity().length();890 Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();891 Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();892 if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / math::twoPi)893 < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / math::twoPi) + rnd(-250, 250))894 {895 this->target_ = (*it);896 this->targetPosition_ = it->getPosition();897 }898 }899 }900 }901 902 void ArtificialController::forgetTarget()903 {904 this->target_ = 0;905 this->bShooting_ = false;906 }907 68 908 69 void ArtificialController::aimAtTarget() … … 945 106 this->targetDied(); 946 107 } 947 948 void ArtificialController::targetDied() 949 { 950 this->forgetTarget(); 951 this->searchRandomTargetPosition(); 952 } 953 954 bool ArtificialController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype) 955 { 956 if (entity1 == entity2) 957 return true; 958 959 int team1 = -1; 960 int team2 = -1; 961 962 Controller* controller = 0; 963 if (entity1->getController()) 964 controller = entity1->getController(); 965 else 966 controller = entity1->getXMLController(); 967 if (controller) 968 { 969 ArtificialController* ac = orxonox_cast<ArtificialController*>(controller); 970 if (ac) 971 team1 = ac->getTeam(); 972 } 973 974 if (entity2->getController()) 975 controller = entity2->getController(); 976 else 977 controller = entity2->getXMLController(); 978 if (controller) 979 { 980 ArtificialController* ac = orxonox_cast<ArtificialController*>(controller); 981 if (ac) 982 team2 = ac->getTeam(); 983 } 984 985 TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype); 986 if (tdm) 987 { 988 if (entity1->getPlayer()) 989 team1 = tdm->getTeam(entity1->getPlayer()); 990 991 if (entity2->getPlayer()) 992 team2 = tdm->getTeam(entity2->getPlayer()); 993 } 994 995 TeamBaseMatchBase* base = 0; 996 base = orxonox_cast<TeamBaseMatchBase*>(entity1); 997 if (base) 998 { 999 switch (base->getState()) 1000 { 1001 case BaseState::ControlTeam1: 1002 team1 = 0; 1003 break; 1004 case BaseState::ControlTeam2: 1005 team1 = 1; 1006 break; 1007 case BaseState::Uncontrolled: 1008 default: 1009 team1 = -1; 1010 } 1011 } 1012 base = orxonox_cast<TeamBaseMatchBase*>(entity2); 1013 if (base) 1014 { 1015 switch (base->getState()) 1016 { 1017 case BaseState::ControlTeam1: 1018 team2 = 0; 1019 break; 1020 case BaseState::ControlTeam2: 1021 team2 = 1; 1022 break; 1023 case BaseState::Uncontrolled: 1024 default: 1025 team2 = -1; 1026 } 1027 } 1028 1029 DroneController* droneController = 0; 1030 droneController = orxonox_cast<DroneController*>(entity1->getController()); 1031 if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2) 1032 return true; 1033 droneController = orxonox_cast<DroneController*>(entity2->getController()); 1034 if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1) 1035 return true; 1036 DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController()); 1037 DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController()); 1038 if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner()) 1039 return true; 1040 1041 Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype); 1042 if (dynamic) 1043 { 1044 if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;} 1045 1046 if (entity1->getPlayer()) 1047 team1 = dynamic->getParty(entity1->getPlayer()); 1048 1049 if (entity2->getPlayer()) 1050 team2 = dynamic->getParty(entity2->getPlayer()); 1051 1052 if (team1 ==-1 ||team2 ==-1 ) {return false;} 1053 else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;} 1054 else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;} 1055 else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;} 1056 else return true; 1057 } 1058 1059 return (team1 == team2 && team1 != -1); 1060 } 108 1061 109 } -
code/branches/formation/src/orxonox/controllers/ArtificialController.h
r8908 r8939 37 37 #include "Controller.h" 38 38 #include "controllers/NewHumanController.h" 39 #include "controllers/Masterable.h" 39 40 40 41 namespace orxonox 41 42 { 42 class _OrxonoxExport ArtificialController : public Controller43 class _OrxonoxExport ArtificialController : public Masterable 43 44 { 44 45 public: … … 46 47 virtual ~ArtificialController(); 47 48 48 virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);49 50 49 void abandonTarget(Pawn* target); 51 50 52 inline void setTeam(int team)53 { this->team_ = team; }54 inline int getTeam() const55 { return this->team_; }56 57 inline void setFormationFlight(bool formation)58 { this->formationFlight_ = formation; }59 inline bool getFormationFlight() const60 { return this->formationFlight_; }61 62 inline void setFormationSize(int size)63 { this->maxFormationSize_ = size; }64 inline int getFormationSize() const65 { return this->maxFormationSize_; }66 67 inline void setPassive(bool passive)68 { this->passive_ = passive; }69 inline bool getPassive() const70 { return this->passive_; }71 72 51 virtual void changedControllableEntity(); 73 74 static void formationflight(const bool form); 75 static void masteraction(const int action); 76 static void followme(); 77 static void passivebehaviour(const bool passive); 78 static void formationsize(const int size); 52 79 53 80 54 protected: 81 82 int team_; 83 bool formationFlight_; 84 bool passive_; 85 unsigned int maxFormationSize_; 86 int freedomCount_; 87 enum State {SLAVE, MASTER, FREE}; 88 State state_; 89 std::vector<ArtificialController*> slaves_; 90 ArtificialController *myMaster_; 91 enum SpecificMasterAction {NONE, HOLD, SPIN, TURN180, FOLLOW}; 92 SpecificMasterAction specificMasterAction_; 93 int specificMasterActionHoldCount_; 94 float speedCounter_; //for speed adjustment when following 95 96 void moveToPosition(const Vector3& target); 97 void moveToTargetPosition(); 98 void copyOrientation(const Quaternion& orient); 99 void copyTargetOrientation(); 100 101 virtual void positionReached() {} 102 103 void removeFromFormation(); 104 void unregisterSlave(); 105 void searchNewMaster(); 106 void commandSlaves(); 107 void setNewMasterWithinFormation(); 108 109 void freeSlaves(); 110 void forceFreeSlaves(); 111 void loseMasterState(); 112 void forceFreedom(); 113 bool forcedFree(); 114 115 void specificMasterActionHold(); 116 void turn180Init(); 117 void turn180(); 118 void spinInit(); 119 void spin(); 120 void followInit(Pawn* pawn, const bool always = false, const int secondsToFollow = 100); 121 void followRandomHumanInit(); 122 void follow(); 123 void followForSlaves(const Vector3& target); 124 125 void setTargetPosition(const Vector3& target); 126 void searchRandomTargetPosition(); 127 128 void setTargetOrientation(const Quaternion& orient); 129 void setTargetOrientation(Pawn* target); 130 131 void setTarget(Pawn* target); 132 void searchNewTarget(); 133 void forgetTarget(); 55 134 56 void aimAtTarget(); 135 57 136 58 bool isCloseAtTarget(float distance) const; 137 59 bool isLookingAtTarget(float angle) const; 138 139 void targetDied();140 141 static bool sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype); // hack142 143 bool bHasTargetPosition_;144 Vector3 targetPosition_;145 146 bool bHasTargetOrientation_;147 Quaternion targetOrientation_;148 149 WeakPtr<Pawn> target_;150 bool bShooting_;151 60 152 61 private: -
code/branches/formation/src/orxonox/controllers/CMakeLists.txt
r7163 r8939 9 9 WaypointPatrolController.cc 10 10 DroneController.cc 11 Masterable.cc 11 12 ) -
code/branches/formation/src/orxonox/controllers/HumanController.cc
r8858 r8939 50 50 SetConsoleCommand("HumanController", "rotatePitch", &HumanController::rotatePitch ).addShortcut().setAsInputCommand(); 51 51 SetConsoleCommand("HumanController", "rotateRoll", &HumanController::rotateRoll ).addShortcut().setAsInputCommand(); 52 SetConsoleCommand("HumanController", "toggleFormationFlight", &HumanController::toggleFormationFlight).addShortcut().setAsInputCommand(); 52 53 SetConsoleCommand("HumanController", __CC_fire_name, &HumanController::fire ).addShortcut().keybindMode(KeybindMode::OnHold); 53 54 SetConsoleCommand("HumanController", "reload", &HumanController::reload ).addShortcut(); … … 69 70 /*static*/ const float HumanController::BOOSTING_TIME = 0.1f; 70 71 71 HumanController::HumanController(BaseObject* creator) : Controller(creator)72 HumanController::HumanController(BaseObject* creator) : Masterable(creator) 72 73 { 73 74 RegisterObject(HumanController); … … 80 81 this->boostingTimeout_.setTimer(HumanController::BOOSTING_TIME, false, createExecutor(createFunctor(&HumanController::terminateBoosting, this))); 81 82 this->boostingTimeout_.stopTimer(); 83 this->state_=MASTER; 82 84 } 83 85 … … 85 87 { 86 88 HumanController::localController_s = 0; 89 if (this->state_==MASTER) 90 freeSlaves(); 87 91 } 88 92 … … 94 98 if (!camera) 95 99 orxout(internal_warning) << "HumanController, Warning: Using a ControllableEntity without Camera" << endl; 100 } 101 102 // commandslaves when Master of a formation 103 if (this->state_==MASTER) 104 { 105 this->commandSlaves(); 96 106 } 97 107 } … … 262 272 } 263 273 274 void HumanController::toggleFormationFlight() 275 { 276 if (HumanController::localController_s) 277 { 278 if (HumanController::localController_s->state_==MASTER) 279 { 280 HumanController::localController_s->freeSlaves(); 281 HumanController::localController_s->state_=FREE; 282 } else //SLAVE or FREE 283 { 284 HumanController::localController_s->takeLeadOfFormation(); 285 //HumanController::localController_s->state_=MASTER; 286 } 287 } 288 289 } 290 264 291 void HumanController::addBots(unsigned int amount) 265 292 { -
code/branches/formation/src/orxonox/controllers/HumanController.h
r8706 r8939 34 34 #include "tools/Timer.h" 35 35 #include "tools/interfaces/Tickable.h" 36 #include " Controller.h"36 #include "Masterable.h" 37 37 38 38 // tolua_begin … … 41 41 class _OrxonoxExport HumanController 42 42 // tolua_end 43 : public Controller, public Tickable43 : public Masterable, public Tickable 44 44 { // tolua_export 45 45 public: … … 85 85 static void myposition(); 86 86 87 static void toggleFormationFlight(); 88 87 89 static void addBots(unsigned int amount); 88 90 static void killBots(unsigned int amount = 0);
Note: See TracChangeset
for help on using the changeset viewer.