Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/AI_HS15/src/orxonox/controllers/CommonController.cc @ 10759

Last change on this file since 10759 was 10759, checked in by gania, 10 years ago

small fixes

File size: 11.4 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#include "controllers/CommonController.h"
29#include "core/XMLPort.h"
30
31#include "weaponsystem/WeaponMode.h"
32#include "weaponsystem/WeaponPack.h"
33#include "weaponsystem/Weapon.h"
34#include "weaponsystem/WeaponSlot.h"
35#include "weaponsystem/WeaponSlot.h"
36#include "worldentities/pawns/SpaceShip.h"
37
38
39namespace orxonox
40{
41
42    RegisterClass(CommonController);
43    float SPEED = 0.7f;
44    float ROTATEFACTOR = 0.3f;
45
46    CommonController::CommonController(Context* context) : Controller(context)
47    {
48        this->bSetupWorked = false;
49
50        RegisterObject(CommonController);
51    }
52
53
54    CommonController::~CommonController()
55    {
56    }
57
58    void CommonController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
59    {
60        SUPER(CommonController, XMLPort, xmlelement, mode);
61        XMLPortParam(CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode);
62
63    }
64    void CommonController::setFormationModeXML(std::string val)
65    {
66        const std::string valUpper = getUppercase(val);
67        FormationMode::Value value;
68        if (valUpper == "VEE")
69            value = FormationMode::VEE;
70        else if (valUpper == "WALL")
71            value = FormationMode::WALL;
72        else if (valUpper == "FINGER4")
73            value = FormationMode::FINGER4;
74        else if (valUpper == "DIAMOND")
75            value = FormationMode::DIAMOND;
76        else
77            ThrowException(ParseError, std::string("Attempting to set an unknown FormationMode: '") + val + "'.");
78        this->setFormationMode(value);
79       
80    }
81    std::string CommonController::getFormationModeXML()
82    {
83        switch (this->formationMode_)
84        {
85            case FormationMode::VEE:
86            {
87                return "VEE";
88                break;
89            }
90            case FormationMode::WALL:
91            {
92                return "WALL";
93                break;
94            }
95            case FormationMode::FINGER4:
96            {
97                return "FINGER4";
98                break;
99            }
100            case FormationMode::DIAMOND:
101            {
102                return "DIAMOND";
103                break;
104            }
105            default:
106                return "DIAMOND";
107                break;
108
109        }
110    }
111
112    bool CommonController::setWingman (CommonController* wingman)
113    {
114        return false;
115    }
116   
117    bool CommonController::hasWingman()
118    {
119        return true;
120    }
121    void CommonController::setTarget(ControllableEntity* target)
122    {
123        this->target_ = target;
124        orxout (internal_error) << " TARGET SET " << endl;
125        if (target)
126            this->targetPosition_ = target->getPosition();
127    }
128
129
130
131    void CommonController::setTargetPosition(const Vector3& target)
132    {
133        this->targetPosition_ = target;
134        this->bHasTargetPosition_ = true;
135    }
136
137    void CommonController::setTargetOrientation(const Quaternion& orient)
138    {
139        this->targetOrientation_=orient;
140        this->bHasTargetOrientation_=true;
141    }
142
143    void CommonController::setTargetOrientation(ControllableEntity* target)
144    {
145        if (target)
146            setTargetOrientation(target->getOrientation());
147    }
148
149    /*void CommonController::spin()
150    {
151        this->moveToTargetPosition();
152        this->getControllableEntity()->rotateRoll(8.0f);
153    }
154    void CommonController::turn180()
155    {
156        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
157
158        this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
159        this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
160
161        this->getControllableEntity()->moveFrontBack(SPEED);
162    }*/
163
164
165
166    //copy the Roll orientation of given Quaternion.
167    void CommonController::copyOrientation(const Quaternion& orient)
168    {
169        //roll angle difference in radian
170        float diff=orient.getRoll(false).valueRadians()-(this->getControllableEntity()->getOrientation().getRoll(false).valueRadians());
171        while(diff>math::twoPi) diff-=math::twoPi;
172        while(diff<-math::twoPi) diff+=math::twoPi;
173        this->getControllableEntity()->rotateRoll(diff*ROTATEFACTOR);
174    }
175    void CommonController::copyTargetOrientation()
176    {
177        if (bHasTargetOrientation_)
178        {   
179            copyOrientation(targetOrientation_);
180        }
181    }
182
183
184
185
186    void CommonController::moveToTargetPosition()
187    {
188        this->moveToPosition(this->targetPosition_);
189    }
190    void CommonController::moveToPosition(const Vector3& target)
191    {
192        if (!this->getControllableEntity())
193            return;
194        if (this->rank_ == Rank::DIVISIONLEADER)
195            SPEED *= 0.8;
196        if (this->rank_ == Rank::SECTIONLEADER)
197            SPEED *= 0.9;
198       
199        //100 is (so far) the smallest tolerance (empirically found) that can be reached,
200        //with smaller distance spaceships can't reach position and go circles around it instead
201        int tolerance = 60;
202
203        ControllableEntity* entity = this->getControllableEntity();
204        Vector2 coord = get2DViewCoordinates
205            (entity->getPosition(), 
206            entity->getOrientation() * WorldEntity::FRONT, 
207            entity->getOrientation() * WorldEntity::UP, 
208            target);
209
210        float distance = (target - this->getControllableEntity()->getPosition()).length();
211
212        //rotates should be in range [-1,+1], clamp cuts off all that is not
213        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
214        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
215
216       
217        if (distance > tolerance)
218        {
219            //Yaw and Pitch are enough to start facing the target
220            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR * rotateX);
221            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR * rotateY);
222
223            //300 works, maybe less is better
224            if (distance < 400)
225            {
226                //Change roll when close. When Spaceship faces target, roll doesn't affect it's trajectory
227                //It's important that roll is not changed in the process of changing yaw and pitch
228                //Wingmen won't face same direction as Leaders, but when Leaders start moving
229                //Yaw and Pitch will adapt.
230                if (bHasTargetOrientation_)
231                {
232                    copyTargetOrientation();
233                }
234            }
235            this->getControllableEntity()->moveFrontBack(1.2f*SPEED);
236        }
237        else
238        {     
239            bHasTargetPosition_ = false;
240            bHasTargetOrientation_ = false;
241        }
242    }
243
244
245    int CommonController::getFiremode(std::string name)
246    {
247        for (std::map< std::string, int >::iterator it = this->weaponModes_.begin(); it != this->weaponModes_.end(); ++it)
248        {
249            if (it->first == name)
250                return it->second;
251        }
252        return -1;
253    }
254    bool CommonController::isCloseAtTarget(float distance) const
255    {
256        if (!this->getControllableEntity())
257            return false;
258
259        if (!this->target_)
260            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
261        else
262            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
263    }
264    void CommonController::setupWeapons() //TODO: Make this function generic!! (at the moment is is based on conventions)
265    {
266        this->bSetupWorked = false;
267        if(this->getControllableEntity())
268        {
269            Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
270            if(pawn && pawn->isA(Class(SpaceShip))) //fix for First Person Mode: check for SpaceShip
271            {
272                this->weaponModes_.clear(); // reset previous weapon information
273                WeaponSlot* wSlot = 0;
274                for(int l=0; (wSlot = pawn->getWeaponSlot(l)) ; l++)
275                {
276                    WeaponMode* wMode = 0;
277                    for(int i=0; (wMode = wSlot->getWeapon()->getWeaponmode(i)) ; i++)
278                    {
279                        std::string wName = wMode->getIdentifier()->getName();
280                        if(this->getFiremode(wName) == -1) //only add a weapon, if it is "new"
281                            weaponModes_[wName] = wMode->getMode();
282                    }
283                }
284                if(weaponModes_.size())//at least one weapon detected
285                    this->bSetupWorked = true;
286            }//pawn->weaponSystem_->getMunition(SubclassIdentifier< Munition > *identifier)->getNumMunition (WeaponMode *user);
287        }
288    }
289    void CommonController::doFire()
290    {
291          if(!this->bSetupWorked)//setup: find out which weapons are active ! hard coded: laser is "0", lens flare is "1", ...
292        {
293            this->setupWeapons();
294        }
295        else if(this->getControllableEntity() && weaponModes_.size()&&this->bShooting_ && 
296            this->isCloseAtTarget((1 + 2)*1000) && this->isLookingAtTarget(math::pi / 20.0f))
297        {
298            int firemode;
299            float random = rnd(1);//
300            if (this->isCloseAtTarget(130) && (firemode = getFiremode("LightningGun")) > -1 )
301            {//LENSFLARE: short range weapon
302                this->getControllableEntity()->fire(firemode); //ai uses lens flare if they're close enough to the target
303            }
304           
305            else if ((firemode = getFiremode("HsW01")) > -1 ) //LASER: default weapon
306                this->getControllableEntity()->fire(firemode);
307       
308        }
309    }
310    bool CommonController::isLookingAtTarget(float angle) const
311    {
312        if (!this->getControllableEntity())
313            return false;
314
315        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
316    }
317
318    void CommonController::aimAtTarget()
319    {
320        if (!this->target_ || !this->getControllableEntity())
321            return;
322
323        static const float hardcoded_projectile_speed = 750;
324
325        Vector3 aimPosition = getPredictedPosition(this->getControllableEntity()->getWorldPosition(), 
326            hardcoded_projectile_speed, this->target_->getWorldPosition(), this->target_->getVelocity());
327
328        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
329        if (pawn)
330            pawn->setAimPosition(aimPosition);
331    }
332   
333 
334
335}
Note: See TracBrowser for help on using the repository browser.