diff --git a/luprex/core/cpp/animqueue.cpp b/luprex/core/cpp/animqueue.cpp index 3767bcae..b1f57cae 100644 --- a/luprex/core/cpp/animqueue.cpp +++ b/luprex/core/cpp/animqueue.cpp @@ -22,14 +22,114 @@ void AnimQueue::set_size_limit(int n) { size_limit_ = n; } -void AnimQueue::add(int64_t id, const std::string &action) { - steps_.emplace_back(); - AnimStep &last = steps_.back(); - last = steps_[steps_.size() - 2]; - last.id_ = id; - last.action_ = action; - last.bits_ = 0; +void AnimQueue::add(int64_t id, lua_State *L, int idx) { + LuaSpecial tab(idx); + LuaVar value; + LuaStack LS(L, value); + if (!LS.istable(tab)) { + luaL_error(L, "animation spec must be a table"); + } + AnimStep step = steps_.back(); + step.id_ = id; + step.bits_ = 0; + step.action_ = ""; + + LS.rawget(value, tab, "action"); + if (!LS.isstring(value)) { + luaL_error(L, "animation action is not optional and must be a string"); + } + step.action_ = LS.ckstring(value); + + LS.rawget(value, tab, "facing"); + if (LS.isnumber(value)) { + step.facing_ = LS.cknumber(value); + step.bits_ |= AnimStep::HAS_FACING; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation facing must be a number"); + } + + LS.rawget(value, tab, "x"); + if (LS.isnumber(value)) { + step.xyz_.x = LS.cknumber(value); + step.bits_ |= AnimStep::HAS_XYZ; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation X coordinate must be a number"); + } + + LS.rawget(value, tab, "y"); + if (LS.isnumber(value)) { + step.xyz_.y = LS.cknumber(value); + step.bits_ |= AnimStep::HAS_XYZ; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation Y coordinate must be a number"); + } + + LS.rawget(value, tab, "z"); + if (LS.isnumber(value)) { + step.xyz_.z = LS.cknumber(value); + step.bits_ |= AnimStep::HAS_XYZ; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation Z coordinate must be a number"); + } + + LS.rawget(value, tab, "dx"); + if (LS.isnumber(value)) { + step.xyz_.x += LS.cknumber(value); + step.bits_ |= AnimStep::HAS_XYZ; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation DX offset must be a number"); + } + + LS.rawget(value, tab, "dy"); + if (LS.isnumber(value)) { + step.xyz_.y += LS.cknumber(value); + step.bits_ |= AnimStep::HAS_XYZ; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation DY offset must be a number"); + } + + LS.rawget(value, tab, "dz"); + if (LS.isnumber(value)) { + step.xyz_.z += LS.cknumber(value); + step.bits_ |= AnimStep::HAS_XYZ; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation DZ offset must be a number"); + } + + LS.rawget(value, tab, "graphic"); + if (LS.isstring(value)) { + step.graphic_ = LS.ckstring(value); + step.bits_ |= AnimStep::HAS_GRAPHIC; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation graphic must be a string"); + } + + LS.rawget(value, tab, "plane"); + if (LS.isstring(value)) { + step.plane_ = LS.ckstring(value); + step.bits_ |= AnimStep::HAS_PLANE; + } else if (!LS.isnil(value)) { + luaL_error(L, "animation plane must be a string"); + } + + steps_.push_back(step); + while (int(steps_.size()) > size_limit_) { + steps_.pop_front(); + } + AnimStep &init = steps_.front(); + init.id_ = 0; + init.action_ = ""; + init.bits_ = AnimStep::HAS_EVERYTHING; +} + +void AnimQueue::add(int64_t id, const std::string &action) { + AnimStep step = steps_.back(); + step.id_ = id; + step.action_ = action; + step.bits_ = 0; + + steps_.push_back(step); while (int(steps_.size()) > size_limit_) { steps_.pop_front(); } diff --git a/luprex/core/cpp/animqueue.hpp b/luprex/core/cpp/animqueue.hpp index 516caf27..c2c559dc 100644 --- a/luprex/core/cpp/animqueue.hpp +++ b/luprex/core/cpp/animqueue.hpp @@ -47,7 +47,7 @@ private: int64_t id_; std::string action_; int bits_; - + float facing_; util::XYZ xyz_; std::string graphic_; @@ -84,13 +84,30 @@ public: const AnimStep &nth(int n) const { return steps_[n]; } int size() const { return steps_.size(); } - // Mutators to create new steps. + // Mutators to create new steps from C++ + // void add(int64_t id, const std::string &action); void set_facing(float f); void set_xyz(util::XYZ xyz); void set_graphic(const std::string &g); void set_plane(const std::string &p); + // Mutator to create new steps from lua. + // + // Lua stack must contain a table, which may contain: + // action: "action" + // facing: 0.0 - 360.0 + // x: x-coordinate + // y: y-coordinate + // z: z-coordinate + // dx: delta-x + // dy: delta-y + // dz: delta-z + // graphic: "graphic" + // plane: "plane" + // + void add(int64_t id, lua_State *L, int idx); + // Get the final resting place after all animations are complete. const std::string &get_graphic() const; const std::string &get_plane() const; diff --git a/luprex/core/cpp/world.cpp b/luprex/core/cpp/world.cpp index 11a12a64..e272aa26 100644 --- a/luprex/core/cpp/world.cpp +++ b/luprex/core/cpp/world.cpp @@ -365,17 +365,23 @@ LuaDefine(tangible_xyz, "c") { return LS.result(); } -LuaDefine(tangible_walkto, "c") { - LuaArg tanobj, x, y, z; - LuaStack LS(L, tanobj, x, y, z); +LuaDefine(tangible_plane, "c") { + LuaArg tanobj; + LuaRet plane; + LuaStack LS(L, tanobj, plane); + World *w = World::fetch_global_pointer(L); + Tangible *tan = w->tangible_get(L, tanobj.index()); + LS.set(plane, tan->anim_queue_.get_plane()); + return LS.result(); +} + +LuaDefine(tangible_animate, "c") { + LuaArg tanobj, config; + LuaStack LS(L, tanobj, config); World *w = World::fetch_global_pointer(L); - lua_Number nx = LS.cknumber(x); - lua_Number ny = LS.cknumber(y); - lua_Number nz = LS.cknumber(z); Tangible *tan = w->tangible_get(L, tanobj.index()); int64_t id = w->id_global_pool_.alloc_id_for_thread(L); - tan->anim_queue_.add(id, "walk"); - tan->anim_queue_.set_xyz(util::XYZ(nx, ny, nz)); + tan->anim_queue_.add(id, L, config.index()); tan->update_plane_item(); return LS.result(); } diff --git a/luprex/core/lua/player.lua b/luprex/core/lua/player.lua index a092d1dc..5040e9e9 100644 --- a/luprex/core/lua/player.lua +++ b/luprex/core/lua/player.lua @@ -10,25 +10,24 @@ end function player.action.north(actor, place, dialog) print("Moving north") x,y,z = tangible.xyz(place); - tangible.walkto(place, x, y+1, z); + tangible.animate(place, {action="walk", dy=1}) end function player.action.south(actor, place, dialog) print("Moving south") x,y,z = tangible.xyz(place); - tangible.walkto(place, x, y-1, z); + tangible.animate(place, {action="walk", dy=-1}) end function player.action.east(actor, place, dialog) print("Moving east") x,y,z = tangible.xyz(place); - tangible.walkto(place, x+1, y, z); + tangible.animate(place, {action="walk", dx=1}) end function player.action.west(actor, place, dialog) print("Moving west") x,y,z = tangible.xyz(place) - tangible.walkto(place, x-1, y, z); - wait(0) - print("Moving west again") + tangible.animate(place, {action="walk", dx=-1}) end +