Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/SectionController.cc @ 10882

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

finished fixing FlyingController: AI is flying as smooth as possible with minimum loss of performance

File size: 12.3 KB
Line 
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
11 *   of the License, or (at your option) any later version.
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 */
28
29#include "SectionController.h"
30//TODO: formation vectors are wrong, fix it.
31// split classes.
32// weaponsystem.
33//-> Math ?
34 
35namespace orxonox
36{
37
38    RegisterClass(SectionController);
39
40    //Leaders share the fact that they have Wingmans
41    SectionController::SectionController(Context* context) : LeaderController(context)
42    {
43        RegisterObject(SectionController);
44        this->setFormationMode(FormationMode::FINGER4);
45
46        this->actionTimer_.setTimer(ACTION_INTERVAL, true, createExecutor(createFunctor(&SectionController::action, this)));
47        this->myWingman_ = 0;
48        this->myDivisionLeader_ = 0;
49        this->bFirstAction_ = true;
50        //orxout(internal_error) << this << "Was created" << endl;
51
52    }
53   
54    SectionController::~SectionController()
55    {
56        // if (this->myWingman_)
57        // {
58        //     this->myWingman_->takeActionpoints(this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
59        // }
60       for (size_t i = 0; i < this->actionpoints_.size(); ++i)
61        {
62            if(this->actionpoints_[i])
63                this->actionpoints_[i]->destroy();
64        }
65        this->parsedActionpoints_.clear();
66        this->actionpoints_.clear();
67    }
68    void SectionController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
69    {
70        SUPER(SectionController, XMLPort, xmlelement, mode);
71
72        //XMLPortParam(SectionController, "target_", setTarget, getTarget, xmlelement, mode).defaultValues(100.0f);
73    }
74
75    //----in tick, move (or look) and shoot----
76    void SectionController::tick(float dt)
77    {
78        if (!this->isActive())
79            return;
80
81    //this doesn't fight in formation flight, thus we can afford executing following code in tick: when nobody fights, tick is anyway stable.
82        if (this->myDivisionLeader_ && this->myDivisionLeader_->getAction() != Action::FIGHT && this->myDivisionLeader_->getAction() !=
83            Action::FIGHTALL && this->myDivisionLeader_->getAction() != Action::ATTACK)
84        {
85           
86        }   
87        SUPER(SectionController, tick, dt);
88    }
89
90    void SectionController::action()
91    {
92        if (!this || !this->getControllableEntity())
93            return;
94
95        //----If no leader, find one---- 
96        if (!myDivisionLeader_)
97        {
98            LeaderController* newDivisionLeader = findNewDivisionLeader();
99            this->myDivisionLeader_ = newDivisionLeader;
100            //spread copyOrientation called equally among the division
101            if (this->myDivisionLeader_)
102            {
103                this->actionCounter_ = 8;
104            }
105        }
106        //----If have leader----
107        else
108        {
109        }
110        if (!myDivisionLeader_)
111        {
112           
113            ActionpointController::action();
114            if (!this || !this->getControllableEntity())
115                return;
116            if (!(this->parsedActionpoints_.empty() && this->loopActionpoints_.empty()))
117            {
118                if (this->myWingman_)
119                {
120                    this->myWingman_->takeActionpoints(this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
121                }   
122            }
123        }
124        else if (myDivisionLeader_)
125        {
126            switch (myDivisionLeader_->getAction())
127            {
128                case Action::FIGHT:
129                {
130                    if (!this->hasTarget())
131                    {
132                        this->chooseTarget();
133                    }
134                    break;
135                }
136                case Action::FIGHTALL:
137                {
138                    if (!this->hasTarget())
139                    {
140                        this->chooseTarget();
141                    }
142                    break;
143                }
144                case Action::ATTACK:
145                {
146                    if (!this->hasTarget())
147                    {
148                        this->chooseTarget();
149                    }
150                    break;
151                }
152                default:
153                {
154                    //formation flight is executed in tick
155                    ControllableEntity* myEntity = this->getControllableEntity();
156            Vector3 myPosition = myEntity->getWorldPosition();
157            if (!this->myDivisionLeader_)
158            {
159                return;
160            }
161            ControllableEntity* leaderEntity = this->myDivisionLeader_->getControllableEntity();
162            Quaternion orient = leaderEntity->getWorldOrientation();
163            Vector3 leaderPosition = leaderEntity->getWorldPosition();
164
165            Vector3 targetRelativePosition = getFormationPosition();
166            if (!this->myDivisionLeader_)
167            {
168                return;
169            }
170            Vector3 targetAbsolutePosition = 
171                (leaderPosition + (orient*WorldEntity::FRONT) * (leaderEntity->getVelocity().length()/5)
172                 + (orient* (targetRelativePosition)));
173            //let ship finish rotating. also don't call copyOrientation to often as it is a slow function.
174            if (this->actionCounter_ % 9 == 0 && !this->bHasTargetOrientation_)
175                this->setAction (Action::FLY, targetAbsolutePosition, orient);
176            else
177                this->setAction (Action::FLY, targetAbsolutePosition);
178
179            if ((targetAbsolutePosition - myPosition).length() > this->tolerance_ * 1.5f)
180            {
181                this->boostControl();
182            }
183            else
184            {
185               this->getControllableEntity()->boost(false);
186            }
187                }
188            }
189            if (this->hasTarget())
190            {
191                //----choose where to go----
192                this->maneuver();
193                //----fire if you can----
194                this->bShooting_ = this->canFire();               
195            }
196        }
197        this->actionCounter_ += this->actionCounter_ < 100000 ? 1 : -this->actionCounter_ ;
198
199    }
200
201   
202    //PRE: myDivisionLeader_ != 0 && myDivisionLeader_->action_ == Action::FIGHT
203    //POST: this->target_ is set unless division leader doesn't have one
204    void SectionController::chooseTarget()
205    {
206        //----If division leader fights, cover him by fighting emenies close to his target----
207        Action::Value action = this->myDivisionLeader_->getAction();
208       
209        Pawn* target;
210        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
211        {
212            //----if he has a target----
213            if (this->myDivisionLeader_->hasTarget())
214            {
215                //----try to find a new target if division leader has wingman (doing fine) and no good target already set----
216                if ( this->myDivisionLeader_->hasWingman() && 
217                    !( this->hasTarget() && this->getTarget() != this->myDivisionLeader_->getTarget() ) )
218                {
219
220                    bool foundTarget = false;
221                    //----new target should be close to division's target----
222                    Vector3 divisionTargetPosition = this->myDivisionLeader_->getTarget()->getWorldPosition();
223                    Gametype* gt = this->getGametype();
224                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
225                    {
226                        //----is enemy?----
227                        if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
228                            continue;           
229                        //----in range?----
230                        if (((*itP)->getWorldPosition() - divisionTargetPosition).length() < 3000 && 
231                            (*itP) != this->myDivisionLeader_->getTarget())
232                        {
233                            foundTarget = true;
234                            target =  (*itP);
235                            //orxout(internal_error) << "Found target" << endl;
236                            break; 
237                        }
238                    }
239                    //----no target? then attack same target as division leader----
240                    if (!foundTarget)
241                    {
242                        target = orxonox_cast<Pawn*>(this->myDivisionLeader_->getTarget());
243                    }
244                }
245                //----if division leader doesn't have a wingman, support his fire----
246                else
247                {
248                    target = orxonox_cast<Pawn*>(this->myDivisionLeader_->getTarget());
249                }
250            }
251            //----If he fights but doesn't have a target, wait for him to get one----
252            else
253            {
254
255            }
256            this->setTarget (orxonox_cast<ControllableEntity*>(target));
257        }
258        else
259        {
260        } 
261    }
262    Vector3 SectionController::getFormationPosition ()
263    {
264        this->setFormationMode( this->myDivisionLeader_->getFormationMode() );
265        Vector3* targetRelativePosition;
266        switch (this->formationMode_){
267            case FormationMode::WALL:
268            {
269                targetRelativePosition = new Vector3 (-2*this->spread_, 0, 0);   
270                break;
271            }
272            case FormationMode::FINGER4: 
273            {
274                targetRelativePosition = new Vector3 (-2*this->spread_, 0, this->spread_);   
275                break;
276            }
277           
278            case FormationMode::DIAMOND: 
279            {
280                targetRelativePosition = new Vector3 (-2*this->spread_, 0, this->spread_);                   
281                break;
282            }
283        }
284        Vector3 result = *targetRelativePosition;
285        delete targetRelativePosition;
286        return result;
287    }
288
289   
290
291    LeaderController* SectionController::findNewDivisionLeader()
292    {
293
294        if (!this->getControllableEntity())
295            return 0;
296
297        LeaderController* closestLeader = 0;
298        float minDistance =  std::numeric_limits<float>::infinity();
299        //go through all pawns
300        for (ObjectList<LeaderController>::iterator it = ObjectList<LeaderController>::begin(); it; ++it)
301        {
302            //0ptr or not DivisionController?
303            if (!(it) || !((it)->getIdentifier()->getName() == "DivisionController") || !(it->getControllableEntity()))
304                continue;
305            //same team?
306            if ((this->getControllableEntity()->getTeam() != (it)->getControllableEntity()->getTeam()))
307                continue;
308
309            //is equal to this?
310            if (orxonox_cast<ControllableEntity*>(*it) == this->getControllableEntity())
311                continue;
312
313            float distance = CommonController::distance (it->getControllableEntity(), this->getControllableEntity());
314           
315            if (distance < minDistance && !(it->hasFollower()))
316            {
317                closestLeader = *it;
318                minDistance = distance;
319            }
320         
321        }
322        if (closestLeader)
323        {
324            if (closestLeader->setFollower(this))
325                return closestLeader;
326        }
327        return 0;
328    }
329    bool SectionController::setWingman(ActionpointController* wingman)
330    {
331        WingmanController* newWingman = orxonox_cast<WingmanController*>(wingman);
332
333        if (!this->myWingman_)
334        {
335            this->myWingman_ = newWingman;
336            return true;
337        }
338        else
339        {
340            return false;
341        }
342    }
343   
344    bool SectionController::hasWingman()
345    {
346        if (this->myWingman_)
347            return true;
348        else
349            return false;
350    }
351}
Note: See TracBrowser for help on using the repository browser.