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