Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10877 was 10877, checked in by gania, 8 years ago

CommonController now has static methods only. Replace with a namespace?

File size: 11.7 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            ControllableEntity* myEntity = this->getControllableEntity();
86            Vector3 myPosition = myEntity->getWorldPosition();
87            if (!this->myDivisionLeader_)
88            {
89                return;
90            }
91            ControllableEntity* leaderEntity = this->myDivisionLeader_->getControllableEntity();
92            Quaternion orient = leaderEntity->getWorldOrientation();
93            Vector3 leaderPosition = leaderEntity->getWorldPosition();
94
95            Vector3 targetRelativePosition = getFormationPosition();
96            if (!this->myDivisionLeader_)
97            {
98                return;
99            }
100            Vector3 targetAbsolutePosition = 
101                (leaderPosition + (orient*WorldEntity::FRONT) * (leaderEntity->getVelocity().length()/5)
102                 + (orient* (targetRelativePosition)));
103       
104            this->setAction (Action::FLY, targetAbsolutePosition, orient);
105            if ((targetAbsolutePosition - myPosition).length() > this->tolerance_ * 1.5f)
106            {
107                this->boostControl();
108            }
109            else
110            {
111               this->getControllableEntity()->boost(false);
112            }
113        }   
114        SUPER(SectionController, tick, dt);
115    }
116
117    void SectionController::action()
118    {
119        if (!this || !this->getControllableEntity())
120            return;
121
122        //----If no leader, find one---- 
123        if (!myDivisionLeader_)
124        {
125            LeaderController* newDivisionLeader = findNewDivisionLeader();
126            this->myDivisionLeader_ = newDivisionLeader;
127
128        }
129        //----If have leader----
130        else
131        {
132        }
133        if (!myDivisionLeader_)
134        {
135           
136            ActionpointController::action();
137            if (!this || !this->getControllableEntity())
138                return;
139            if (!(this->parsedActionpoints_.empty() && this->loopActionpoints_.empty()))
140            {
141                if (this->myWingman_)
142                {
143                    this->myWingman_->takeActionpoints(this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
144                }   
145            }
146        }
147        else if (myDivisionLeader_)
148        {
149            switch (myDivisionLeader_->getAction())
150            {
151                case Action::FIGHT:
152                {
153                    if (!this->hasTarget())
154                    {
155                        this->chooseTarget();
156                    }
157                    break;
158                }
159                case Action::FIGHTALL:
160                {
161                    if (!this->hasTarget())
162                    {
163                        this->chooseTarget();
164                    }
165                    break;
166                }
167                case Action::ATTACK:
168                {
169                    if (!this->hasTarget())
170                    {
171                        this->chooseTarget();
172                    }
173                    break;
174                }
175                default:
176                {
177                    //formation flight is executed in tick
178                }
179            }
180            if (this->hasTarget())
181            {
182                //----choose where to go----
183                this->maneuver();
184                //----fire if you can----
185                this->bShooting_ = this->canFire();               
186            }
187        }
188     
189    }
190
191   
192    //PRE: myDivisionLeader_ != 0 && myDivisionLeader_->action_ == Action::FIGHT
193    //POST: this->target_ is set unless division leader doesn't have one
194    void SectionController::chooseTarget()
195    {
196        //----If division leader fights, cover him by fighting emenies close to his target----
197        Action::Value action = this->myDivisionLeader_->getAction();
198       
199        Pawn* target;
200        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
201        {
202            //----if he has a target----
203            if (this->myDivisionLeader_->hasTarget())
204            {
205                //----try to find a new target if division leader has wingman (doing fine) and no good target already set----
206                if ( this->myDivisionLeader_->hasWingman() && 
207                    !( this->hasTarget() && this->getTarget() != this->myDivisionLeader_->getTarget() ) )
208                {
209
210                    bool foundTarget = false;
211                    //----new target should be close to division's target----
212                    Vector3 divisionTargetPosition = this->myDivisionLeader_->getTarget()->getWorldPosition();
213                    Gametype* gt = this->getGametype();
214                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
215                    {
216                        //----is enemy?----
217                        if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
218                            continue;           
219                        //----in range?----
220                        if (((*itP)->getWorldPosition() - divisionTargetPosition).length() < 3000 && 
221                            (*itP) != this->myDivisionLeader_->getTarget())
222                        {
223                            foundTarget = true;
224                            target =  (*itP);
225                            //orxout(internal_error) << "Found target" << endl;
226                            break; 
227                        }
228                    }
229                    //----no target? then attack same target as division leader----
230                    if (!foundTarget)
231                    {
232                        target = orxonox_cast<Pawn*>(this->myDivisionLeader_->getTarget());
233                    }
234                }
235                //----if division leader doesn't have a wingman, support his fire----
236                else
237                {
238                    target = orxonox_cast<Pawn*>(this->myDivisionLeader_->getTarget());
239                }
240            }
241            //----If he fights but doesn't have a target, wait for him to get one----
242            else
243            {
244
245            }
246            this->setTarget (orxonox_cast<ControllableEntity*>(target));
247        }
248        else
249        {
250        } 
251    }
252    Vector3 SectionController::getFormationPosition ()
253    {
254        this->setFormationMode( this->myDivisionLeader_->getFormationMode() );
255        Vector3* targetRelativePosition;
256        switch (this->formationMode_){
257            case FormationMode::WALL:
258            {
259                targetRelativePosition = new Vector3 (-2*this->spread_, 0, 0);   
260                break;
261            }
262            case FormationMode::FINGER4: 
263            {
264                targetRelativePosition = new Vector3 (-2*this->spread_, 0, this->spread_);   
265                break;
266            }
267           
268            case FormationMode::DIAMOND: 
269            {
270                targetRelativePosition = new Vector3 (-2*this->spread_, 0, this->spread_);                   
271                break;
272            }
273        }
274        return *targetRelativePosition;
275    }
276
277   
278
279    LeaderController* SectionController::findNewDivisionLeader()
280    {
281
282        if (!this->getControllableEntity())
283            return 0;
284
285        LeaderController* closestLeader = 0;
286        float minDistance =  std::numeric_limits<float>::infinity();
287        //go through all pawns
288        for (ObjectList<LeaderController>::iterator it = ObjectList<LeaderController>::begin(); it; ++it)
289        {
290            //0ptr or not DivisionController?
291            if (!(it) || !((it)->getIdentifier()->getName() == "DivisionController") || !(it->getControllableEntity()))
292                continue;
293            //same team?
294            if ((this->getControllableEntity()->getTeam() != (it)->getControllableEntity()->getTeam()))
295                continue;
296
297            //is equal to this?
298            if (orxonox_cast<ControllableEntity*>(*it) == this->getControllableEntity())
299                continue;
300
301            float distance = CommonController::distance (it->getControllableEntity(), this->getControllableEntity());
302           
303            if (distance < minDistance && !(it->hasFollower()))
304            {
305                closestLeader = *it;
306                minDistance = distance;
307            }
308         
309        }
310        if (closestLeader)
311        {
312            if (closestLeader->setFollower(this))
313                return closestLeader;
314        }
315        return 0;
316    }
317    bool SectionController::setWingman(ActionpointController* wingman)
318    {
319        WingmanController* newWingman = orxonox_cast<WingmanController*>(wingman);
320
321        if (!this->myWingman_)
322        {
323            this->myWingman_ = newWingman;
324            return true;
325        }
326        else
327        {
328            return false;
329        }
330    }
331   
332    bool SectionController::hasWingman()
333    {
334        if (this->myWingman_)
335            return true;
336        else
337            return false;
338    }
339}
Note: See TracBrowser for help on using the repository browser.