Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/controllers/ScriptController.cc @ 11810

Last change on this file since 11810 was 11083, checked in by muemart, 9 years ago

Fix some clang-tidy warnings.
Also, Serialise.h was doing some C-style casts that ended up being const casts. I moved those const casts as close to the source as possible and changed the loadAndIncrease functions to not do that.

  • Property svn:eol-style set to native
File size: 12.2 KB
RevLine 
[10014]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:
[10622]23 *      ...
[10014]24 *   Co-authors:
25 *      ...
26 *
27 */
28
[10622]29 /*
30  * Currently available lua commands:
31  *
32  * IMPORTANT: ALL COMMANDS DO REQUIRE 7 PARAMETERS TO BE PROVIDED. FILL UP WITH ZEROES IN UNIMPORTANT PLACES.
33  *
34  * Command             | Abbreviation | Parameter 1          | '' 2     | '' 3    | '' 4                 | '' 5     | '' 6     | '' 7
35  *
36  * "Move And Look"     | mal          | GoTo X Coordinate    | '' Y ''  | '' Z '' | LookAt X Coordinate  |  '' Y '' |  '' Y '' | Duration
37  * "Rotate And Look"   | ral          | GoTo X Coordinate    | '' Y ''  | '' Z '' | Axis (1=x, 2=z, 3=z) |     -    |     -    | Duration
38  * "Spiral"            | spi          | GoTo X Coordinate    | '' Y ''  | '' Z '' |          -           |     -    |     -    | Duration
39  * "Transition Look"   | chl          | From X Coordinate    | '' Y ''  | '' Z '' | To X Coordinate      |  '' Y '' |  '' Y '' | Duration
40  * "Idle (Do nothing)" | idle         | Duration
41  */
42
[10014]43#include "ScriptController.h"
[10047]44#include "infos/PlayerInfo.h"
[10014]45#include "core/CoreIncludes.h"
[10028]46#include "worldentities/ControllableEntity.h"
[10045]47#include "core/LuaState.h"
[10622]48#include "core/LuaState.h"
49#include "util/Math.h"
[10014]50
51namespace orxonox
52{
53    RegisterClass(ScriptController);
54
[10028]55    ScriptController::ScriptController(Context* context) : ArtificialController(context)
[10014]56    {
57        RegisterObject(ScriptController);
[10065]58
59        /* By default, this controller has ID 0, which means it is not assigned
60         * to anything yet.
61         */
[10047]62        this->ctrlid_ = 0;
[10065]63
64        /* Set default values for all variables */
65        /* - pointers to zero */
[11071]66        this->player_ = nullptr;
67        this->entity_ = nullptr;
[10065]68
69        /* - times */
70        this->scTime = 0.0f;
71        this->eventTime = 0.0f;
72
73        /* - Points in space */
74        this->startpos = Vector3(0,0,0);
[10066]75        //this->lookAtPosition = Vector3(0,0,0);
[10065]76
77        /* - Processing flag */
78        this->processing = false;
79
80        /* - Counters */
81        this->eventno = 0;
82
[10622]83        /* - First "previous event" scheduled at t=0 */
84        /* - Needed for automatically updating event times */
85        this->prevEventTime = 0;
[10014]86    }
87
[10047]88    void ScriptController::takeControl(int ctrlid)
[10014]89    {
[10065]90        /* Output some debugging information */
[10077]91        orxout(verbose) << "ScriptController: Taking control" << endl;
92        orxout(verbose) << "This-pointer: " << this << endl;
[10065]93
94        /* Set the controller ID (the argument here should be nonzero) */
[10047]95        this->ctrlid_ = ctrlid;
[10065]96
97        /* Store the entity pointer in a private variable */
[10047]98        this->entity_ = this->player_->getControllableEntity();
99        assert(this->entity_);
[10065]100         
101        /* Add the controller here to this entity. Apparently this still leaves
102         * any preexisting human controllers in place.
103         */
[10047]104        this->entity_->setDestroyWhenPlayerLeft(false);
105        this->player_->pauseControl();
106        this->entity_->setController(this);
107        this->setControllableEntity(this->entity_);
[10065]108        this->entity_->mouseLook();
109        this->entity_->setVisible(false);
[10014]110    }
111
[10034]112    const Vector3& ScriptController::getPosition()
[10020]113    {
[10065]114      return this->entity_->getPosition();
[10028]115    }
[10014]116
[10045]117    ScriptController* ScriptController::getScriptController()
118    {
[10046]119      /* Output a message that confirms this function was called */
[10077]120      orxout(verbose) << "Great success!" << std::endl;
[10046]121
[10047]122      /* Debugging: print all the scriptcontroller object pointers */
[11071]123      for(ScriptController* controller : ObjectList<ScriptController>())
124      { orxout(verbose) << "Have object in list: " << controller << endl; }
[10047]125
126      /* Find the first one with a nonzero ID */
[11071]127      for(ScriptController* controller : ObjectList<ScriptController>())
[10045]128      { 
129        // TODO: do some selection here. Currently just returns the first one
[11071]130        if( controller->getID() > 0 )
131        { orxout(verbose) << "Controller to return: " << controller << endl;
132          return controller;
[10065]133        }
[10045]134     
135      }
[11071]136      return nullptr;
[10045]137    }
138
[10048]139    void ScriptController::execute(event ev)
140    {
[10066]141        /* Debugging output */
142        //orxout() << "Executing event " << ev.fctName
143          //<< " with parameters:\n "
144          //<< ev.x1 << " " << ev.y1 << " " << ev.z1 << "\n"
145          //<< ev.x2 << " " << ev.y2 << " " << ev.z2 << "\n"
146          //<< ev.duration << endl;
[10057]147
[10066]148        /* Event is starting, hence set the time to 0 */
[10065]149        this->eventTime = 0.0f;
150        this->processing = true;
151
[10066]152        /* Copy the event into the currentEvent holder */
153        this->currentEvent = ev;
154
155        /* Store starting position */
156        this->startpos = this->entity_->getPosition();
[10048]157    }
158
159
[10047]160    void ScriptController::tick(float dt)
161    {
[10065]162        /* Call the tick function of the classes we derive from */
163        SUPER(ScriptController, tick, dt);
[10059]164
[10047]165        /* If this controller has no entity entry, do nothing */
[10066]166        if( !(this->entity_) ) return;
[10045]167
[10065]168        /* See if time has come for the next event to be run */
169        if(this->eventList.size() > 0 && this->eventList[0].eventTime <= scTime)
[10066]170        { /* Execute the next event on the list */
[10065]171          this->execute(this->eventList[0]);
172          this->eventList.erase(this->eventList.begin());
173          this->eventno -= 1;
174        }
[10048]175
[10065]176        /* Update the local timers in this object */
[10066]177        scTime += dt; eventTime += dt;
[10065]178
179        /* If we've arrived at the target, stop processing */
[10066]180        if( eventTime > currentEvent.duration && this->processing == true)
[10065]181        { this->processing = false;
182
[10066]183          /* If we reached the last event, also reenable the normal movement
184           * and make the model visible again
185           */
[10065]186          if( this->eventno == 0 )
187          {
188            this->entity_->mouseLook();
189            this->entity_->setVisible(true);
190          }
[10048]191        }
192
[10065]193        /* Get a variable that specifies how far along the trajectory
[10622]194         * we are currently.
[10065]195         */
[10066]196        float dl = eventTime / currentEvent.duration; 
[10048]197
[10622]198        /* Depending on command */
[10065]199        /* Do some moving */
200        if( this->processing )
[10622]201        {
202          // Abbreviation for "spiral" (rotation + translation)
203          if (this->currentEvent.fctName == "spi") {
204
205            // Need to know a perpendicular basis to the translation vector:
206            // Given (a, b, c) we chose (b, -a, 0)norm and (0, c, -b)norm
207            // Currently we set a fix rotational radius of 400
208            // TODO: Add an option to adjust radius of spiral movement
209            Vector3 direction = this->currentEvent.v1 - startpos;
210
211            Vector3* ortho1 = new Vector3(direction.y, -direction.x, 0);
212            float absOrtho1 = sqrt(direction.y * direction.y + direction.x * direction.x);
213            *ortho1 = 400 * cos(2 * math::pi * dl) * (*ortho1)/absOrtho1;
214
215            Vector3* ortho2 = new Vector3(0, direction.z, -direction.y);
216            float absOrtho2 = sqrt(direction.y * direction.y + direction.z * direction.z);
217            *ortho2 = 400 * sin(2 * math::pi * dl) * (*ortho2)/absOrtho2;
218
219            this->entity_->setPosition( (1-dl)*startpos + dl * this->currentEvent.v1 + *ortho1 + *ortho2);
220
221            delete ortho1;
222            delete ortho2;
223          }
224
225          // Abbreviation for "rotate and look"
226          if (this->currentEvent.fctName == "ral")
227          { 
228            // Specify the axis
[11083]229            Vector3 a;
[10622]230              switch ((int) currentEvent.d) {
231                case 3:
[11083]232                  a = Vector3(this->currentEvent.v1.x + this->currentEvent.e*cos(2*math::pi*dl),
[10622]233                                  this->currentEvent.v1.y + this->currentEvent.e*sin(2*math::pi*dl),
234                                  this->currentEvent.v1.z);
235                break;
236                case 2:
[11083]237                  a = Vector3(this->currentEvent.v1.x + this->currentEvent.e*sin(2*math::pi*dl),
[10622]238                                  this->currentEvent.v1.y,
239                                  this->currentEvent.v1.z + this->currentEvent.e*cos(2*math::pi*dl));
240                break;
241                case 1:
[11083]242                  a = Vector3(this->currentEvent.v1.x,
[10622]243                                  this->currentEvent.v1.y + this->currentEvent.e*sin(2*math::pi*dl),
244                                  this->currentEvent.v1.z + this->currentEvent.e*cos(2*math::pi*dl));
245                break;
246              }
247
[11083]248            this->entity_->setPosition(a);
[10622]249
250            /* Look at the specified position */
251            this->entity_->lookAt(this->currentEvent.v1);
252          }
253          else if( this->currentEvent.fctName == "mal" )
[10066]254          {
255            /* Set the position to the correct place in the trajectory */
256            this->entity_->setPosition( (1-dl)*startpos + dl * this->currentEvent.v1);
[10047]257
[10066]258            /* Look at the specified position */
259            this->entity_->lookAt(this->currentEvent.v2);
260          }
261          else if( this->currentEvent.fctName == "chl" )
262          {
263            /* Sweep the look from v1 to v2 */
264            this->entity_->lookAt( (1-dl)*this->currentEvent.v1 + 
265              dl * this->currentEvent.v2 );
266          }
267
268
[10065]269          /* Force mouse look */
270          if( this->entity_->isInMouseLook() == false )
271            this->entity_->mouseLook();
272        }
273    }
[10048]274
[10065]275    void ScriptController::eventScheduler(std::string instruction, 
276      float x1, float y1, float z1, 
277      float x2, float y2, float z2, 
278      float duration, float executionTime)
[10048]279    {
[10065]280      /* put data (from LUA) into time-sorted eventList*/ 
281      /* Nimmt den befehl und die argumente aus luascript und ertellt einen
282       * struct pro event, diese structs werden sortiert nach eventTime
283       */
284      struct event tmp;
[10057]285
[10065]286      /* Fill the structure with all the provided information */
287      tmp.fctName = instruction;
[10622]288
[10066]289      //tmp.x1 = x1; tmp.y1 = y1; tmp.z1 = z1;
290      //tmp.x2 = x2; tmp.y2 = y2; tmp.z2 = z2;
291      tmp.v1 = Vector3(x1,y1,z1);
292      tmp.v2 = Vector3(x2,y2,z2);
[10622]293
294      // the parameters are not required to be vector coordinates!
295      // for convenience they are however stored twice if they have some kind of different meaning
296      tmp.a = x1;
297      tmp.b = y1;
298      tmp.c = z1;
299      tmp.d = x2;
300      tmp.e = y2;
301      tmp.f = z2;
302
[10065]303      tmp.duration = duration;
[10059]304
[10622]305      /* This is kind of a hack. If we hit the function idle all we want to do is
306         advance event execution time, not schedule anything */
307      if (instruction == "idle") {
308        tmp.eventTime = this->prevEventTime;
309        this->prevEventTime += x1;
310        return;
311      } else {
312        tmp.eventTime = this->prevEventTime;
313        this->prevEventTime += duration;
314      }
[10047]315
[10065]316      /* Add the created event to the event list */
317      if(eventList.size()==0)
318      { /* The list is still empty, just add it */
[10077]319        orxout(verbose) << "eventList empty (01)" << endl;
[10065]320        eventList.insert(eventList.begin(), tmp);
321        this->eventno += 1;
322        return; /* Nothing more to do, the event was added */
323      }
[10059]324
[10065]325      /* Event was not added yet since the list was not empty. Walk through
326       * the list of events and add it so that the events are correctly in
327       * order.
328       */
329      for (std::vector<event>::iterator it=eventList.begin(); it<eventList.end(); it++)
330      { if(tmp.eventTime < it->eventTime)
331        { eventList.insert(it,tmp);
332          this->eventno += 1;
[10076]333          //orxout()<<"new event added"<<endl;
[10065]334          return;
[10059]335        }
[10065]336      }
[10034]337
[10065]338      /* If the event was still not added here, it belongs in the end of the list */
339      eventList.insert(eventList.end(), tmp);
340      this->eventno += 1;
[10059]341
[10048]342    }
[10014]343}
Note: See TracBrowser for help on using the repository browser.