Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 12, 2011, 7:50:43 PM (13 years ago)
Author:
jo
Message:

Ai and tutorial improvements merged back to the trunk. AI features: all weapons are used, the ai-firestrength is configurable, bots are able to collect pickups . I've set the tutorial level as default level.

Location:
code/trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/orxonox/controllers/AIController.cc

    r8729 r8891  
    6565                if (this->freedomCount_ == 1)
    6666                {
    67                 this->state_ = SLAVE;
    68                 this->freedomCount_ = 0;
     67                    this->state_ = SLAVE;
     68                    this->freedomCount_ = 0;
    6969                }
    7070
     
    7676            // search enemy
    7777            random = rnd(maxrand);
    78             if (random < 15 && (!this->target_))
     78            if (random < (15 + botlevel_* 20) && (!this->target_))
    7979                this->searchNewTarget();
    8080
    8181            // forget enemy
    8282            random = rnd(maxrand);
    83             if (random < 5 && (this->target_))
     83            if (random < ((1-botlevel_)*6) && (this->target_))
    8484                this->forgetTarget();
    8585
    8686            // next enemy
    8787            random = rnd(maxrand);
    88             if (random < 10 && (this->target_))
     88            if (random < (botlevel_*20) && (this->target_))
    8989                this->searchNewTarget();
    9090
     
    106106            // shoot
    107107            random = rnd(maxrand);
    108             if (!(this->passive_) && random < 75 && (this->target_ && !this->bShooting_))
     108            if (!(this->passive_) && random < (75 + botlevel_*25) && (this->target_ && !this->bShooting_))
    109109                this->bShooting_ = true;
    110110
    111111            // stop shooting
    112112            random = rnd(maxrand);
    113             if (random < 25 && (this->bShooting_))
     113            if (random < ((1 - botlevel_)*25) && (this->bShooting_))
    114114                this->bShooting_ = false;
     115
     116            // boost
     117            random = rnd(maxrand);
     118            if (random < botlevel_*100 )
     119                this->boostControl();
     120
     121            // update Checkpoints
     122            /*random = rnd(maxrand);
     123            if (this->defaultWaypoint_ && random > (maxrand-10))
     124                this->manageWaypoints();
     125            else //if(random > maxrand-10) //CHECK USABILITY!!*/
     126            if (this->waypoints_.size() == 0 )
     127                this->manageWaypoints();
    115128
    116129        }
     
    159172                // search enemy
    160173                random = rnd(maxrand);
    161                 if (random < 15 && (!this->target_))
     174                if (random < (botlevel_)*25 && (!this->target_))
    162175                    this->searchNewTarget();
    163176
    164177                // forget enemy
    165178                random = rnd(maxrand);
    166                 if (random < 5 && (this->target_))
     179                if (random < (1-botlevel_)*6 && (this->target_))
    167180                    this->forgetTarget();
    168181
     
    185198                // shoot
    186199                random = rnd(maxrand);
    187                 if (!(this->passive_) && random < 9 && (this->target_ && !this->bShooting_))
    188                 {
    189                 this->bShooting_ = true;
    190                 this->forceFreeSlaves();
     200                if (!(this->passive_) && random < 25*(botlevel_)+1 && (this->target_ && !this->bShooting_))
     201                {
     202                    this->bShooting_ = true;
     203                    this->forceFreeSlaves();
    191204                }
    192205
    193206                // stop shooting
    194207                random = rnd(maxrand);
    195                 if (random < 25 && (this->bShooting_))
     208                if (random < ( (1- botlevel_)*25 ) && (this->bShooting_))
    196209                    this->bShooting_ = false;
    197210
     211                // boost
     212                random = rnd(maxrand);
     213                if (random < botlevel_*100 )
     214                    this->boostControl();
     215
     216                // update Checkpoints
     217                /*random = rnd(maxrand);
     218                if (this->defaultWaypoint_ && random > (maxrand-10))
     219                    this->manageWaypoints();
     220                else //if(random > maxrand-10) //CHECK USABILITY!!*/
     221                if (this->waypoints_.size() == 0 )
     222                    this->manageWaypoints();
    198223            }
    199224        }
     
    206231            return;
    207232
    208         if (this->state_ == MASTER)
     233        float random;
     234        float maxrand = 100.0f / ACTION_INTERVAL;
     235        ControllableEntity* controllable = this->getControllableEntity();
     236
     237        if (controllable && this->mode_ == DEFAULT)// bot is ready to move to a target
    209238        {
    210             if (this->specificMasterAction_ ==  NONE)
     239            if (this->waypoints_.size() > 0 ) //Waypoint functionality.
     240            {
     241                WorldEntity* wPoint = this->waypoints_[this->waypoints_.size()-1];
     242                if(wPoint)
     243                {
     244                    this->moveToPosition(wPoint->getWorldPosition()); //BUG ?? sometime wPoint->getWorldPosition() causes crash
     245                    if (wPoint->getWorldPosition().squaredDistance(controllable->getPosition()) <= this->squaredaccuracy_)
     246                        this->waypoints_.pop_back(); // if goal is reached, remove it from the list
     247                }
     248                else
     249                    this->waypoints_.pop_back(); // remove invalid waypoints
     250
     251            }
     252            else if(this->defaultWaypoint_ && ((this->defaultWaypoint_->getPosition()-controllable->getPosition()).length()  > 200.0f))
     253            {
     254                this->moveToPosition(this->defaultWaypoint_->getPosition()); // stay within a certain range of the defaultWaypoint_
     255                random = rnd(maxrand);
     256            }
     257        }
     258        if(this->mode_ == DEFAULT)
     259            {
     260            if (this->state_ == MASTER)
     261            {
     262                if (this->specificMasterAction_ ==  NONE)
     263                {
     264                    if (this->target_)
     265                    {
     266                        if (!this->target_->getRadarVisibility()) /* So AI won't shoot invisible Spaceships */
     267                            this->forgetTarget();
     268                        else
     269                        {
     270                            this->aimAtTarget();
     271                            random = rnd(maxrand);
     272                            if(this->botlevel_*100 > random && !this->isCloseAtTarget(20))
     273                                this->follow();  //If a bot is shooting a player, it shouldn't let him go away easily.
     274                        }
     275                    }
     276
     277                    if (this->bHasTargetPosition_)
     278                        this->moveToTargetPosition();
     279
     280                    this->doFire();
     281                }
     282
     283                if (this->specificMasterAction_  == TURN180)
     284                    this->turn180();
     285
     286                if (this->specificMasterAction_ == SPIN)
     287                    this->spin();
     288                if (this->specificMasterAction_ == FOLLOW)
     289                    this->follow();
     290            }
     291
     292            if (this->state_ == SLAVE)
     293            {
     294                if (this->bHasTargetPosition_)
     295                    this->moveToTargetPosition();
     296            }
     297
     298            if (this->state_ == FREE)
    211299            {
    212300                if (this->target_)
     
    214302                    if (!this->target_->getRadarVisibility()) /* So AI won't shoot invisible Spaceships */
    215303                        this->forgetTarget();
    216                     else this->aimAtTarget();
     304                    else
     305                    {
     306                        this->aimAtTarget();
     307                        random = rnd(maxrand);
     308
     309                        if(this->botlevel_*100 > random && !this->isCloseAtTarget(20))
     310                            this->follow();//If a bot is shooting a player, it shouldn't let him go away easily.
     311                     }
    217312                }
    218313
     
    220315                    this->moveToTargetPosition();
    221316
    222                 if (this->getControllableEntity() && this->bShooting_ && this->isCloseAtTarget(1000) && this->isLookingAtTarget(math::pi / 20.0f))
    223                     this->getControllableEntity()->fire(0);
    224             }
    225 
    226             if (this->specificMasterAction_  == TURN180)
    227                     this->turn180();
    228 
    229             if (this->specificMasterAction_ == SPIN)
    230                     this->spin();
    231             if (this->specificMasterAction_ == FOLLOW)
     317                this->doFire();
     318            }
     319        }//END_OF DEFAULT MODE
     320        else if (this->mode_ == ROCKET)//Rockets do not belong to a group of bots -> bot states are not relevant.
     321        {   //Vector-implementation: mode_.back() == ROCKET;
     322            if(controllable)
     323            {
     324                if(controllable->getRocket())//Check wether the bot is controlling the rocket and if the timeout is over.
     325                {
    232326                    this->follow();
    233         }
    234 
    235         if (this->state_ == SLAVE)
    236         {
    237 
    238             if (this->bHasTargetPosition_)
    239                 this->moveToTargetPosition();
    240 
    241         }
    242 
    243          if (this->state_ == FREE)
    244         {
    245             if (this->target_)
    246             {
    247                 if (!this->target_->getRadarVisibility()) /* So AI won't shoot invisible Spaceships */
    248                     this->forgetTarget();
    249                 else this->aimAtTarget();
    250             }
    251 
    252             if (this->bHasTargetPosition_)
    253                 this->moveToTargetPosition();
    254 
    255             if (this->getControllableEntity() && this->bShooting_ && this->isCloseAtTarget(1000) && this->isLookingAtTarget(math::pi / 20.0f))
    256                 this->getControllableEntity()->fire(0);
    257         }
     327                    this->timeout_ -= dt;
     328                    if((timeout_< 0)||(!target_))//Check if the timeout is over or target died.
     329                    {
     330                       controllable->fire(0);//kill the rocket
     331                       this->setPreviousMode();//get out of rocket mode
     332                    }
     333                }
     334                else
     335                    this->setPreviousMode();//no rocket entity -> get out of rocket mode
     336            }
     337            else
     338                this->setPreviousMode();//If bot dies -> getControllableEntity == NULL -> get out of ROCKET mode
     339        }//END_OF ROCKET MODE
    258340
    259341        SUPER(AIController, tick, dt);
  • code/trunk/src/orxonox/controllers/ArtificialController.cc

    r8858 r8891  
    3939#include "worldentities/pawns/Pawn.h"
    4040#include "worldentities/pawns/TeamBaseMatchBase.h"
     41#include "worldentities/pawns/SpaceShip.h"
    4142#include "gametypes/TeamDeathmatch.h"
    4243#include "gametypes/Dynamicmatch.h"
     
    4445#include "controllers/NewHumanController.h"
    4546#include "controllers/DroneController.h"
     47#include "weaponsystem/WeaponMode.h"
     48#include "weaponsystem/WeaponPack.h"
     49#include "weaponsystem/Weapon.h"
     50#include "weaponsystem/WeaponSlot.h"
     51#include "weaponsystem/WeaponSlot.h"
    4652
    4753namespace orxonox
     
    5258    SetConsoleCommand("ArtificialController", "passivebehaviour", &ArtificialController::passivebehaviour);
    5359    SetConsoleCommand("ArtificialController", "formationsize",    &ArtificialController::formationsize);
     60    SetConsoleCommand("ArtificialController", "setbotlevel",      &ArtificialController::setAllBotLevel);
    5461
    5562    static const unsigned int STANDARD_MAX_FORMATION_SIZE = 7;
     
    8491
    8592        this->target_.setCallback(createFunctor(&ArtificialController::targetDied, this));
     93        this->bSetupWorked = false;
     94        this->botlevel_ = 0.5f;
     95        this->mode_ = DEFAULT;////Vector-implementation: mode_.push_back(DEFAULT);
     96        this->timeout_ = 0;
     97        this->currentWaypoint_ = 0;
     98        this->setAccuracy(5);
     99        this->defaultWaypoint_ = NULL;
    86100    }
    87101
     
    89103    {
    90104        if (this->isInitialized())
    91         {
     105        {//Vector-implementation: mode_.erase(mode_.begin(),mode_.end());
     106            this->waypoints_.clear();
    92107            this->removeFromFormation();
    93 
     108            this->weaponModes_.clear();
    94109            for (ObjectList<ArtificialController>::iterator it = ObjectList<ArtificialController>::begin(); it; ++it)
    95110            {
     
    305320        if (!this->getControllableEntity())
    306321            this->removeFromFormation();
     322        this->bSetupWorked = false;        // reset weapon information
     323        this->setupWeapons();
    307324    }
    308325
     
    387404        }
    388405    }
     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
    389431
    390432    void ArtificialController::moveToTargetPosition()
     
    915957    bool ArtificialController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
    916958    {
     959        if(!entity1 || !entity2)
     960            return true;
    917961        if (entity1 == entity2)
    918962            return true;
     
    10201064        return (team1 == team2 && team1 != -1);
    10211065    }
     1066
     1067    /**
     1068        @brief DoFire is called when a bot should shoot and decides which weapon is used and whether the bot shoots at all.
     1069    */
     1070    void ArtificialController::doFire()
     1071    {
     1072        if(!this->bSetupWorked)//setup: find out which weapons are active ! hard coded: laser is "0", lens flare is "1", ...
     1073        {
     1074            this->setupWeapons();
     1075        }
     1076        else if(this->getControllableEntity() && weaponModes_.size()&&this->bShooting_ && this->isCloseAtTarget((1 + 2*botlevel_)*1000) && this->isLookingAtTarget(math::pi / 20.0f))
     1077        {
     1078            int firemode;
     1079            float random = rnd(1);//
     1080            if (this->isCloseAtTarget(130) && (firemode = getFiremode("LightningGun")) > -1 )
     1081            {//LENSFLARE: short range weapon
     1082                this->getControllableEntity()->fire(firemode); //ai uses lens flare if they're close enough to the target
     1083            }
     1084            else if( this->isCloseAtTarget(400) && (random < this->botlevel_) && (firemode = getFiremode("RocketFire")) > -1 )
     1085            {//ROCKET: mid range weapon
     1086                this->mode_ = ROCKET; //Vector-implementation: mode_.push_back(ROCKET);
     1087                this->getControllableEntity()->fire(firemode); //launch rocket
     1088                if(this->getControllableEntity() && this->target_) //after fire(3) is called, getControllableEntity() refers to the rocket!
     1089                {
     1090                    float speed = this->getControllableEntity()->getVelocity().length() - target_->getVelocity().length();
     1091                    if(!speed) speed = 0.1f;
     1092                    float distance = target_->getPosition().length() - this->getControllableEntity()->getPosition().length();
     1093                    this->timeout_= distance/speed*sgn(speed*distance) + 1.8f; //predicted time of target hit (+ tolerance)
     1094                }
     1095                else
     1096                    this->timeout_ = 4.0f; //TODO: find better default value
     1097            }
     1098            else if ((firemode = getFiremode("HsW01")) > -1 ) //LASER: default weapon
     1099                this->getControllableEntity()->fire(firemode);
     1100        }
     1101    }
     1102
     1103    /**
     1104        @brief Information gathering: Which weapons are ready to use?
     1105    */
     1106    void ArtificialController::setupWeapons() //TODO: Make this function generic!! (at the moment is is based on conventions)
     1107    {
     1108        this->bSetupWorked = false;
     1109        if(this->getControllableEntity())
     1110        {
     1111            Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
     1112            if(pawn)
     1113            {
     1114                this->weaponModes_.clear(); // reset previous weapon information
     1115                WeaponSlot* wSlot = 0;
     1116                for(int l=0; (wSlot = pawn->getWeaponSlot(l)) ; l++)
     1117                {
     1118                    WeaponMode* wMode = 0;
     1119                    for(int i=0; (wMode = wSlot->getWeapon()->getWeaponmode(i)) ; i++)
     1120                    {
     1121                        std::string wName = wMode->getIdentifier()->getName();
     1122                        if(this->getFiremode(wName) == -1) //only add a weapon, if it is "new"
     1123                            weaponModes_[wName] = wMode->getMode();
     1124                    }
     1125                }
     1126                if(weaponModes_.size())//at least one weapon detected
     1127                    this->bSetupWorked = true;
     1128            }//pawn->weaponSystem_->getMunition(SubclassIdentifier< Munition > *identifier)->getNumMunition (WeaponMode *user);
     1129        }
     1130    }
     1131
     1132
     1133    void ArtificialController::setBotLevel(float level)
     1134    {
     1135        if (level < 0.0f)
     1136            this->botlevel_ = 0.0f;
     1137        else if (level > 1.0f)
     1138            this->botlevel_ = 1.0f;
     1139        else
     1140            this->botlevel_ = level;
     1141    }
     1142
     1143    void ArtificialController::setAllBotLevel(float level)
     1144    {
     1145        for (ObjectList<ArtificialController>::iterator it = ObjectList<ArtificialController>::begin(); it != ObjectList<ArtificialController>::end(); ++it)
     1146            it->setBotLevel(level);
     1147    }
     1148
     1149    void ArtificialController::setPreviousMode()
     1150    {
     1151        this->mode_ = DEFAULT; //Vector-implementation: mode_.pop_back();
     1152    }
     1153
     1154    /**
     1155        @brief Manages boost. Switches between boost usage and boost safe mode.
     1156    */
     1157    void ArtificialController::boostControl()
     1158    {
     1159        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
     1160        if(ship == NULL) return;
     1161        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower() ) //upper limit ->boost
     1162            this->getControllableEntity()->boost(true);
     1163        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
     1164            this->getControllableEntity()->boost(false);
     1165    }
     1166
     1167    int ArtificialController::getFiremode(std::string name)
     1168    {
     1169        for (std::map< std::string, int >::iterator it = this->weaponModes_.begin(); it != this->weaponModes_.end(); ++it)
     1170        {
     1171            if (it->first == name)
     1172                return it->second;
     1173        }
     1174        return -1;
     1175    }
     1176
     1177    void ArtificialController::addWaypoint(WorldEntity* waypoint)
     1178    {
     1179        this->waypoints_.push_back(waypoint);
     1180    }
     1181
     1182    WorldEntity* ArtificialController::getWaypoint(unsigned int index) const
     1183    {
     1184        if (index < this->waypoints_.size())
     1185            return this->waypoints_[index];
     1186        else
     1187            return 0;
     1188    }
     1189
     1190    /**
     1191        @brief Adds first waypoint of type name to the waypoint stack, which is within the searchDistance
     1192        @param name object-name of a point of interest (e.g. "PickupSpawner", "ForceField")
     1193    */
     1194    void ArtificialController::updatePointsOfInterest(std::string name, float searchDistance)
     1195    {
     1196        WorldEntity* waypoint = NULL;
     1197        for (ObjectList<WorldEntity>::iterator it = ObjectList<WorldEntity>::begin(); it != ObjectList<WorldEntity>::end(); ++it)
     1198        {
     1199            if((*it)->getIdentifier() == ClassByString(name))
     1200            {
     1201                ControllableEntity* controllable = this->getControllableEntity();
     1202                if(!controllable) continue;
     1203                float actualDistance = ( (*it)->getPosition() - controllable->getPosition() ).length();
     1204                if(actualDistance > searchDistance || actualDistance < 5.0f) continue;
     1205                    // TODO: PickupSpawner: adjust waypoint accuracy to PickupSpawner's triggerdistance
     1206                    // TODO: ForceField: analyze is angle between forcefield boost and own flying direction is acceptable
     1207                else
     1208                {
     1209                    waypoint = *it;
     1210                    break;
     1211                }
     1212            }
     1213        }
     1214        if(waypoint)
     1215            this->waypoints_.push_back(waypoint);
     1216    }
     1217
     1218    /**
     1219        @brief Adds point of interest depending on context. Further Possibilites: "ForceField", "PortalEndPoint", "MovableEntity", "Dock"
     1220    */
     1221    void ArtificialController::manageWaypoints()
     1222    {
     1223        if(!defaultWaypoint_)
     1224            this->updatePointsOfInterest("PickupSpawner", 200.0f); // long search radius if there is no default goal
     1225        else
     1226            this->updatePointsOfInterest("PickupSpawner", 20.0f); // take pickup en passant if there is a default waypoint
     1227    }
     1228
    10221229}
  • code/trunk/src/orxonox/controllers/ArtificialController.h

    r8706 r8891  
    3232#include "OrxonoxPrereqs.h"
    3333
    34 #include <vector>
     34#include <map>
    3535
    3636#include "util/Math.h"
    3737#include "Controller.h"
    3838#include "controllers/NewHumanController.h"
     39#include "weaponsystem/WeaponSystem.h"
    3940
    4041namespace orxonox
     
    7879            static void formationsize(const int size);
    7980
     81            virtual void doFire();
     82            void setBotLevel(float level=1.0f);
     83            inline float getBotLevel() const
     84                { return this->botlevel_; }
     85            static void setAllBotLevel(float level);
     86            //WAYPOINT FUNCTIONS
     87            void addWaypoint(WorldEntity* waypoint);
     88            WorldEntity* getWaypoint(unsigned int index) const;
     89
     90            inline void setAccuracy(float accuracy)
     91                { this->squaredaccuracy_ = accuracy*accuracy; }
     92            inline float getAccuracy() const
     93                { return sqrt(this->squaredaccuracy_); }
     94            void updatePointsOfInterest(std::string name, float distance);
     95            void manageWaypoints();
     96
    8097        protected:
    8198
     
    96113            void moveToPosition(const Vector3& target);
    97114            void moveToTargetPosition();
     115            void absoluteMoveToPosition(const Vector3& target);
    98116
    99117            virtual void positionReached() {}
     
    135153
    136154            static bool sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype); // hack
     155            void boostControl(); //<! Sets and resets the boost parameter of the spaceship. Bots alternate between boosting and saving boost.
    137156
    138157            bool bHasTargetPosition_;
     
    141160            bool bShooting_;
    142161
    143         private:
     162            float botlevel_; //<! Makes the level of a bot configurable.
     163            enum Mode {DEFAULT, ROCKET, DEFENCE, MOVING};//TODO; implement DEFENCE, MOVING modes
     164            Mode mode_; //TODO: replace single value with stack-like implementation: std::vector<Mode> mode_;
     165            void setPreviousMode();
     166
     167            //WEAPONSYSTEM DATA
     168            std::map<std::string, int> weaponModes_; //<! Links each "weapon" to it's weaponmode- managed by setupWeapons()
     169            //std::vector<int> projectiles_; //<! Displays amount of projectiles of each weapon. - managed by setupWeapons()
     170            float timeout_; //<! Timeout for rocket usage. (If a rocket misses, a bot should stop using it.)
     171            void setupWeapons(); //<! Defines which weapons are available for a bot. Is recalled whenever a bot was killed.
     172            bool bSetupWorked; //<! If false, setupWeapons() is called.
     173            int getFiremode(std::string name);
     174
     175            //WAYPOINT DATA
     176            std::vector<WeakPtr<WorldEntity> > waypoints_;
     177            size_t currentWaypoint_;
     178            float squaredaccuracy_;
     179            WorldEntity* defaultWaypoint_;
    144180    };
    145181}
  • code/trunk/src/orxonox/controllers/DroneController.cc

    r8729 r8891  
    5252        this->drone_ = 0;
    5353        this->isShooting_ = false;
     54        this->setAccuracy(10);
    5455
    5556        this->actionTimer_.setTimer(ACTION_INTERVAL, true, createExecutor(createFunctor(&DroneController::action, this)));
     
    9293        The duration of the tick.
    9394    */
     95    /* PORTALS workaround:
     96    if the owner uses a portal -> distance between owner and drone is huge -> is detected by drone
     97    -> drone searches for portal -> drone adds portal as waypoint -> drone flies towards portal //ignores owner
     98    -> if the drone used a portal, then the distance to the owner is small -> remove waypoint // back to normal mode
     99
     100    */
    94101    void DroneController::tick(float dt)
    95102    {
    96103        if (this->getDrone() && this->getOwner())
    97104        {
    98             if (this->target_)
     105            if (this->waypoints_.size() > 0 ) //Waypoint functionality: Drone should follow it's master through portals
     106            {// Idea: after using the the portal, the master is far away.
     107                WorldEntity* wPoint = this->waypoints_[this->waypoints_.size()-1];
     108                if(wPoint)
     109                {
     110                    float distanceToOwnerSquared = (this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength();
     111                    this->absoluteMoveToPosition(wPoint->getWorldPosition()); //simplified function - needs WORKAROUND
     112                    if (distanceToOwnerSquared <= 90000.0f) //WORKAROUND: if the Drone is again near its owner, the portal has been used correctly.
     113                    {
     114                        this->waypoints_.pop_back(); // if goal is reached, remove it from the list
     115                        this->positionReached(); //needed??
     116                    }
     117
     118                }
     119                else
     120                    this->waypoints_.pop_back(); // remove invalid waypoints
     121            }
     122            else
    99123            {
    100                 float distanceToTargetSquared = (this->getDrone()->getWorldPosition() - this->target_->getWorldPosition()).squaredLength();
    101                 if (distanceToTargetSquared < (this->getDrone()->getMaxShootingRange()*this->getDrone()->getMaxShootingRange()))
     124                if (this->target_)
    102125                {
    103                     this->isShooting_ = true;
    104                     this->aimAtTarget();
    105                     this->getDrone()->fire(0);
     126                    float distanceToTargetSquared = (this->getDrone()->getWorldPosition() - this->target_->getWorldPosition()).squaredLength();
     127                    if (distanceToTargetSquared < (this->getDrone()->getMaxShootingRange()*this->getDrone()->getMaxShootingRange()))
     128                    {
     129                       this->isShooting_ = true;
     130                       this->aimAtTarget();
     131                       if(!this->friendlyFire())
     132                           this->getDrone()->fire(0);
     133                    }
     134               }
     135
     136
     137                float maxDistanceSquared = this->getDrone()->getMaxDistanceToOwner()*this->getDrone()->getMaxDistanceToOwner();
     138                float minDistanceSquared = this->getDrone()->getMinDistanceToOwner()*this->getDrone()->getMinDistanceToOwner();
     139                if((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength()  > 20.0f*maxDistanceSquared)
     140                {//FIX: if the drone's owner uses portal, the drone searches for the portal & adds it as a waypoint.
     141                    this->updatePointsOfInterest("PortalEndPoint", 500.0f); //possible conflict: speed-pickup
    106142                }
     143                if ((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength()  > maxDistanceSquared)
     144                {
     145                    this->moveToPosition(this->getOwner()->getWorldPosition()); //fly towards owner
     146                }
     147                else if((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength() < minDistanceSquared)
     148                {
     149                    this->moveToPosition(-this->getOwner()->getWorldPosition()); //fly away from owner
     150                }
     151                else if (!this->isShooting_)
     152                {
     153                    float random = rnd(2.0f);
     154                    float randomSelection = rnd(6.0f);
     155                    if((int)randomSelection==0) drone_->moveUpDown(random);
     156                    else if((int)randomSelection==1) drone_->moveRightLeft(random);
     157                    else if((int)randomSelection==2) drone_->moveFrontBack(random);
     158                    else if((int)randomSelection==3) drone_->rotateYaw(random);
     159                    else if((int)randomSelection==4) drone_->rotatePitch(random);
     160                    else if((int)randomSelection==5) drone_->rotateRoll(random);
     161                }
     162
     163                this->isShooting_ = false;
    107164            }
    108 
    109             float maxDistanceSquared = this->getDrone()->getMaxDistanceToOwner()*this->getDrone()->getMaxDistanceToOwner();
    110             float minDistanceSquared = this->getDrone()->getMinDistanceToOwner()*this->getDrone()->getMinDistanceToOwner();
    111             if ((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength()  > maxDistanceSquared)
    112             {
    113                 this->moveToPosition(this->getOwner()->getWorldPosition()); //fly towards owner
    114             }
    115             else if((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength() < minDistanceSquared)
    116             {
    117                 this->moveToPosition(-this->getOwner()->getWorldPosition()); //fly away from owner
    118             }
    119             else if (!this->isShooting_)
    120             {
    121                 float random = rnd(2.0f);
    122                 float randomSelection = rnd(6.0f);
    123                 if((int)randomSelection==0) drone_->moveUpDown(random);
    124                 else if((int)randomSelection==1) drone_->moveRightLeft(random);
    125                 else if((int)randomSelection==2) drone_->moveFrontBack(random);
    126                 else if((int)randomSelection==3) drone_->rotateYaw(random);
    127                 else if((int)randomSelection==4) drone_->rotatePitch(random);
    128                 else if((int)randomSelection==5) drone_->rotateRoll(random);
    129             }
    130 
    131             this->isShooting_ = false;
    132165        }
    133 
    134166        SUPER(AIController, tick, dt);
    135 
    136167    }
    137168
     
    147178            this->destroy();
    148179    }
     180
     181    bool DroneController::friendlyFire()
     182    {   ControllableEntity* droneEntity_ = this->getControllableEntity();
     183        if (!droneEntity_) return false;
     184        if(!owner_) return false;
     185        if(this->bHasTargetPosition_)
     186        {
     187            Vector3 ownerPosition_ = owner_->getPosition();
     188            Vector3 toOwner_ = owner_->getPosition() - droneEntity_->getPosition();
     189            Vector3 toTarget_ = targetPosition_ - droneEntity_->getPosition();
     190            if(toTarget_.length() < toOwner_.length()) return false; //owner is far away = in safty
     191            float angleToOwner = getAngle(droneEntity_->getPosition(), droneEntity_->getOrientation() * WorldEntity::FRONT, ownerPosition_);
     192            float angleToTarget = getAngle(droneEntity_->getPosition(), droneEntity_->getOrientation() * WorldEntity::FRONT, targetPosition_);
     193            float angle = angleToOwner - angleToTarget;//angle between target and owner, observed by the drone
     194            if(std::sin(angle)*toOwner_.length() < 5.0f)//calculate owner's distance to shooting line
     195            return true;
     196        }
     197        return false;//Default return value: Usually there is no friendlyFire
     198    }
    149199}
  • code/trunk/src/orxonox/controllers/DroneController.h

    r8729 r8891  
    6666            virtual void action();
    6767            void ownerDied();
     68            bool friendlyFire(); //<! returns true if the owner_ would be hit.
    6869            bool isShooting_;
    6970
  • code/trunk/src/orxonox/controllers/WaypointController.cc

    r5929 r8891  
    4040    {
    4141        RegisterObject(WaypointController);
    42 
    43         this->currentWaypoint_ = 0;
    4442        this->setAccuracy(100);
    4543    }
     
    4745    WaypointController::~WaypointController()
    4846    {
    49         if (this->isInitialized())
     47        for (size_t i = 0; i < this->waypoints_.size(); ++i)
    5048        {
    51             for (size_t i = 0; i < this->waypoints_.size(); ++i)
     49            if(this->waypoints_[i])
    5250                this->waypoints_[i]->destroy();
    5351        }
     
    5856        SUPER(WaypointController, XMLPort, xmlelement, mode);
    5957
    60         XMLPortParam(WaypointController, "accuracy", setAccuracy, getAccuracy, xmlelement, mode).defaultValues(100.0f);
    61         XMLPortObject(WaypointController, WorldEntity, "waypoints", addWaypoint, getWaypoint,  xmlelement, mode);
     58        XMLPortParam(ArtificialController, "accuracy", setAccuracy, getAccuracy, xmlelement, mode).defaultValues(100.0f);
     59        XMLPortObject(ArtificialController, WorldEntity, "waypoints", addWaypoint, getWaypoint,  xmlelement, mode);
    6260    }
    6361
     
    7674    }
    7775
    78     void WaypointController::addWaypoint(WorldEntity* waypoint)
    79     {
    80         this->waypoints_.push_back(waypoint);
    81     }
    82 
    83     WorldEntity* WaypointController::getWaypoint(unsigned int index) const
    84     {
    85         if (index < this->waypoints_.size())
    86             return this->waypoints_[index];
    87         else
    88             return 0;
    89     }
    9076}
  • code/trunk/src/orxonox/controllers/WaypointController.h

    r5781 r8891  
    4747            virtual void tick(float dt);
    4848
    49             void addWaypoint(WorldEntity* waypoint);
    50             WorldEntity* getWaypoint(unsigned int index) const;
     49        protected:
    5150
    52             inline void setAccuracy(float accuracy)
    53                 { this->squaredaccuracy_ = accuracy*accuracy; }
    54             inline float getAccuracy() const
    55                 { return sqrt(this->squaredaccuracy_); }
    56 
    57         protected:
    58             std::vector<WorldEntity*> waypoints_;
    59             size_t currentWaypoint_;
    60             float squaredaccuracy_;
    6151    };
    6252}
Note: See TracChangeset for help on using the changeset viewer.