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:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • 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}
Note: See TracChangeset for help on using the changeset viewer.