Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Zombie can now approach, tried to add waves

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