#ifndef SCRIPTABLE_CONTROLLER_API_H #define SCRIPTABLE_CONTROLLER_API_H #include #include "core/CoreIncludes.h" #include "tools/Timer.h" #include "OgreVector3.h" struct lua_State; namespace orxonox { class ScriptableController; class WorldEntity; class Pawn; /** * @brief API for ScriptableController's lua-scripts * * Defines the interface that lua can use in the scripts to communicate with orxonox. * * \sa ScriptableController */ class ScriptableControllerAPI { friend class ScriptableController; public: /** * @brief Constructs the API with the given lua state * @param lua The lua state * @param controller The parent controller * * This will not run any scripts, it'll just make the API visible to lua. */ ScriptableControllerAPI(lua_State *lua, ScriptableController *controller); /** * @brief Destructs the API and closes the lua state. */ ~ScriptableControllerAPI(); // ### API #################################################################### /** * @brief Print a message * @param msg The message * * Use this function instead of printing from lua directly, because that will mess up the * output as it is not synchronized. */ void orxPrint(std::string msg); /** * @brief Register a function that will be called after a timeout * @param callback The function to call after the timeout expired * @param timeout The timeout in seconds */ void registerAfterTimeout(std::function callback, double timeout); /** * @brief Register a function that will be called when two object are close to eachother * @param callback The function to call when the objects are close enough * @param id1 The first object * @param id2 The second object * @param distance If the distance between the two objects is smaller than this value, * the function is called * * Note: Distances are only checked every 0.5s! */ void registerAtNearObject(std::function callback, std::string id1, std::string id2, double distance); /** * @brief Register a function that will be called when an object is close to a certain point * @param callback The function to call when the object is close enough * @param id The object * @param x X-coordinate of the point * @param y Y-coordinate of the point * @param z Z-coordinate of the point * @param distance If the distance between the object and the point is smaller than this value, the * function is called. * * Note: Distances are only checked every 0.5s! */ void registerAtNearPoint(std::function callback, std::string id, double x, double y, double z, double distance); /** * @brief Register a function that will be called when an object enters a cubic area * @param callback The function to call when the object entered the area * @param id The object * @param x X-coordinate of the top-left corner * @param y Y-coordinate of the top-left corner * @param z Z-coordinate of the top-left corner * @param dx Size in X-direction of the cube * @param dy Size in Y-direction of the cube * @param dz Size in Z-direction of the cube * * Note: Distances are only checked every 0.5s! */ void registerAtAreaEnter(std::function callback, std::string id, int x, int y, int z, int dx, int dy, int dz); /** * @brief Register a function that will be called when an object leaves a cubic area * @param callback The function to call when the object left the area * @param id The object * @param x X-coordinate of the top-left corner * @param y Y-coordinate of the top-left corner * @param z Z-coordinate of the top-left corner * @param dx Size in X-direction of the cube * @param dy Size in Y-direction of the cube * @param dz Size in Z-direction of the cube * * Note: Distances are only checked every 0.5s! */ void registerAtAreaLeave(std::function callback, std::string id, int x, int y, int z, int dx, int dy, int dz); /** * @brief Register a function that will be called when a Pawn is killed * @param callback The function to call as soon as the Pawn is dead * @param id The Pawn * * Note: Once a Pawn is dead, the callback is removed, even if the pawn got magically revived. */ void registerAtPawnKilled(std::function callback, std::string id); /** * @brief Register a function that will be called when a Pawn is hit * @param callback The function to call as soon as the Pawn is hit * @param id The Pawn * * Note: Once a Pawn is dead, the all hit-callbacks are removed, even if the pawn got magically revived. */ void registerAtPawnHit(std::function callback, std::string id); /** * @brief Kill a pawn * @param id The pawn to kill * * Note: It might up to 0.5s until the pawn is actually killed. */ void killPawn(std::string id); /** * @brief Spawn an object * @param type Name of the class of the object you want to spawn * @param id The newly created ID that can be used to access this object * * IMPORTANT: Do not use this function yet, it only has minimal functionality and is not * really helpful as it is. */ void spawn(std::string type, std::string id); void spawnTest(std::string id); /** * @brief Set the position of an object * @param id The ID of the object * @param x The position on the x-axis * @param y The position on the y-axis * @param z The position on the z-axis */ void setPosition(std::string id, double x, double y, double z); /** * @brief Set the orientation of an object * @param id The ID of the object * @param x The x component of the axis vector * @param y The y component of the axis vector * @param z The z component of the axis vector * @param angle The angle around the axis * * To set the orientation, you have to specify the direction that the * object should be facing with the vector (x, y, z) and the rotation * of the object around this axis with 'angle', which has to be given * in degrees, NOT radian. The vector does not have to be normalized. */ void setOrientation(std::string id, double x, double y, double z, double angle); /** * @brief Set the velocity of an object * @param id The ID of the object * @param x The velocity in x-direction * @param y The velocity in y-direction * @param z The velocity in z-direction * * The velocity is in units per second. */ void setVelocity(std::string id, double x, double y, double z); /** * @brief Set the angular velocity of an object * @param id The ID of the object * @param x The rotation velocity around the x-axis * @param y The rotation velocity around the y-axis * @param z The rotation velocity around the z-axis */ void setAngularVelocity(std::string id, double x, double y, double z); /** * @brief Set the angular velocity of an object * @param id The ID of the object * @param x The rotation velocity around the x-axis * @param y The rotation velocity around the y-axis * @param z The rotation velocity around the z-axis */ double myTestFunction(double x, double y); void moveControllableEntity(std::string id, double x, double y, double z); // ### API END ################################################################ private: /** * @brief Groups everything together that is needed to handle a near-object event */ struct NearObjectHandler { NearObjectHandler(WorldEntity *entity1, WorldEntity *entity2, std::string id1, std::string id2, double distance, std::function callback) : entity1_(entity1), entity2_(entity2), id1_(id1), id2_(id2), distance_(distance), callback_(callback) {} WorldEntity *entity1_, *entity2_; std::string id1_, id2_; double distance_; std::function callback_; }; /** * @brief Groups everything together that is needed to handle a near-poinb event */ struct NearPointHandler { NearPointHandler(WorldEntity *entity, std::string id, double x, double y, double z, double distance, std::function callback) : entity_(entity), id_(id), point_(x, y, z), distance_(distance), callback_(callback) {} WorldEntity *entity_; std::string id_; Vector3 point_; double distance_; std::function callback_; }; /** * @brief Groups everything together that is needed to handle an area enter/leave event */ struct AreaHandler { AreaHandler(WorldEntity *entity, std::string id, double x, double y, double z, double dx, double dy, double dz, bool atEnter, std::function callback) : entity_(entity), id_(id), start_point_(x, y, z), atEnter_(atEnter), callback_(callback) { this-> end_point_ = this->start_point_ + Vector3(dx, dy, dz); } WorldEntity *entity_; std::string id_; Vector3 start_point_, end_point_; bool atEnter_; std::function callback_; }; lua_State *lua_; ScriptableController *controller_; std::list nearObjectHandlers_; std::list nearPointHandlers_; std::list areaHandlers_; std::map > > pawnDestroyedHandlers_; std::map > > pawnHitHandlers_; Timer periodicTimer; static const double periodic_interval; /** * @brief Called by ScriptableController when a pawn is killed * @param id The dead pawn * * Calls the lua callbacks associated with this event. */ void pawnKilled(std::string id, Pawn *pawn); /** * @brief Called by ScriptableController when a Pawn is hit * @param target_id The hit Pawn * @param source_id The shooting Pawn * @param new_health The new health of the hit Pawn * @param new_shield The new shield health of the hit Pawn */ void pawnHit(std::string target_id, std::string source_id, double new_health, double new_shield); /** * @brief Called every 0.5s * * This handles things that have to be checked periodically (like area events) * but doing this in every tick would be an overkill. */ void periodic(void); }; } #endif // SCRIPTABLE_CONTROLLER_API_H