Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

finished copyOrientation function. Now ships move smoothly

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