Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/Boxhead_FS19/src/orxonox/scriptablecontroller/scriptable_controller_api.cc

Last change on this file was 12398, checked in by cwaupoti, 5 years ago

temorary

File size: 22.8 KB
Line 
1
2#include "scriptable_controller_api.h"
3#include "luatb.h"
4#include "scriptable_controller.h"
5#include "tools/Timer.h"
6#include "worldentities/pawns/Pawn.h"
7#include "infos/Bot.h"
8#include "worldentities/pawns/ModularSpaceShip.h"
9//#include "../modules/objects/collisionshapes/SphereCollisionShape.h"
10#include "graphics/Model.h"
11#include "worldentities/pawns/ScriptableControllerDrone.h"
12#include "worldentities/pawns/SpaceShip.h"
13
14
15
16namespace orxonox
17{
18
19    const double ScriptableControllerAPI::periodic_interval = 0.5;
20
21    ScriptableControllerAPI::ScriptableControllerAPI(lua_State *lua, ScriptableController *controller)
22    {
23        this->lua_ = lua;
24        this->controller_ = controller;
25
26        // Haven't found a shorter way yet to write that... We need C++17!
27        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::orxPrint)>::registerFunction<&ScriptableControllerAPI::orxPrint>(this, lua, "orxPrint");
28
29        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAfterTimeout)>::registerFunction<&ScriptableControllerAPI::registerAfterTimeout>(this, lua, "registerAfterTimeout");
30        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtNearObject)>::registerFunction<&ScriptableControllerAPI::registerAtNearObject>(this, lua, "registerAtNearObject");
31        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtNearPoint)>::registerFunction<&ScriptableControllerAPI::registerAtNearPoint>(this, lua, "registerAtNearPoint");
32        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtAreaEnter)>::registerFunction<&ScriptableControllerAPI::registerAtAreaEnter>(this, lua, "registerAtAreaEnter");
33        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtAreaLeave)>::registerFunction<&ScriptableControllerAPI::registerAtAreaLeave>(this, lua, "registerAtAreaLeave");
34        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPawnKilled)>::registerFunction<&ScriptableControllerAPI::registerAtPawnKilled>(this, lua, "registerAtPawnKilled");
35        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPawnHit)>::registerFunction<&ScriptableControllerAPI::registerAtPawnHit>(this, lua, "registerAtPawnHit");
36
37        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setPosition)>::registerFunction<&ScriptableControllerAPI::setPosition>(this, lua, "setPosition");
38        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setOrientation)>::registerFunction<&ScriptableControllerAPI::setOrientation>(this, lua, "setOrientation");
39        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setVelocity)>::registerFunction<&ScriptableControllerAPI::setVelocity>(this, lua, "setVelocity");
40        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setAngularVelocity)>::registerFunction<&ScriptableControllerAPI::setAngularVelocity>(this, lua, "setAngularVelocity");
41
42        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::killPawn)>::registerFunction<&ScriptableControllerAPI::killPawn>(this, lua, "killPawn");
43        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::spawn)>::registerFunction<&ScriptableControllerAPI::spawn>(this, lua, "spawn");
44
45        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::spawnTest)>::registerFunction<&ScriptableControllerAPI::spawnTest>(this, lua, "spawnTest");
46        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::spawnZombie)>::registerFunction<&ScriptableControllerAPI::spawnZombie>(this, lua, "spawnZombie");
47
48
49        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::myTestFunction)>::registerFunction<&ScriptableControllerAPI::myTestFunction>(this, lua, "mytestfunction");
50        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::moveControllableEntity)>::registerFunction<&ScriptableControllerAPI::moveControllableEntity>(this, lua, "moveControllableEntity");
51
52
53
54        this->periodicTimer.setTimer(ScriptableControllerAPI::periodic_interval, true, createExecutor(createFunctor(&ScriptableControllerAPI::periodic, this)), false);
55    }
56
57    ScriptableControllerAPI::~ScriptableControllerAPI()
58    {
59        lua_close(this->lua_);
60    }
61
62    void ScriptableControllerAPI::orxPrint(std::string msg)
63    {
64        orxout(user_info) << msg << std::endl;
65    }
66
67    void ScriptableControllerAPI::registerAfterTimeout(std::function<void (void)> callback, double timeout)
68    {
69        // Kills itself when the timer fires
70        new Timer(timeout, false, callback, true);
71    }
72
73    //void ScriptableControllerAPI::registerPeriodically(std::function<void (void)> callback, double timeout)
74    //{
75    //    // Kills itself when the timer fires
76    //    new Timer(timeout, false, callback, true);
77    //}
78
79    void ScriptableControllerAPI::registerAtNearObject(std::function<void (std::string, std::string)> callback, std::string id1, std::string id2, double distance)
80    {
81        WorldEntity *entity1 = this->controller_->getWorldEntityByID(id1);
82        WorldEntity *entity2 = this->controller_->getWorldEntityByID(id2);
83
84        if(entity1 != nullptr && entity2 != nullptr)
85            this->nearObjectHandlers_.push_front(NearObjectHandler(entity1, entity2, id1, id2, distance, callback));
86    }
87
88    void ScriptableControllerAPI::registerAtNearPoint(std::function<void (std::string)> callback, std::string id, double x, double y, double z, double distance)
89    {
90        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
91
92        if(entity != nullptr)
93            this->nearPointHandlers_.push_front(NearPointHandler(entity, id, x, y, z, distance, callback));
94    }
95
96    void ScriptableControllerAPI::registerAtAreaEnter(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz)
97    {
98        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
99
100        if(entity != nullptr)
101            this->areaHandlers_.push_front(AreaHandler(entity, id, x, y, z, dx, dy, dz, true, callback));
102    }
103
104    void ScriptableControllerAPI::registerAtAreaLeave(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz)
105    {
106        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
107
108        if(entity != nullptr)
109            this->areaHandlers_.push_front(AreaHandler(entity, id, x, y, z, dx, dy, dz, false, callback));
110    }
111
112    void ScriptableControllerAPI::registerAtPawnKilled(std::function<void (std::string)> callback, std::string id)
113    {
114        this->pawnDestroyedHandlers_[id].push_back(callback);
115    }
116
117    void ScriptableControllerAPI::registerAtPawnHit(std::function<void (std::string, std::string, double, double)> callback, std::string id)
118    {
119        this->pawnHitHandlers_[id].push_back(callback);
120    }
121
122    void ScriptableControllerAPI::killPawn(std::string id)
123    {
124        Pawn *pawn = this->controller_->getPawnByID(id);
125        if(pawn == nullptr)
126            orxout(user_warning) << "Trying to kill an unknown pawn" << std::endl;
127        else
128            pawn->kill();
129    }
130
131    void ScriptableControllerAPI::spawn(std::string type, std::string id)
132    {
133        if(this->controller_->getWorldEntityByID(id) != nullptr)
134        {
135            orxout(user_warning) << "Script tried to spawn an object, but an object with the given ID exists already" << std::endl;
136            return;
137        }
138
139        Identifier *identifier = ClassByString(type);
140        if(!identifier)
141        {
142            orxout(user_error) << "Script tried to spawn unknown object" << std::endl;
143            return;
144        }
145
146        if(!identifier->isLoadable())
147        {
148            orxout(user_error) << "Script tried to spawn unloadable object" << std::endl;
149            return;
150        }
151
152        WorldEntity *entity;
153        Identifiable *obj = identifier->fabricate(this->controller_->getWorldEntityByID("Player")->getContext());
154
155        orxout(user_error) << "First hit!" << std::endl;
156
157        if(obj->isA(ClassIdentifier<WorldEntity>::getIdentifier()))
158        {
159            entity = orxonox_cast<WorldEntity*>(obj);
160        }
161        else if(obj->isA(ClassIdentifier<PlayerInfo>::getIdentifier()))
162        {
163            // TODO This does not work yet because somehow the controllable entity is not set
164            // yet at this stage.
165    //        entity = orxonox_cast<PlayerInfo*>(obj)->getControllableEntity();
166
167
168            //use TEMPLATES in the map to define objects that are not present on the map yet
169            return;
170        }
171        else
172        {
173            orxout(user_warning) << "Script tried to spawn an object that is neither a WorldEntity, nor a PlayerInfo" << std::endl;
174           
175            return;
176        }
177
178        orxout(user_error) << "Second hit!" << std::endl;
179
180        if(entity->isA(ClassIdentifier<MobileEntity>::getIdentifier()))
181            this->controller_->registerMobileEntity(id, orxonox_cast<MobileEntity*>(entity));
182
183        if(entity->isA(ClassIdentifier<Pawn>::getIdentifier()))
184            this->controller_->registerPawn(id, orxonox_cast<Pawn*>(entity));
185
186        this->controller_->registerWorldEntity(id, orxonox_cast<WorldEntity*>(entity));
187
188
189        orxout(user_error) << "Third and final hit!" << std::endl;
190
191    }
192
193
194
195
196
197    void ScriptableControllerAPI::spawnTest(std::string id)
198    {
199       
200        if(this->controller_->getWorldEntityByID(id) != nullptr)
201        {
202            orxout(user_warning) << "Script tried to spawn an object, but an object with the given ID exists already" << std::endl;
203            return;
204        }
205       
206
207        Identifier *identifier = ClassByString("ScriptableControllerDrone");
208       
209       
210        if(!identifier)
211        {
212            orxout(user_error) << "Script tried to spawn unknown object" << std::endl;
213            return;
214        }
215
216        if(!identifier->isLoadable())
217        {
218            orxout(user_error) << "Script tried to spawn unloadable object" << std::endl;
219            return;
220        }
221
222       
223
224        WorldEntity *entity;
225        Identifiable *obj = identifier->fabricate(this->controller_->getWorldEntityByID("Player")->getContext());
226
227        orxout(user_status) << "First hit!" << std::endl;
228
229        if(obj->isA(ClassIdentifier<WorldEntity>::getIdentifier()))
230        {
231            orxout(user_status) << "Is WorldEntity!" << std::endl;
232            entity = orxonox_cast<WorldEntity*>(obj);
233        }
234        else if(obj->isA(ClassIdentifier<PlayerInfo>::getIdentifier()))
235        {
236            // TODO This does not work yet because somehow the controllable entity is not set
237            // yet at this stage.
238    //        entity = orxonox_cast<PlayerInfo*>(obj)->getControllableEntity();
239
240            orxout(user_status) << "Is PlayerInfo!" << std::endl;
241
242            //use TEMPLATES in the map to define objects that are not present on the map yet
243            return;
244        }
245        else
246        {
247            orxout(user_warning) << "Script tried to spawn an object that is neither a WorldEntity, nor a PlayerInfo" << std::endl;
248           
249            return;
250        }
251
252
253        if(entity->isA(ClassIdentifier<MobileEntity>::getIdentifier())) {
254            orxout(user_status) << "Is MobileEntity!" << std::endl;
255            this->controller_->registerMobileEntity(id, orxonox_cast<MobileEntity*>(entity));
256        }
257
258        if(entity->isA(ClassIdentifier<Pawn>::getIdentifier())) {
259            orxout(user_status) << "Is Pawn!" << std::endl;
260            this->controller_->registerPawn(id, orxonox_cast<Pawn*>(entity));
261        }
262
263        this->controller_->registerWorldEntity(id, orxonox_cast<WorldEntity*>(entity));
264
265        if(this->controller_->getPawnByID(id) != nullptr) {
266            orxout(user_status) << "Pawn is indeed available!" << std::endl;
267        }
268
269
270
271        ///////////////GOLD!!!!!!!!!!!!!!!////////////////////////
272        Pawn* pawn = this->controller_->getPawnByID(id);
273        //Attach to pawn
274        ScriptableControllerDrone* drone = new ScriptableControllerDrone(pawn->getContext()); // this is neccessary because the projectiles fired need a valid creator for the particlespawner (when colliding against something)
275       
276        drone->addTemplate("ScriptableControllerDroneTemplate"); //ScriptableControllerDroneTemplate spaceshipescort
277
278        Vector3 spawnPosition = pawn->getWorldPosition() + Vector3(30,0,-30);
279        drone->setPosition(spawnPosition);
280        //drone->moveFrontBack(1.0);
281
282
283        orxout(user_status) << "Final hit!" << std::endl;
284    }
285
286    void ScriptableControllerAPI::spawnZombie(std::string id)
287    {
288        Identifier *identifier = ClassByString("SpaceShip");
289
290          if(!identifier)
291        {
292            orxout(user_error) << "Script tried to spawn unknown object" << std::endl;
293            return;
294        }
295
296        if(!identifier->isLoadable())
297        {
298            orxout(user_error) << "Script tried to spawn unloadable object" << std::endl;
299            return;
300        }
301       
302   
303        WorldEntity *entity;
304        Identifiable *obj = identifier->fabricate(this->controller_->getWorldEntityByID("Player")->getContext());
305
306
307
308        orxout(user_status) << "First hit!" << std::endl;
309
310       if(obj->isA(ClassIdentifier<WorldEntity>::getIdentifier()))
311        {
312            orxout(user_status) << "Is WorldEntity!" << std::endl;
313            entity = orxonox_cast<WorldEntity*>(obj);
314        }
315        else if(obj->isA(ClassIdentifier<PlayerInfo>::getIdentifier()))
316        {
317            // TODO This does not work yet because somehow the controllable entity is not set
318            // yet at this stage.
319    //        entity = orxonox_cast<PlayerInfo*>(obj)->getControllableEntity();
320
321            orxout(user_status) << "Is PlayerInfo!" << std::endl;
322
323            //use TEMPLATES in the map to define objects that are not present on the map yet
324            return;
325        }
326        else
327        {
328            orxout(user_warning) << "Script tried to spawn an object that is neither a WorldEntity, nor a PlayerInfo" << std::endl;
329           
330            return;
331        }
332       
333        if(entity->isA(ClassIdentifier<MobileEntity>::getIdentifier())) {
334            orxout(user_status) << "Is MobileEntity!" << std::endl;
335            this->controller_->registerMobileEntity(id, orxonox_cast<MobileEntity*>(entity));
336        }
337
338       
339
340        if(entity->isA(ClassIdentifier<Pawn>::getIdentifier())) {
341            orxout(user_status) << "Is Pawn!" << std::endl;
342            this->controller_->registerPawn(id, orxonox_cast<Pawn*>(entity));
343        }
344       
345        this->controller_->registerWorldEntity(id, orxonox_cast<WorldEntity*>(entity));
346
347
348        ///////////////GOLD!!!!!!!!!!!!!!!////////////////////////
349        Pawn* pawn = this->controller_->getPawnByID(id);
350
351        //Attach to pawn
352        SpaceShip* drone = new SpaceShip(pawn->getContext()); // this is neccessary because the projectiles fired need a valid creator for the particlespawner (when colliding against something)
353       
354        drone->addTemplate("spaceshipzombie"); //ScriptableControllerDroneTemplate spaceshipescort
355
356        Vector3 spawnPosition = pawn->getWorldPosition() + Vector3(500,20,500);
357        drone->setPosition(spawnPosition);
358    }
359
360
361
362    void ScriptableControllerAPI::setPosition(std::string id, double x, double y, double z)
363    {
364        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
365        if(entity == nullptr)
366        {
367            orxout(user_warning) << "Trying to set position of an unknown object" << std::endl;
368            return;
369        }
370
371        const Vector3 &old = entity->getPosition();
372
373        // If one of the values is NaN, don't change that value
374        x = std::isnan(x) ? old.x : x;
375        y = std::isnan(y) ? old.y : y;
376        z = std::isnan(z) ? old.z : z;
377
378        entity->setPosition(x, y, z);
379    }
380
381    void ScriptableControllerAPI::setOrientation(std::string id, double x, double y, double z, double angle)
382    {
383        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
384        if(entity == nullptr)
385        {
386            orxout(user_warning) << "Trying to set orientation of an unknown object" << std::endl;
387            return;
388        }
389
390        Vector3 old_axis;
391        Degree old_angle;
392
393        entity->getOrientation().ToAngleAxis(old_angle, old_axis);
394
395        // If one of the values is NaN, don't change that value
396        x = std::isnan(x) ? old_axis.x : x;
397        y = std::isnan(y) ? old_axis.y : y;
398        z = std::isnan(z) ? old_axis.z : z;
399        angle = std::isnan(x) ? old_angle.valueDegrees() : angle;
400
401
402        entity->setOrientation(Vector3(x, y, z), Degree(angle));
403    }
404
405    void ScriptableControllerAPI::setVelocity(std::string id, double x, double y, double z)
406    {
407        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
408        if(entity == nullptr)
409        {
410            orxout(user_warning) << "Trying to set velocity of an unknown object" << std::endl;
411            return;
412        }
413
414        const Vector3 &old = entity->getVelocity();
415
416        // If one of the values is NaN, don't change that value
417        x = std::isnan(x) ? old.x : x;
418        y = std::isnan(y) ? old.y : y;
419        z = std::isnan(z) ? old.z : z;
420
421        entity->setVelocity(x, y, z);
422    }
423
424    void ScriptableControllerAPI::setAngularVelocity(std::string id, double x, double y, double z)
425    {
426        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
427        if(entity == nullptr)
428        {
429            orxout(user_warning) << "Trying to set angular velocity of an unknown object" << std::endl;
430            return;
431        }
432
433        const Vector3 &old = entity->getAngularVelocity();
434
435        // If one of the values is NaN, don't change that value
436        x = std::isnan(x) ? old.x : x;
437        y = std::isnan(y) ? old.y : y;
438        z = std::isnan(z) ? old.z : z;
439
440        entity->setAngularVelocity(x, y, z);
441    }
442
443    void ScriptableControllerAPI::pawnKilled(std::string id, Pawn *pawn)
444    {
445        for(auto callback : this->pawnDestroyedHandlers_[id])
446            callback(id);
447
448        this->pawnDestroyedHandlers_.erase(id);
449
450        // We need to delete those handlers as well, they're no longer valid
451        auto near_obj_handler = this->nearObjectHandlers_.begin();
452        while(near_obj_handler != this->nearObjectHandlers_.end())
453        {
454            if(near_obj_handler->entity1_ == pawn || near_obj_handler->entity2_ == pawn)
455                near_obj_handler = this->nearObjectHandlers_.erase(near_obj_handler);
456            else
457                near_obj_handler++;
458        }
459
460        auto near_point_handler = this->nearPointHandlers_.begin();
461        while(near_point_handler != this->nearPointHandlers_.end())
462        {
463            if(near_point_handler->entity_ == pawn)
464                near_point_handler = this->nearPointHandlers_.erase(near_point_handler);
465            else
466                near_point_handler++;
467        }
468
469        auto area_handler = this->areaHandlers_.begin();
470        while(area_handler != this->areaHandlers_.end())
471        {
472            if(area_handler->entity_ == pawn)
473                area_handler = this->areaHandlers_.erase(area_handler);
474            else
475                area_handler++;
476        }
477    }
478
479    void ScriptableControllerAPI::pawnHit(std::string target_id, std::string source_id, double new_health, double new_shield)
480    {
481        for(auto callback : this->pawnHitHandlers_[target_id])
482            callback(target_id, source_id, new_health, new_shield);
483    }
484
485    void ScriptableControllerAPI::periodic()
486    {
487        // Near object
488        auto near_obj_handler = this->nearObjectHandlers_.begin();
489        while(near_obj_handler != this->nearObjectHandlers_.end())
490        {
491            if((near_obj_handler->entity1_->getPosition() - near_obj_handler->entity2_->getPosition()).length() < near_obj_handler->distance_)
492            {
493                near_obj_handler->callback_(near_obj_handler->id1_, near_obj_handler->id2_);
494                near_obj_handler = this->nearObjectHandlers_.erase(near_obj_handler);
495            }
496            else
497            {
498                near_obj_handler++;
499            }
500        }
501
502        // Near point
503        auto near_point_handler = this->nearPointHandlers_.begin();
504        while(near_point_handler != this->nearPointHandlers_.end())
505        {
506            if((near_point_handler->entity_->getPosition() - near_point_handler->point_).length() < near_point_handler->distance_)
507            {
508                near_point_handler->callback_(near_point_handler->id_);
509                near_point_handler = this->nearPointHandlers_.erase(near_point_handler);
510            }
511            else
512            {
513                near_point_handler++;
514            }
515        }
516
517        // Areas
518        auto area_handler = this->areaHandlers_.begin();
519        while(area_handler != this->areaHandlers_.end())
520        {
521            if(area_handler->entity_->getPosition() > area_handler->start_point_ &&
522               area_handler->entity_->getPosition() < area_handler->end_point_)
523            {
524                if(area_handler->atEnter_)
525                {
526                    area_handler->callback_(area_handler->id_);
527                    area_handler = this->areaHandlers_.erase(area_handler);
528                }
529                else
530                {
531                    area_handler++;
532                }
533            }
534            else
535            {
536                if(!area_handler->atEnter_)
537                {
538                    area_handler->callback_(area_handler->id_);
539                    area_handler = this->areaHandlers_.erase(area_handler);
540                }
541                else
542                {
543                    area_handler++;
544                }
545            }
546        }
547
548    }
549
550
551    //// TESTTESTTESTTESTTESTTEST
552    double ScriptableControllerAPI::myTestFunction(double x, double y)
553    {
554        double z = x + y;
555        orxout(user_info) << "Result = " << z << endl;
556        return z;
557    }
558
559
560    void ScriptableControllerAPI::moveControllableEntity(std::string id, double x, double y, double z)
561    {
562        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
563       
564        if(entity == nullptr)
565        {
566            orxout(user_warning) << "Trying to move an unknown object" << std::endl;
567            return;
568        }
569
570        Identifier *identifier = ClassByString("ControllableEntity");
571       
572        ControllableEntity *controllable_entity;
573       
574        if(identifier->isA(ClassIdentifier<ControllableEntity>::getIdentifier()))
575        {
576            orxout(user_info) << "Before final cast..."<< endl;
577            controllable_entity = orxonox_cast<ControllableEntity*>(entity);
578            orxout(user_info) << "After final cast..."<< endl;
579            //ATTACHED COLLISION SHAPE is MANDATORY in order to move the entity
580            controllable_entity->moveFrontBack(x);
581            controllable_entity->moveRightLeft(y);
582            controllable_entity->moveUpDown(z);
583            orxout(user_info) << "After move..."<< endl;
584        }
585
586        return;
587       
588    }
589}
Note: See TracBrowser for help on using the repository browser.