Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/CommonController.cc @ 10849

Last change on this file since 10849 was 10849, checked in by gania, 9 years ago

major change: introduced Actionpoints, look AITest.oxw. Only FLY works for now

File size: 33.7 KB
RevLine 
[10719]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
[10799]11 *   of the License, or ( at your option )any later version.
[10719]12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Dominik Solenicki
26 *
27 */
[10800]28//bug or feature? Press 4 control keys from {Q,W,E,A,S,D,C} at the same time or 3 keys from {Q,E,A,D}, spaceship goes in free fly mode
[10719]29#include "controllers/CommonController.h"
[10759]30#include "core/XMLPort.h"
31
[10737]32#include "weaponsystem/WeaponMode.h"
33#include "weaponsystem/WeaponPack.h"
34#include "weaponsystem/Weapon.h"
35#include "weaponsystem/WeaponSlot.h"
36#include "weaponsystem/WeaponSlot.h"
37#include "worldentities/pawns/SpaceShip.h"
[10719]38
[10780]39#include "Scene.h"
[10838]40
41#include "worldentities/pawns/TeamBaseMatchBase.h"
42#include "gametypes/TeamDeathmatch.h"
43#include "gametypes/Dynamicmatch.h"
44#include "gametypes/Mission.h"
45#include "gametypes/Gametype.h"
46#include "controllers/WaypointPatrolController.h"
47#include "controllers/NewHumanController.h"
48#include "controllers/DroneController.h"
49
50
[10719]51namespace orxonox
52{
53
[10799]54    RegisterClass( CommonController );
[10826]55    const float SPEED = 0.9f/0.02f;
56    const float ROTATEFACTOR = 1.0f/0.02f;
[10719]57
[10799]58    CommonController::CommonController( Context* context ): Controller( context )
[10719]59    {
[10849]60        this->squaredaccuracy_ = 500;
61        this->action_ = Action::NONE;
[10803]62        this->stopLookingAtTarget();
[10849]63        this->attackRange_ = 800;
[10799]64        RegisterObject( CommonController );
[10719]65    }
[10731]66
67
[10799]68    CommonController::~CommonController() 
[10719]69    {
[10826]70        //orxout(internal_error) << "I died, my Rank is " << rank_ << endl;
[10731]71    }
[10849]72   
73 
[10799]74    void CommonController::XMLPort( Element& xmlelement, XMLPort::Mode mode )
[10759]75    {
[10799]76        SUPER( CommonController, XMLPort, xmlelement, mode );
77        XMLPortParam( CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode );
[10847]78        //XMLPortParam( CommonController, "action", setActionXML, getActionXML,  xmlelement, mode );
79        //XMLPortParam ( CommonController, "protect", setProtectXML, getProtectXML,  xmlelement, mode );
[10838]80        //XMLPortParam ( CommonController, "enemy", setEnemyXML, getEnemyXML,  xmlelement, mode );
[10847]81        XMLPortObject(CommonController, WorldEntity, "actionpoints", addActionpoint, getActionpoint,  xmlelement, mode);
82
[10838]83    }
84    void CommonController::setProtectXML( std::string val )
85    {
[10840]86        this->protectName_ = val;
87       
[10838]88    }
[10840]89    void CommonController::tick(float dt)
90    {
[10843]91        if (this->bHasTargetPosition_)
92        {
93            this->moveToTargetPosition(dt);
94        }
95        else if (this->bLookAtTarget_)
96        {
97            this->lookAtTarget(dt);
98        }
99        if (bShooting_)
100        {
101            this->doFire();
102        }
103        SUPER(CommonController, tick, dt);
[10840]104    }
105
[10838]106    std::string CommonController::getProtectXML ()
107    {
108        if (!this->getProtect())
109            return "noProtectWasSet";
[10849]110        return CommonController::getName (orxonox_cast<Pawn*>(this->getProtect()));
[10838]111    }
[10848]112    std::string CommonController::getName(Pawn* entity)
[10847]113    {
114        std::string name = entity->getName();
115        if (name == "")
116        {
117            const void * address = static_cast<const void*>(entity);
118            std::stringstream ss;
119            ss << address; 
120            name = ss.str();           
121        }
122        return name;
[10731]123
[10847]124    }
[10838]125    void CommonController::setProtect (ControllableEntity* protect)
126    {
127        this->protect_ = protect;
[10759]128    }
[10838]129    ControllableEntity* CommonController::getProtect ()
130    {
131        return this->protect_;
132    }
[10832]133    void CommonController::setActionXML( std::string val)
134    {
135        const std::string valUpper = getUppercase( val );
136        Action::Value value;
137       
138        if ( valUpper == "FIGHT" )
139            value = Action::FIGHT;
140        else if ( valUpper == "FLY" )
141            value = Action::FLY;
142        else if ( valUpper == "PROTECT" )
143            value = Action::PROTECT;
[10847]144        else if ( valUpper == "NONE" )
145            value = Action::NONE;
146        else if ( valUpper == "FIGHTALL" )
147            value = Action::FIGHTALL;
148        else if ( valUpper == "ATTACK" )
149            value = Action::ATTACK;
[10832]150        else
151            ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ val + "'." );
152        this->setAction( value );
153    }
154    std::string CommonController::getActionXML()
155    {
156        switch ( this->action_ )
157        {
158            case Action::FIGHT:
159            {
160                return "FIGHT";
161                break;
162            }
163            case Action::FLY:
164            {
165                return "FLY";
166                break;
167            }
168            case Action::PROTECT:
169            {
170                return "PROTECT";
171                break;
172            }
[10847]173            case Action::NONE:
174            {
175                return "NONE";
176                break;
177            }
178            case Action::FIGHTALL:
179            {
180                return "FIGHTALL";
181                break;
182            }
183            case Action::ATTACK:
184            {
185                return "ATTACK";
186                break;
187            }
[10832]188            default:
[10847]189                return "NONE";
[10832]190                break;
191        }
192    }
[10799]193    void CommonController::setFormationModeXML( std::string val )
[10759]194    {
[10799]195        const std::string valUpper = getUppercase( val );
[10759]196        FormationMode::Value value;
[10826]197       
198        if ( valUpper == "WALL" )
[10759]199            value = FormationMode::WALL;
[10799]200        else if ( valUpper == "FINGER4" )
[10759]201            value = FormationMode::FINGER4;
[10799]202        else if ( valUpper == "DIAMOND" )
[10759]203            value = FormationMode::DIAMOND;
204        else
[10799]205            ThrowException( ParseError, std::string( "Attempting to set an unknown FormationMode: '" )+ val + "'." );
206        this->setFormationMode( value );
[10759]207       
208    }
[10799]209    std::string CommonController::getFormationModeXML() 
[10759]210    {
[10799]211        switch ( this->formationMode_ )
[10759]212        {
213            case FormationMode::WALL:
214            {
215                return "WALL";
216                break;
217            }
218            case FormationMode::FINGER4:
219            {
220                return "FINGER4";
221                break;
222            }
223            case FormationMode::DIAMOND:
224            {
225                return "DIAMOND";
226                break;
227            }
228            default:
229                return "DIAMOND";
230                break;
[10731]231
[10759]232        }
233    }
[10805]234    Action::Value CommonController::getAction ()
235    {
236        return this->action_;
237    }
[10832]238    void CommonController::setAction (Action::Value action)
239    {
240        this->action_ = action;
241    }
[10805]242
243    void CommonController::setAction (Action::Value action, ControllableEntity* target)
244    {
245        this->action_ = action;
[10849]246        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
[10805]247        {   
248            if (target)
249                this->setTarget (target);
250        }
251        else if (action == Action::PROTECT)
252        {
[10840]253            if (target)
254                this->setProtect (target);
[10805]255        }
256    }
257    void CommonController::setAction (Action::Value action, const Vector3& target)
258    {
259        this->action_ = action;
260        if (action == Action::FLY)
261        {
262            this->setTargetPosition (target);
263        }
[10840]264       
[10805]265    }
266    void CommonController::setAction (Action::Value action, const Vector3& target,  const Quaternion& orient )
267    {
268        this->action_ = action;
269        if (action == Action::FLY)
270        {
271            this->setTargetPosition (target);
272            this->setTargetOrientation (orient);
273        }
[10840]274       
[10805]275    }
[10847]276    void CommonController::addActionpoint(WorldEntity* actionpoint)
277    {
278        std::string actionName;
279        Vector3 position;
280        std::string targetName;
[10848]281
[10847]282        if (static_cast<Actionpoint*> (actionpoint))
283        {
284            Actionpoint* ap = static_cast<Actionpoint*> (actionpoint);
[10848]285           
[10847]286            actionName = ap->getActionXML();
[10848]287            targetName = ap->getName();
288            position = ap->getWorldPosition();
289
[10847]290            Action::Value value;
291           
[10848]292            if ( actionName == "FIGHT" )
[10847]293            {
294                value = Action::FIGHT;
295
296            }
[10848]297            else if ( actionName == "FLY" )
[10847]298            {
299                value = Action::FLY;
300
301            }
[10848]302            else if ( actionName == "PROTECT" )
[10847]303            {
304                value = Action::PROTECT;
305
306            }
[10848]307            else if ( actionName == "NONE" )
[10847]308            {
309                value = Action::NONE;
310
311            }
[10848]312            else if ( actionName == "FIGHTALL" )
[10847]313            {
314                value = Action::FIGHTALL;
315
316            }
[10848]317            else if ( actionName == "ATTACK" )
[10847]318            {
319                value = Action::ATTACK;
320
[10848]321
[10847]322            }
323            else
[10849]324                ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ actionName + "'." );
[10848]325            //this->setAction( value );
[10849]326            Point p = { value, targetName, position };
327            parsedActionpoints_.push_back(p);
328            orxout(internal_error) << "Pushed " << p.action << endl;
[10847]329        }
330        else
331        {
[10849]332            Point p = { Action::FLY, "", actionpoint->getWorldPosition() };
333            parsedActionpoints_.push_back(p);
[10847]334        }
[10848]335            this->actionpoints_.push_back(actionpoint);
336
[10847]337       
338    }
339
340    WorldEntity* CommonController::getActionpoint(unsigned int index) const
341    {
342        if (index < this->actionpoints_.size())
343            return this->actionpoints_[index];
344        else
345            return 0;
346    }
[10832]347    void CommonController::setClosestTarget()
348    {
[10849]349        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
[10847]350    }
[10849]351    Pawn* CommonController::closestTarget()
[10847]352    {
[10832]353        if (!this->getControllableEntity())
[10847]354            return 0;
[10832]355
356        Pawn* closestTarget = 0;
357        float minDistance =  std::numeric_limits<float>::infinity();
[10838]358        Gametype* gt = this->getGametype();
[10832]359        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
360        {
[10838]361            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
[10832]362                continue;
363
364            float distance = CommonController::distance (*itP, this->getControllableEntity());
365            if (distance < minDistance)
366            {
367                closestTarget = *itP;
368                minDistance = distance;
369            }
370        }
371        if (closestTarget)
372        {
[10849]373           return closestTarget;
[10847]374        } 
375        return 0; 
[10832]376    }
[10848]377    //POST: this starts doing what was asked by the last element of parsedActionpoints_,
378    //if last element was failed to be parsed, next element will be executed.
379    void CommonController::executeActionpoint()
380    {
381        if (!this->parsedActionpoints_.empty())
382        {
[10849]383            this->action_ = this->parsedActionpoints_.back().action;
[10848]384
385            switch ( this->action_ )
386            {
387                case Action::FIGHT:
388                {               
389                    break;
390                }
391                case Action::FLY:
392                {
[10849]393                    this->setTargetPosition( this->parsedActionpoints_.back().position );
[10848]394                    if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
395                    {
396                        this->nextActionpoint();
397                        this->executeActionpoint();
398                    }
399                    break;
400                }
401                case Action::PROTECT:
402                {
[10849]403                    std::string protectName = this->parsedActionpoints_.back().name;
[10848]404
405                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
406                    {
407                        if (CommonController::getName(*itP) == protectName)
408                        {
409                            this->setProtect (static_cast<ControllableEntity*>(*itP));
410                        }
411                    }
412                    if (!this->getProtect())
413                    {
414                        this->nextActionpoint();
415                        this->executeActionpoint();
416                    }
417                    break;
418                }
419                case Action::NONE:
420                {
421                    break;
422                }
423                case Action::FIGHTALL:
424                {
425                    break;
426                }
427                case Action::ATTACK:
428                {
[10849]429                    std::string targetName = this->parsedActionpoints_.back().name;
[10848]430
431                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
432                    {
433                        if (CommonController::getName(*itP) == targetName)
434                        {
[10849]435                            orxout(internal_error) << "Attacking" << endl;
[10848]436                            this->setTarget (static_cast<ControllableEntity*>(*itP));
437                        }
438                    }
439                    if (!this->getTarget())
440                    {
441                        this->nextActionpoint();
442                        this->executeActionpoint();
443                    }
444                    break;
445                }
446                default:
447                    break;
448            }
449           
450
451        }
452        else
453        {
454            this->setTarget(0);
455            this->setTargetPosition(this->getControllableEntity()->getWorldPosition());
456            this->action_ = Action::NONE;
457        }
[10849]458        orxout(internal_error) << "Executing action " << this->getActionXML() << endl;
[10848]459    }
460    void CommonController::nextActionpoint()
461    {
462        if (!this->parsedActionpoints_.empty())
463        {
464            this->parsedActionpoints_.pop_back();
465        }
466        this->setAction(Action::NONE);
467    }
468
[10799]469    void CommonController::maneuver() 
[10797]470    {
[10832]471        maneuverCounter_++;
[10797]472
[10832]473        if (maneuverCounter_ > 5)
474            maneuverCounter_ = 0;
[10803]475        if ( this->target_ && this->getControllableEntity())
[10797]476        {
[10803]477            Vector3 thisPosition = this->getControllableEntity()->getWorldPosition();
478            //Quaternion thisOrientation = this->getControllableEntity()->getOrientation();
[10799]479
[10803]480            this->setPositionOfTarget( getPredictedPosition( 
[10799]481                thisPosition, 
482                hardcoded_projectile_speed, 
483                this->target_->getWorldPosition() , 
484                this->target_->getVelocity() 
[10803]485                )  );
[10800]486            this->setOrientationOfTarget( this->target_->getOrientation() );
[10799]487
488
489            Vector3 diffVector = this->positionOfTarget_ - thisPosition;
[10797]490            float diffLength = diffVector.length();
491            Vector3 diffUnit = diffVector/diffLength;
492
493
494
[10803]495            //bool bThisIsLookingAtTarget = this->isLooking ( getControllableEntity(), this->target_, math::pi/4 );
[10832]496            bool bTargetIsLookingAtThis = this->isLooking ( this->target_, getControllableEntity(), math::pi/10.0f );
[10803]497           
[10799]498
499
[10803]500            //too far? well, come closer then
[10805]501            if ( diffLength > 3000 )
[10797]502            {
[10803]503                if (diffLength < 6000)
[10797]504                {
[10805]505
[10797]506                }
507                else
508                {
509                }
[10803]510                this->setTargetPosition( this->positionOfTarget_ );
[10797]511            }
[10803]512            //too close? How do u expect to dodge anything? Just attack!
[10805]513            else if ( diffLength < 500 )
[10803]514            {   
515                //at this point, just look and shoot
[10805]516                if ( diffLength < 250 )
[10800]517                {
[10803]518                    this->stopMoving();
519                    this->startLookingAtTarget();
[10800]520                }
521                else
522                {
[10803]523                    this->setTargetPosition( this->positionOfTarget_ );
[10800]524                }
525            }
[10803]526            //Good distance? Check if target looks at us. It doesn't? Go hunt!
527            else if ( !bTargetIsLookingAtThis )
[10793]528            {
[10803]529                this->setTargetPosition( this->positionOfTarget_ );
[10832]530              /*  if (maneuverCounter_ == 0)
[10793]531                {
[10803]532                    this->setTargetPosition( this->positionOfTarget_ );   
533                    return;
[10793]534                }
[10803]535                else
[10793]536                {
[10803]537                    dodge( thisPosition, diffUnit );
538                }*/
539            }
540            //That's unfortunate, he is looking and probably shooting... try to dodge what we can... 
541            else 
542            {   
543           
[10832]544                if (maneuverCounter_ == 0)
[10793]545                {
[10803]546                    this->setTargetPosition( this->positionOfTarget_ );   
547                    return;
[10793]548                }
[10803]549                dodge( thisPosition, diffUnit );
550               
[10793]551            }
552        }
[10826]553       
[10805]554        //orxout ( internal_error ) << "ManeuverType = " << this->maneuverType_ << endl;
[10793]555    }
[10803]556    ControllableEntity* CommonController::getTarget()
557    {
558        return this->target_;
559    }
560    void CommonController::dodge(Vector3& thisPosition, Vector3& diffUnit)
561    {
562        float factorX = 0, factorY = 0, factorZ = 0;
563        float rand = randomInRange (0, 1);
564        if (rand <= 0.5)
565        {
566            factorX = 1;
567        }
568        else
569        {
570            factorX = -1;
571        }
572        rand = randomInRange (0, 1);
573        if (rand <= 0.5)
574        {
575            factorY = 1;
576        }
577        else
578        {
579            factorY = -1;
580        }
581        rand = randomInRange (0, 1);
582        if (rand <= 0.5)
583        {
584            factorZ = 1;
585        }
586        else
587        {
588            factorZ = -1;
589        }
590        Vector3 target = ( diffUnit )* 8000.0f;
591        Vector3* randVector = new Vector3( 
592            factorX * randomInRange( 10000, 40000 ), 
593            factorY * randomInRange( 10000, 40000 ), 
594            factorZ * randomInRange( 10000, 40000 ) 
595        );
596        Vector3 projection = randVector->dotProduct( diffUnit )* diffUnit;
597        *randVector -= projection;
598        target += *randVector;
599        this->setTargetPosition( thisPosition + target );
600    }
601    void CommonController::stopMoving()
602    {
603        this->bHasTargetPosition_ = false;
604    }
605    void CommonController::startLookingAtTarget()
606    {
607        this->bLookAtTarget_ = true;
608    }
609    void CommonController::stopLookingAtTarget()
610    {
611        this->bLookAtTarget_ = false;
612    }
613    void CommonController::lookAtTarget(float dt)
614    {
615
616       
617        ControllableEntity* entity = this->getControllableEntity();
618        if ( !entity )
619            return;
620        Vector2 coord = get2DViewCoordinates
621            ( entity->getPosition() , 
622            entity->getOrientation()  * WorldEntity::FRONT, 
623            entity->getOrientation()  * WorldEntity::UP, 
624            positionOfTarget_ );
625
626        //rotates should be in range [-1,+1], clamp cuts off all that is not
627        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
628        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
629
630       
631   
632        //Yaw and Pitch are enough to start facing the target
633        this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
634        this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
635       
636           
637    }
638   
[10799]639    bool CommonController::setWingman ( CommonController* wingman )
[10731]640    {
[10719]641        return false;
642    }
[10731]643   
[10799]644    bool CommonController::hasWingman() 
[10722]645    {
646        return true;
647    }
[10799]648    void CommonController::setTarget( ControllableEntity* target )
[10759]649    {
650        this->target_ = target;
[10805]651        //orxout ( internal_error ) << " TARGET SET " << endl;
[10793]652       
[10799]653        if ( this->target_ )
[10793]654        {
[10799]655            this->setPositionOfTarget( target_->getWorldPosition() );
[10793]656
657        }
[10759]658    }
[10799]659    bool CommonController::hasTarget() 
[10793]660    {
[10799]661        if ( this->target_ )
[10793]662            return true;
663        return false;
664    }
[10799]665    void CommonController::setPositionOfTarget( const Vector3& target )
[10793]666    {
667        this->positionOfTarget_ = target;
668        this->bHasPositionOfTarget_ = true;
669    }
[10799]670    void CommonController::setOrientationOfTarget( const Quaternion& orient )
[10793]671    {
672        this->orientationOfTarget_=orient;
673        this->bHasOrientationOfTarget_=true;
674    }
[10722]675
[10799]676    void CommonController::setTargetPosition( const Vector3& target )
[10719]677    {
[10731]678        this->targetPosition_ = target;
679        this->bHasTargetPosition_ = true;
680    }
[10719]681
[10799]682    void CommonController::setTargetOrientation( const Quaternion& orient )
[10731]683    {
684        this->targetOrientation_=orient;
685        this->bHasTargetOrientation_=true;
[10719]686    }
687
[10799]688    void CommonController::setTargetOrientation( ControllableEntity* target )
[10731]689    {
[10799]690        if ( target )
691            setTargetOrientation( target->getOrientation() );
[10731]692    }
[10719]693
[10731]694
695
[10729]696    //copy the Roll orientation of given Quaternion.
[10799]697    void CommonController::copyOrientation( const Quaternion& orient, float dt )
[10729]698    {
699        //roll angle difference in radian
[10799]700        float diff=orient.getRoll( false ).valueRadians() -( this->getControllableEntity() ->getOrientation() .getRoll( false ).valueRadians() );
701        while( diff>math::twoPi )diff-=math::twoPi;
702        while( diff<-math::twoPi )diff+=math::twoPi;
703        this->getControllableEntity() ->rotateRoll( diff*ROTATEFACTOR * dt );
[10729]704    }
[10799]705    void CommonController::copyTargetOrientation( float dt )
[10729]706    {
[10799]707        if ( bHasTargetOrientation_ )
[10729]708        {   
[10799]709            copyOrientation( targetOrientation_, dt );
[10729]710        }
711    }
[10731]712
713
714
715
[10799]716    void CommonController::moveToTargetPosition( float dt )
[10729]717    {
[10799]718        this->moveToPosition( this->targetPosition_, dt );
[10729]719    }
[10799]720    void CommonController::moveToPosition( const Vector3& target, float dt )
[10725]721    {
[10805]722     
[10729]723       
[10799]724        //100 is ( so far )the smallest tolerance ( empirically found )that can be reached,
[10729]725        //with smaller distance spaceships can't reach position and go circles around it instead
[10803]726        int tolerance = 65;
[10725]727
[10729]728        ControllableEntity* entity = this->getControllableEntity();
729        Vector2 coord = get2DViewCoordinates
[10799]730            ( entity->getPosition() , 
731            entity->getOrientation()  * WorldEntity::FRONT, 
732            entity->getOrientation()  * WorldEntity::UP, 
733            target );
[10729]734
[10799]735        float distance = ( target - this->getControllableEntity() ->getPosition() ).length();
[10729]736
737        //rotates should be in range [-1,+1], clamp cuts off all that is not
[10803]738        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
[10799]739        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
[10725]740
741       
[10799]742        if ( distance > tolerance )
[10725]743        {
[10729]744            //Yaw and Pitch are enough to start facing the target
[10803]745            this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
746            this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
[10729]747
748            //300 works, maybe less is better
[10799]749            if ( distance < 400 )
[10729]750            {
751                //Change roll when close. When Spaceship faces target, roll doesn't affect it's trajectory
752                //It's important that roll is not changed in the process of changing yaw and pitch
753                //Wingmen won't face same direction as Leaders, but when Leaders start moving
754                //Yaw and Pitch will adapt.
[10799]755                if ( bHasTargetOrientation_ )
[10729]756                {
[10799]757                    copyTargetOrientation( dt );
[10729]758                }
759            }
[10763]760
[10805]761            this->getControllableEntity() ->moveFrontBack( SPEED * dt );
[10725]762        }
[10729]763        else
764        {     
765            bHasTargetPosition_ = false;
766            bHasTargetOrientation_ = false;
767        }
[10731]768    }
[10799]769    float CommonController::randomInRange( float a, float b )
[10796]770    {
[10799]771        float random = rnd( 1.0f );
[10796]772        float diff = b - a;
773        float r = random * diff;
774        return a + r;
775    }
[10803]776   
[10796]777
[10782]778    //to be called in action
779    //PRE: relativeTargetPosition is desired position relative to the spaceship,
[10789]780    //angleRoll is the angle in degrees of Roll that should be applied by the end of the movement
[10799]781    //POST: target orientation and position are set, so that it can be used by MoveAndRoll()
782    void CommonController::moveToPoint( const Vector3& relativeTargetPosition, float angleRoll )
[10782]783    {
784        ControllableEntity* entity = this->getControllableEntity();
[10799]785        if ( !entity )
[10789]786            return;
[10782]787        Quaternion orient = entity->getWorldOrientation();
[10799]788        Quaternion rotation = Quaternion( Degree( angleRoll ), Vector3::UNIT_Z );
[10737]789
[10782]790        Vector3 target = orient * relativeTargetPosition + entity->getWorldPosition();
[10799]791        setTargetPosition( target );
[10789]792        orient = orient * rotation;
[10799]793        this->setTargetOrientation( orient );
[10789]794       
[10782]795    }
796    //to be called in tick
797    //PRE: MoveToPoint was called
798    //POST: spaceship changes its yaw and pitch to point towards targetPosition_,
799    //moves towards targetPosition_ by amount depending on dt and its speed,
800    //rolls by amount depending on the difference between angleRoll_ and angleRolled_, dt, and
801    //angular speed
802    //if position reached with a certain tolerance, and angleRolled_ = angleRoll_, returns false,
803    //otherwise returns true
[10789]804    //dt is normally around 0.02f, which makes it 1/0.02 = 50 frames/sec
[10799]805    bool CommonController::moveAndRoll( float dt )
[10737]806    {
[10789]807        float factor = 1;
[10799]808        if ( !this->getControllableEntity() )
[10789]809            return false;
[10799]810        if ( this->rank_ == Rank::DIVISIONLEADER )
[10789]811            factor = 0.8;
[10799]812        if ( this->rank_ == Rank::SECTIONLEADER )
[10789]813            factor = 0.9;
[10782]814        int tolerance = 60;
[10789]815       
[10782]816        ControllableEntity* entity = this->getControllableEntity();
[10799]817        if ( !entity )
[10789]818            return true;
[10782]819        Vector2 coord = get2DViewCoordinates
[10799]820            ( entity->getPosition() , 
821            entity->getOrientation()  * WorldEntity::FRONT, 
822            entity->getOrientation()  * WorldEntity::UP, 
823            targetPosition_ );
[10737]824
[10799]825        float distance = ( targetPosition_ - this->getControllableEntity() ->getPosition() ).length();
[10782]826
827        //rotates should be in range [-1,+1], clamp cuts off all that is not
[10799]828        float rotateX = clamp( coord.x * 10, -1.0f, 1.0f );
829        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
[10782]830
831       
[10799]832        if ( distance > tolerance )
[10782]833        {
834            //Yaw and Pitch are enough to start facing the target
[10799]835            this->getControllableEntity() ->rotateYaw( -2.0f * ROTATEFACTOR * rotateX * dt );
836            this->getControllableEntity() ->rotatePitch( 2.0f * ROTATEFACTOR * rotateY * dt );
[10782]837           
[10789]838            //Roll
[10799]839            if ( bHasTargetOrientation_ )
[10789]840            {
[10799]841                copyTargetOrientation( dt );
[10789]842            }
843         
[10782]844            //Move
[10799]845            this->getControllableEntity() ->moveFrontBack( 1.2f * SPEED * factor * dt );
[10782]846            //if still moving, return false
847            return false;
848        }
[10737]849        else
[10782]850        {     
[10789]851           
[10782]852            //if finished, return true;
[10789]853            return true;
[10782]854        }
[10737]855    }
[10782]856
[10799]857    float CommonController::squaredDistanceToTarget()  const
[10782]858    {
[10799]859        if ( !this->getControllableEntity()  )
[10782]860            return 0;
[10803]861        if ( !this->target_ || !this->getControllableEntity() )
[10799]862            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->targetPosition_ ) );
[10782]863        else
[10800]864            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->positionOfTarget_ ) );
[10782]865    }
866   
[10799]867    bool CommonController::isLookingAtTarget( float angle )const
[10737]868    {
[10803]869        if ( !this->getControllableEntity()  || !this->target_ )
[10762]870            return false;
871
[10803]872        return ( getAngle( this->getControllableEntity() ->getPosition() , 
873            this->getControllableEntity() ->getOrientation()  * WorldEntity::FRONT, this->positionOfTarget_ ) < angle );
[10780]874    }
[10832]875    bool CommonController::isLooking( ControllableEntity* entityThatLooks, ControllableEntity* entityBeingLookedAt, float angle )
[10803]876    {
877        if ( !entityThatLooks || !entityBeingLookedAt )
878            return false;
879        return ( getAngle( entityThatLooks ->getPosition() , 
880            entityThatLooks->getOrientation()  * WorldEntity::FRONT, 
881            entityBeingLookedAt->getWorldPosition() ) < angle );
882    }
[10764]883
[10799]884    bool CommonController::canFire() 
[10780]885    {
[10803]886
887        //no target? why fire?
888        if ( !this->target_ )
889            return false;
890
891        Vector3 newPositionOfTarget = getPredictedPosition( this->getControllableEntity() ->getWorldPosition() , 
892            hardcoded_projectile_speed, this->target_->getWorldPosition() , this->target_->getVelocity() );
893        if ( newPositionOfTarget != Vector3::ZERO )
894        {
895            this->setPositionOfTarget( newPositionOfTarget );
896        }
897
[10782]898        float squaredDistance = squaredDistanceToTarget();
[10800]899
[10832]900        if ( squaredDistance < 9000000.0f && this->isLookingAtTarget( math::pi / 20.0f)) {
[10780]901            return true;
902        }
903        else
904        {
[10762]905            return false;
[10780]906        }
[10762]907
[10780]908    }
[10826]909    float CommonController::distance (ControllableEntity* entity1, ControllableEntity* entity2)
910    {
911        if (!entity1 || !entity2)
912            return std::numeric_limits<float>::infinity();
913        return ( entity1->getPosition() - entity2->getPosition() ).length();
914    }
[10838]915    bool CommonController::sameTeam (ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
[10826]916    {
[10838]917        /*if (!entity1 || !entity2)
[10826]918            return false;
[10838]919        return entity1->getTeam() == entity2->getTeam();*/
920        if (entity1 == entity2)
921            return true;
922
923        int team1 = entity1->getTeam();
924        int team2 = entity2->getTeam();
925
926        Controller* controller = 0;
927        if (entity1->getController())
928            controller = entity1->getController();
929        else
930            controller = entity1->getXMLController();
931        if (controller)
932        {
933            CommonController* ac = orxonox_cast<CommonController*>(controller);
934            if (ac)
935                team1 = ac->getTeam();
936        }
937
938        if (entity2->getController())
939            controller = entity2->getController();
940        else
941            controller = entity2->getXMLController();
942        if (controller)
943        {
944            CommonController* ac = orxonox_cast<CommonController*>(controller);
945            if (ac)
946                team2 = ac->getTeam();
947        }
948
949        TeamGametype* tdm = orxonox_cast<TeamGametype*>(gametype);
950        if (tdm)
951        {
952            if (entity1->getPlayer())
953                team1 = tdm->getTeam(entity1->getPlayer());
954
955            if (entity2->getPlayer())
956                team2 = tdm->getTeam(entity2->getPlayer());
957        }
958
959        TeamBaseMatchBase* base = 0;
960        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
961        if (base)
962        {
963            switch (base->getState())
964            {
965                case BaseState::ControlTeam1:
966                    team1 = 0;
967                    break;
968                case BaseState::ControlTeam2:
969                    team1 = 1;
970                    break;
971                case BaseState::Uncontrolled:
972                default:
973                    team1 = -1;
974            }
975        }
976        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
977        if (base)
978        {
979            switch (base->getState())
980            {
981                case BaseState::ControlTeam1:
982                    team2 = 0;
983                    break;
984                case BaseState::ControlTeam2:
985                    team2 = 1;
986                    break;
987                case BaseState::Uncontrolled:
988                default:
989                    team2 = -1;
990            }
991        }
992
993        DroneController* droneController = 0;
994        droneController = orxonox_cast<DroneController*>(entity1->getController());
995        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
996            return true;
997        droneController = orxonox_cast<DroneController*>(entity2->getController());
998        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
999            return true;
1000        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
1001        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
1002        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
1003            return true;
1004
1005        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
1006        if (dynamic)
1007        {
1008            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
1009
1010            if (entity1->getPlayer())
1011                team1 = dynamic->getParty(entity1->getPlayer());
1012
1013            if (entity2->getPlayer())
1014                team2 = dynamic->getParty(entity2->getPlayer());
1015
1016            if (team1 ==-1 ||team2 ==-1 ) {return false;}
1017            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
1018            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
1019            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
1020            else return true;
1021        }
1022
1023        return (team1 == team2 && team1 != -1);
[10826]1024    }
[10799]1025    void CommonController::doFire() 
[10780]1026    {
[10799]1027        if ( !this->target_ || !this->getControllableEntity() )
[10803]1028        {
[10780]1029            return;
[10803]1030        }
1031     
[10799]1032        Pawn* pawn = orxonox_cast<Pawn*>( this->getControllableEntity() );
[10793]1033
[10799]1034        if ( pawn )
1035            //pawn->setAimPosition( this->getControllableEntity() ->getWorldPosition()  + 4000*( this->getControllableEntity() ->getOrientation()  * WorldEntity::FRONT ));
[10800]1036            pawn->setAimPosition( this->positionOfTarget_ );
[10763]1037   
[10799]1038        this->getControllableEntity() ->fire( 0 );
[10731]1039    }
[10762]1040   
[10725]1041
[10719]1042}
Note: See TracBrowser for help on using the repository browser.