Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/SciptableControllerFS15/src/orxonox/controllers/ScriptController.cc @ 10448

Last change on this file since 10448 was 10448, checked in by rgraczyk, 9 years ago

Various changes, see comments in cpp file

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