diff --git a/src/cfsp/core/manager/CFSPGroupManager.cpp b/src/cfsp/core/manager/CFSPGroupManager.cpp index 7a0af3f..8b1eef0 100644 --- a/src/cfsp/core/manager/CFSPGroupManager.cpp +++ b/src/cfsp/core/manager/CFSPGroupManager.cpp @@ -199,6 +199,7 @@ GROUP_FUNC_FROM_SP(Destroy, Destroy(player, spname, _long, times, interval, true GROUP_FUNC_FROM_SP(Chat, Chat(player, spname, message, true), std::string const& message) GROUP_FUNC_FROM_SP(RunCmd, RunCmd(player, spname, message, true), std::string const& message) GROUP_FUNC_FROM_SP(LookAt, LookAt(player, spname, pos, true), Vec3 const& pos) +GROUP_FUNC_FROM_SP(LookAt, LookAt(player, spname, direction, true), simulated_player::SimPlayer::Direction direction) GROUP_FUNC_FROM_SP(MoveTo, MoveTo(player, spname, pos, speed, true), Vec3 const& pos, float speed) GROUP_FUNC_FROM_SP(NavTo, NavTo(player, spname, pos, speed, true), Vec3 const& pos, float speed) GROUP_FUNC_FROM_SP(Tp, Tp(player, spname, pos, dimId, true), Vec3 pos, std::optional dimId) diff --git a/src/cfsp/core/manager/CFSPManager.h b/src/cfsp/core/manager/CFSPManager.h index 5311a86..3804ab8 100644 --- a/src/cfsp/core/manager/CFSPManager.h +++ b/src/cfsp/core/manager/CFSPManager.h @@ -100,6 +100,8 @@ class CFSPManager { base::OperateResult spStop(Player* player, std::string const& spname, bool nocheck = false); base::OperateResult spInfo(Player* player, std::string const& spname, bool nocheck = false); base::OperateResult spLookAt(Player* player, std::string const& spname, Vec3 const& pos, bool nocheck = false); + base::OperateResult + spLookAt(Player* player, std::string const& spname, simulated_player::SimPlayer::Direction direction, bool nocheck = false); base::OperateResult spInvInfo(Player* player, std::string const& spname, bool nocheck = false); base::OperateResult @@ -222,6 +224,8 @@ class CFSPManager { std::vector groupRunCmd(Player* player, std::string const& gname, std::string const& message); std::vector groupLookAt(Player* player, std::string const& gname, Vec3 const& pos); + std::vector + groupLookAt(Player* player, std::string const& gname, simulated_player::SimPlayer::Direction direction); std::vector groupMoveTo(Player* player, std::string const& gname, Vec3 const& pos, float speed = 4.3f); diff --git a/src/cfsp/core/manager/CFSPSpManager.cpp b/src/cfsp/core/manager/CFSPSpManager.cpp index c3ae6ff..22bb0b6 100644 --- a/src/cfsp/core/manager/CFSPSpManager.cpp +++ b/src/cfsp/core/manager/CFSPSpManager.cpp @@ -328,6 +328,7 @@ base::OperateResult CFSPManager::spInvInfo(Player* player, std::string const& sp SP_ONLINE_FUNC_DEF(Stop, stop()) SP_ONLINE_FUNC_DEF(LookAt, lookAt(pos), Vec3 const& pos) +SP_ONLINE_FUNC_DEF(LookAt, lookAt(direction), simulated_player::SimPlayer::Direction direction) SP_ONLINE_FUNC_DEF(Drop, drop(times, interval), int times, int interval) SP_ONLINE_FUNC_DEF(DropInv, dropInv(times, interval), int times, int interval) diff --git a/src/cfsp/core/simPlayer/SimPlayer.cpp b/src/cfsp/core/simPlayer/SimPlayer.cpp index ecc5591..d1013ff 100644 --- a/src/cfsp/core/simPlayer/SimPlayer.cpp +++ b/src/cfsp/core/simPlayer/SimPlayer.cpp @@ -5,6 +5,7 @@ #include "cfsp/core/fix/CFSPFixManager.h" #include "ll/api/i18n/I18n.h" #include "ll/api/service/Bedrock.h" +#include "mc/deps/core/math/Vec3.h" #include "mc/server/SimulatedPlayer.h" #include "mc/server/sim/ContinuousLookAtPositionIntent.h" #include "mc/server/sim/sim.h" @@ -191,4 +192,44 @@ base::OperateResult SimPlayer::lookAt(Vec3 const& pos) { this->mSimPlayer->mLookAtIntent->mType = sim::ContinuousLookAtPositionIntent(glm::vec3(pos.x, pos.y, pos.z), false); return base::OperateResult::success("manager.success.operate"_tr()); } + +base::OperateResult SimPlayer::lookAt(Direction direction) { + using ll::i18n_literals::operator""_tr; + if (!this->mSimPlayer) [[unlikely]] + return base::OperateResult::error("manager.error.loseSimplayer"_tr()); + if (this->mSimPlayer->isDead()) [[unlikely]] + return base::OperateResult::error("manager.fail.spIsDead"_tr()); + + Vec3 offSet; + switch (direction) { + case Direction::North: + offSet = {0, 0, -1}; + break; + case Direction::South: + offSet = {0, 0, 1}; + break; + case Direction::West: + offSet = {-1, 0, 0}; + break; + case Direction::East: + offSet = {1, 0, 0}; + break; + case Direction::Up: + offSet = {0, 1, 0}; + break; + case Direction::Down: + offSet = {0, -1, 0}; + break; + default: + return base::OperateResult::error("manager.fail.invalidDirection"_tr()); + } + + this->mSaveData.lookAtOffSet = offSet; + this->mSimPlayer->simulateSetBodyRotation( + (float)(atan2(this->mSaveData.lookAtOffSet.z, this->mSaveData.lookAtOffSet.x) * 57.295776) - 90.0f + ); + Vec3 pos = this->mSimPlayer->getEyePos() + offSet; + this->mSimPlayer->mLookAtIntent->mType = sim::ContinuousLookAtPositionIntent(glm::vec3(pos.x, pos.y, pos.z), false); + return base::OperateResult::success("manager.success.operate"_tr()); +} } // namespace coral_fans::cfsp::simulated_player \ No newline at end of file diff --git a/src/cfsp/core/simPlayer/SimPlayer.h b/src/cfsp/core/simPlayer/SimPlayer.h index ddf4240..c4db5ff 100644 --- a/src/cfsp/core/simPlayer/SimPlayer.h +++ b/src/cfsp/core/simPlayer/SimPlayer.h @@ -38,6 +38,9 @@ class SimPlayer { uint getPermission(Player*); base::OperateResult setPermission(Player*, SimPlayerPermission); +public: + enum class Direction : int { North, South, West, East, Up, Down }; + public: CFSP_API void cancelTask(); CFSP_API void cancelScript(); @@ -48,6 +51,7 @@ class SimPlayer { CFSP_API base::OperateResult despawn(); CFSP_API base::OperateResult respawn(); CFSP_API base::OperateResult lookAt(Vec3 const& pos); + CFSP_API base::OperateResult lookAt(Direction direction); CFSP_API base::OperateResult info(); public: diff --git a/src/cfsp/entrance/command/GroupCommand.cpp b/src/cfsp/entrance/command/GroupCommand.cpp index d8a9544..fc02016 100644 --- a/src/cfsp/entrance/command/GroupCommand.cpp +++ b/src/cfsp/entrance/command/GroupCommand.cpp @@ -430,6 +430,35 @@ void ComandManager::registerGroupComand() { for (auto perRes : res) perRes.output(output); }); + // sp g lookat + ll ::command ::CommandRegistrar ::getInstance(false).tryRegisterRuntimeEnum( + "cfspFacing", + { + {"north", 0}, + {"south", 1}, + {"west", 2}, + {"east", 3}, + {"up", 4}, + {"down", 5} + } + ); + this->command->runtimeOverload() + .text("g") + .text("lookat") + .required("gname", ll::command::ParamKind::SoftEnum, "cfspGroup") + .required("facing", ll::command::ParamKind::Enum, "cfspFacing") + .execute([this](CommandOrigin const& origin, CommandOutput& output, ll::command::RuntimeCommand const& self) { + auto player = this->tryGetPlayer(origin); + if (!player.has_value()) return output.error("command.fail.illegalOrigin"_tr()); + std::vector res; + res = manager::CFSPManager::getInstance().groupLookAt( + player.value(), + self["gname"].get(), + static_cast(self["facing"].get().index) + ); + for (auto perRes : res) perRes.output(output); + }); + // sp g [pos: Vec3] [speed: float] ll::command::CommandRegistrar::getInstance(false).tryRegisterRuntimeEnum( "cfspGroupOperate7", diff --git a/src/cfsp/entrance/command/SpCommand.cpp b/src/cfsp/entrance/command/SpCommand.cpp index 1c9c96b..b7a5d8d 100644 --- a/src/cfsp/entrance/command/SpCommand.cpp +++ b/src/cfsp/entrance/command/SpCommand.cpp @@ -468,6 +468,35 @@ void ComandManager::registerSpComand() { .output(output); }); + // sp p lookat + ll ::command ::CommandRegistrar ::getInstance(false).tryRegisterRuntimeEnum( + "cfspFacing", + { + {"north", 0}, + {"south", 1}, + {"west", 2}, + {"east", 3}, + {"up", 4}, + {"down", 5} + } + ); + this->command->runtimeOverload() + .text("p") + .text("lookat") + .required("spname", ll ::command ::ParamKind ::SoftEnum, "cfspOnlineSp") + .required("facing", ll ::command ::ParamKind ::Enum, "cfspFacing") + .execute([this](CommandOrigin const& origin, CommandOutput& output, ll ::command ::RuntimeCommand const& self) { + auto player = this->tryGetPlayer(origin); + if (!player.has_value()) return output.error("command.fail.illegalOrigin"_tr()); + return manager ::CFSPManager ::getInstance() + .spLookAt( + player.value(), + self["spname"].get(), + static_cast(self["facing"].get().index) + ) + .output(output); + }); + // sp p [pos: Vec3] [speed: float] ll::command::CommandRegistrar::getInstance(false).tryRegisterRuntimeEnum( "cfspOnlineSpOperate6", diff --git a/src/lang/en_US.json b/src/lang/en_US.json index f86744b..96a700f 100644 --- a/src/lang/en_US.json +++ b/src/lang/en_US.json @@ -62,7 +62,8 @@ "targetNotHavePerm": "Target does not have this permission", "targetIsSp": "Target object is a SimulatedPlayer", "targetIsManager": "Target object is already a manager", - "targetNotManager": "Target object is not a manager" + "targetNotManager": "Target object is not a manager", + "invalidDirection": "Invalid direction" }, "error": { "failedtocreate": "Error: Failed to create SimulatedPlayer", diff --git a/src/lang/zh_CN.json b/src/lang/zh_CN.json index b7cb57c..5c04a16 100644 --- a/src/lang/zh_CN.json +++ b/src/lang/zh_CN.json @@ -62,7 +62,8 @@ "targetNotHavePerm": "目标没有该权限", "targetIsSp": "目标对象为假人", "targetIsManager": " 目标对象已为管理员", - "targetNotManager": " 目标对象不是管理员" + "targetNotManager": " 目标对象不是管理员", + "invalidDirection": "无效的方向" }, "error": { "failedtocreate": "Error: 创建假人失败",