| @@ -60,7 +60,7 @@ public: | |||||
| virtual bool PickProp(THUAI6::PropType prop) = 0; | virtual bool PickProp(THUAI6::PropType prop) = 0; | ||||
| virtual bool UseProp(THUAI6::PropType prop) = 0; | virtual bool UseProp(THUAI6::PropType prop) = 0; | ||||
| virtual bool ThrowProp(THUAI6::PropType prop) = 0; | virtual bool ThrowProp(THUAI6::PropType prop) = 0; | ||||
| virtual bool UseSkill(int32_t skillID) = 0; | |||||
| virtual bool UseSkill(int32_t skillID, int32_t skillParam) = 0; | |||||
| virtual bool SendMessage(int64_t toID, std::string message, bool binary) = 0; | virtual bool SendMessage(int64_t toID, std::string message, bool binary) = 0; | ||||
| virtual bool HaveMessage() = 0; | virtual bool HaveMessage() = 0; | ||||
| virtual std::pair<int64_t, std::string> GetMessage() = 0; | virtual std::pair<int64_t, std::string> GetMessage() = 0; | ||||
| @@ -108,7 +108,7 @@ public: | |||||
| virtual std::future<bool> PickProp(THUAI6::PropType prop) = 0; | virtual std::future<bool> PickProp(THUAI6::PropType prop) = 0; | ||||
| virtual std::future<bool> UseProp(THUAI6::PropType prop) = 0; | virtual std::future<bool> UseProp(THUAI6::PropType prop) = 0; | ||||
| virtual std::future<bool> ThrowProp(THUAI6::PropType prop) = 0; | virtual std::future<bool> ThrowProp(THUAI6::PropType prop) = 0; | ||||
| virtual std::future<bool> UseSkill(int32_t skillID) = 0; | |||||
| virtual std::future<bool> UseSkill(int32_t skillID, int32_t skillParam = 0) = 0; | |||||
| virtual std::future<bool> Attack(double angleInRadian) = 0; | virtual std::future<bool> Attack(double angleInRadian) = 0; | ||||
| virtual std::future<bool> OpenDoor() = 0; | virtual std::future<bool> OpenDoor() = 0; | ||||
| @@ -236,7 +236,7 @@ public: | |||||
| std::future<bool> PickProp(THUAI6::PropType prop) override; | std::future<bool> PickProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | std::future<bool> UseProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> ThrowProp(THUAI6::PropType prop) override; | std::future<bool> ThrowProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseSkill(int32_t skillID) override; | |||||
| std::future<bool> UseSkill(int32_t skillID, int32_t skillParam = 0) override; | |||||
| std::future<bool> Attack(double angleInRadian) override; | std::future<bool> Attack(double angleInRadian) override; | ||||
| @@ -329,7 +329,7 @@ public: | |||||
| std::future<bool> PickProp(THUAI6::PropType prop) override; | std::future<bool> PickProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | std::future<bool> UseProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> ThrowProp(THUAI6::PropType prop) override; | std::future<bool> ThrowProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseSkill(int32_t skillID) override; | |||||
| std::future<bool> UseSkill(int32_t skillID, int32_t skillParam = 0) override; | |||||
| std::future<bool> OpenDoor() override; | std::future<bool> OpenDoor() override; | ||||
| std::future<bool> CloseDoor() override; | std::future<bool> CloseDoor() override; | ||||
| @@ -410,7 +410,7 @@ public: | |||||
| std::future<bool> PickProp(THUAI6::PropType prop) override; | std::future<bool> PickProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | std::future<bool> UseProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> ThrowProp(THUAI6::PropType prop) override; | std::future<bool> ThrowProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseSkill(int32_t skillID) override; | |||||
| std::future<bool> UseSkill(int32_t skillID, int32_t skillParam = 0) override; | |||||
| std::future<bool> Attack(double angleInRadian) override; | std::future<bool> Attack(double angleInRadian) override; | ||||
| @@ -488,7 +488,7 @@ public: | |||||
| std::future<bool> PickProp(THUAI6::PropType prop) override; | std::future<bool> PickProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | std::future<bool> UseProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> ThrowProp(THUAI6::PropType prop) override; | std::future<bool> ThrowProp(THUAI6::PropType prop) override; | ||||
| std::future<bool> UseSkill(int32_t skillID) override; | |||||
| std::future<bool> UseSkill(int32_t skillID, int32_t skillParam = 0) override; | |||||
| std::future<bool> OpenDoor() override; | std::future<bool> OpenDoor() override; | ||||
| std::future<bool> CloseDoor() override; | std::future<bool> CloseDoor() override; | ||||
| @@ -31,7 +31,7 @@ public: | |||||
| bool PickProp(THUAI6::PropType prop, int64_t playerID); | bool PickProp(THUAI6::PropType prop, int64_t playerID); | ||||
| bool UseProp(THUAI6::PropType prop, int64_t playerID); | bool UseProp(THUAI6::PropType prop, int64_t playerID); | ||||
| bool ThrowProp(THUAI6::PropType prop, int64_t playerID); | bool ThrowProp(THUAI6::PropType prop, int64_t playerID); | ||||
| bool UseSkill(int32_t skillID, int64_t playerID); | |||||
| bool UseSkill(int32_t skillID, int32_t skillParam, int64_t playerID); | |||||
| bool SendMessage(int64_t toID, std::string message, bool binary, int64_t playerID); | bool SendMessage(int64_t toID, std::string message, bool binary, int64_t playerID); | ||||
| bool OpenDoor(int64_t playerID); | bool OpenDoor(int64_t playerID); | ||||
| bool CloseDoor(int64_t playerID); | bool CloseDoor(int64_t playerID); | ||||
| @@ -116,7 +116,7 @@ private: | |||||
| bool PickProp(THUAI6::PropType prop) override; | bool PickProp(THUAI6::PropType prop) override; | ||||
| bool UseProp(THUAI6::PropType prop) override; | bool UseProp(THUAI6::PropType prop) override; | ||||
| bool ThrowProp(THUAI6::PropType prop) override; | bool ThrowProp(THUAI6::PropType prop) override; | ||||
| bool UseSkill(int32_t skillID) override; | |||||
| bool UseSkill(int32_t skillID, int32_t skillParam) override; | |||||
| bool SendMessage(int64_t toID, std::string message, bool binary) override; | bool SendMessage(int64_t toID, std::string message, bool binary) override; | ||||
| bool HaveMessage() override; | bool HaveMessage() override; | ||||
| @@ -62,6 +62,7 @@ namespace THUAI6 | |||||
| AddHpOrAp = 6, | AddHpOrAp = 6, | ||||
| ShieldOrSpear = 7, | ShieldOrSpear = 7, | ||||
| RecoveryFromDizziness = 8, | RecoveryFromDizziness = 8, | ||||
| CraftingBench = 9, | |||||
| }; | }; | ||||
| enum class BulletType : unsigned char | enum class BulletType : unsigned char | ||||
| @@ -71,7 +72,7 @@ namespace THUAI6 | |||||
| CommonAttackOfTricker = 2, | CommonAttackOfTricker = 2, | ||||
| BombBomb = 3, | BombBomb = 3, | ||||
| JumpyDumpty = 4, | JumpyDumpty = 4, | ||||
| AtomBomb = 5, | |||||
| Strike = 5, | |||||
| }; | }; | ||||
| // 玩家类型 | // 玩家类型 | ||||
| @@ -363,6 +364,7 @@ namespace THUAI6 | |||||
| {PropType::AddHpOrAp, "AddHpOrAp"}, | {PropType::AddHpOrAp, "AddHpOrAp"}, | ||||
| {PropType::ShieldOrSpear, "ShieldOrSpear"}, | {PropType::ShieldOrSpear, "ShieldOrSpear"}, | ||||
| {PropType::RecoveryFromDizziness, "RecoveryFromDizziness"}, | {PropType::RecoveryFromDizziness, "RecoveryFromDizziness"}, | ||||
| {PropType::CraftingBench, "CraftingBench"}, | |||||
| }; | }; | ||||
| @@ -372,7 +374,7 @@ namespace THUAI6 | |||||
| {BulletType::CommonAttackOfTricker, "CommonAttackOfTricker"}, | {BulletType::CommonAttackOfTricker, "CommonAttackOfTricker"}, | ||||
| {BulletType::BombBomb, "BombBomb"}, | {BulletType::BombBomb, "BombBomb"}, | ||||
| {BulletType::JumpyDumpty, "JumpyDumpty"}, | {BulletType::JumpyDumpty, "JumpyDumpty"}, | ||||
| {BulletType::AtomBomb, "AtomBomb"}, | |||||
| {BulletType::Strike, "Strike"}, | |||||
| }; | }; | ||||
| inline std::map<StudentBuffType, std::string> studentBuffDict{ | inline std::map<StudentBuffType, std::string> studentBuffDict{ | ||||
| @@ -108,6 +108,7 @@ namespace Proto2THUAI6 | |||||
| {protobuf::PropType::ADD_LIFE_OR_CLAIRAUDIENCE, THUAI6::PropType::AddLifeOrClairaudience}, | {protobuf::PropType::ADD_LIFE_OR_CLAIRAUDIENCE, THUAI6::PropType::AddLifeOrClairaudience}, | ||||
| {protobuf::PropType::SHIELD_OR_SPEAR, THUAI6::PropType::ShieldOrSpear}, | {protobuf::PropType::SHIELD_OR_SPEAR, THUAI6::PropType::ShieldOrSpear}, | ||||
| {protobuf::PropType::RECOVERY_FROM_DIZZINESS, THUAI6::PropType::RecoveryFromDizziness}, | {protobuf::PropType::RECOVERY_FROM_DIZZINESS, THUAI6::PropType::RecoveryFromDizziness}, | ||||
| {protobuf::PropType::CRAFTING_BENCH, THUAI6::PropType::CraftingBench}, | |||||
| }; | }; | ||||
| inline std::map<protobuf::PlayerType, THUAI6::PlayerType> playerTypeDict{ | inline std::map<protobuf::PlayerType, THUAI6::PlayerType> playerTypeDict{ | ||||
| @@ -186,7 +187,7 @@ namespace Proto2THUAI6 | |||||
| {protobuf::BulletType::COMMON_ATTACK_OF_TRICKER, THUAI6::BulletType::CommonAttackOfTricker}, | {protobuf::BulletType::COMMON_ATTACK_OF_TRICKER, THUAI6::BulletType::CommonAttackOfTricker}, | ||||
| {protobuf::BulletType::BOMB_BOMB, THUAI6::BulletType::BombBomb}, | {protobuf::BulletType::BOMB_BOMB, THUAI6::BulletType::BombBomb}, | ||||
| {protobuf::BulletType::JUMPY_DUMPTY, THUAI6::BulletType::JumpyDumpty}, | {protobuf::BulletType::JUMPY_DUMPTY, THUAI6::BulletType::JumpyDumpty}, | ||||
| {protobuf::BulletType::ATOM_BOMB, THUAI6::BulletType::AtomBomb}, | |||||
| {protobuf::BulletType::STRIKE, THUAI6::BulletType::Strike}, | |||||
| }; | }; | ||||
| inline std::map<protobuf::MessageOfObj::MessageOfObjCase, THUAI6::MessageOfObj> messageOfObjDict{ | inline std::map<protobuf::MessageOfObj::MessageOfObjCase, THUAI6::MessageOfObj> messageOfObjDict{ | ||||
| @@ -373,6 +374,7 @@ namespace THUAI62Proto | |||||
| {THUAI6::PropType::AddLifeOrClairaudience, protobuf::PropType::ADD_LIFE_OR_CLAIRAUDIENCE}, | {THUAI6::PropType::AddLifeOrClairaudience, protobuf::PropType::ADD_LIFE_OR_CLAIRAUDIENCE}, | ||||
| {THUAI6::PropType::AddSpeed, protobuf::PropType::ADD_SPEED}, | {THUAI6::PropType::AddSpeed, protobuf::PropType::ADD_SPEED}, | ||||
| {THUAI6::PropType::ShieldOrSpear, protobuf::PropType::SHIELD_OR_SPEAR}, | {THUAI6::PropType::ShieldOrSpear, protobuf::PropType::SHIELD_OR_SPEAR}, | ||||
| {THUAI6::PropType::CraftingBench, protobuf::PropType::CRAFTING_BENCH}, | |||||
| }; | }; | ||||
| inline std::map<THUAI6::PlayerType, protobuf::PlayerType> playerTypeDict{ | inline std::map<THUAI6::PlayerType, protobuf::PlayerType> playerTypeDict{ | ||||
| @@ -486,11 +488,12 @@ namespace THUAI62Proto | |||||
| return attackMsg; | return attackMsg; | ||||
| } | } | ||||
| inline protobuf::SkillMsg THUAI62ProtobufSkill(int32_t skillID, int64_t id) | |||||
| inline protobuf::SkillMsg THUAI62ProtobufSkill(int32_t skillID, int32_t skillParam, int64_t id) | |||||
| { | { | ||||
| protobuf::SkillMsg skillMsg; | protobuf::SkillMsg skillMsg; | ||||
| skillMsg.set_skill_id(skillID); | skillMsg.set_skill_id(skillID); | ||||
| skillMsg.set_player_id(id); | skillMsg.set_player_id(id); | ||||
| skillMsg.set_skill_param(skillParam); | |||||
| return skillMsg; | return skillMsg; | ||||
| } | } | ||||
| } // namespace THUAI62Proto | } // namespace THUAI62Proto | ||||
| @@ -106,16 +106,16 @@ std::future<bool> TrickerAPI::ThrowProp(THUAI6::PropType prop) | |||||
| { return logic.ThrowProp(prop); }); | { return logic.ThrowProp(prop); }); | ||||
| } | } | ||||
| std::future<bool> StudentAPI::UseSkill(int32_t skillID) | |||||
| std::future<bool> StudentAPI::UseSkill(int32_t skillID, int32_t skillParam) | |||||
| { | { | ||||
| return std::async(std::launch::async, [=]() | return std::async(std::launch::async, [=]() | ||||
| { return logic.UseSkill(skillID); }); | |||||
| { return logic.UseSkill(skillID, skillParam); }); | |||||
| } | } | ||||
| std::future<bool> TrickerAPI::UseSkill(int32_t skillID) | |||||
| std::future<bool> TrickerAPI::UseSkill(int32_t skillID, int32_t skillParam) | |||||
| { | { | ||||
| return std::async(std::launch::async, [=]() | return std::async(std::launch::async, [=]() | ||||
| { return logic.UseSkill(skillID); }); | |||||
| { return logic.UseSkill(skillID, skillParam); }); | |||||
| } | } | ||||
| std::future<bool> StudentAPI::OpenDoor() | std::future<bool> StudentAPI::OpenDoor() | ||||
| @@ -91,7 +91,7 @@ bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID) | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool Communication::UseSkill(int32_t skillID, int64_t playerID) | |||||
| bool Communication::UseSkill(int32_t skillID, int32_t skillParam, int64_t playerID) | |||||
| { | { | ||||
| { | { | ||||
| std::lock_guard<std::mutex> lock(mtxLimit); | std::lock_guard<std::mutex> lock(mtxLimit); | ||||
| @@ -101,7 +101,7 @@ bool Communication::UseSkill(int32_t skillID, int64_t playerID) | |||||
| } | } | ||||
| protobuf::BoolRes useSkillResult; | protobuf::BoolRes useSkillResult; | ||||
| ClientContext context; | ClientContext context; | ||||
| auto request = THUAI62Proto::THUAI62ProtobufSkill(skillID, playerID); | |||||
| auto request = THUAI62Proto::THUAI62ProtobufSkill(skillID, skillParam, playerID); | |||||
| auto status = THUAI6Stub->UseSkill(&context, request, &useSkillResult); | auto status = THUAI6Stub->UseSkill(&context, request, &useSkillResult); | ||||
| if (status.ok()) | if (status.ok()) | ||||
| return useSkillResult.act_success(); | return useSkillResult.act_success(); | ||||
| @@ -212,21 +212,21 @@ std::future<bool> TrickerDebugAPI::ThrowProp(THUAI6::PropType prop) | |||||
| return result; }); | return result; }); | ||||
| } | } | ||||
| std::future<bool> StudentDebugAPI::UseSkill(int32_t skillID) | |||||
| std::future<bool> StudentDebugAPI::UseSkill(int32_t skillID, int32_t skillParam) | |||||
| { | { | ||||
| logger->info("UseSkill: skillID={}, called at {}ms", skillID, Time::TimeSinceStart(startPoint)); | |||||
| logger->info("UseSkill: skillID={}, skillParam={}, called at {}ms", skillID, skillParam, Time::TimeSinceStart(startPoint)); | |||||
| return std::async(std::launch::async, [=]() | return std::async(std::launch::async, [=]() | ||||
| { auto result = logic.UseSkill(skillID); | |||||
| { auto result = logic.UseSkill(skillID, skillParam); | |||||
| if (!result) | if (!result) | ||||
| logger->warn("UseSkill: failed at {}ms", Time::TimeSinceStart(startPoint)); | logger->warn("UseSkill: failed at {}ms", Time::TimeSinceStart(startPoint)); | ||||
| return result; }); | return result; }); | ||||
| } | } | ||||
| std::future<bool> TrickerDebugAPI::UseSkill(int32_t skillID) | |||||
| std::future<bool> TrickerDebugAPI::UseSkill(int32_t skillID, int32_t skillParam) | |||||
| { | { | ||||
| logger->info("UseSkill: skillID={}, called at {}ms", skillID, Time::TimeSinceStart(startPoint)); | |||||
| logger->info("UseSkill: skillID={}, skillParam={}, called at {}ms", skillID, skillParam, Time::TimeSinceStart(startPoint)); | |||||
| return std::async(std::launch::async, [=]() | return std::async(std::launch::async, [=]() | ||||
| { auto result = logic.UseSkill(skillID); | |||||
| { auto result = logic.UseSkill(skillID, skillParam); | |||||
| if (!result) | if (!result) | ||||
| logger->warn("UseSkill: failed at {}ms", Time::TimeSinceStart(startPoint)); | logger->warn("UseSkill: failed at {}ms", Time::TimeSinceStart(startPoint)); | ||||
| return result; }); | return result; }); | ||||
| @@ -208,10 +208,10 @@ bool Logic::ThrowProp(THUAI6::PropType prop) | |||||
| return pComm->ThrowProp(prop, playerID); | return pComm->ThrowProp(prop, playerID); | ||||
| } | } | ||||
| bool Logic::UseSkill(int32_t skill) | |||||
| bool Logic::UseSkill(int32_t skill, int32_t skillParam) | |||||
| { | { | ||||
| logger->debug("Called UseSkill"); | logger->debug("Called UseSkill"); | ||||
| return pComm->UseSkill(skill, playerID); | |||||
| return pComm->UseSkill(skill, skillParam, playerID); | |||||
| } | } | ||||
| bool Logic::SendMessage(int64_t toID, std::string message, bool binary) | bool Logic::SendMessage(int64_t toID, std::string message, bool binary) | ||||
| @@ -180,7 +180,7 @@ namespace protobuf | |||||
| ::_pbi::ConstantInitialized | ::_pbi::ConstantInitialized | ||||
| ) : | ) : | ||||
| _impl_{ | _impl_{ | ||||
| /*decltype(_impl_.player_id_)*/ int64_t{0}, /*decltype(_impl_.skill_id_)*/ 0, /*decltype(_impl_._cached_size_)*/ {}} | |||||
| /*decltype(_impl_.player_id_)*/ int64_t{0}, /*decltype(_impl_.skill_id_)*/ 0, /*decltype(_impl_.skill_param_)*/ 0, /*decltype(_impl_._cached_size_)*/ {}} | |||||
| { | { | ||||
| } | } | ||||
| struct SkillMsgDefaultTypeInternal | struct SkillMsgDefaultTypeInternal | ||||
| @@ -274,6 +274,7 @@ const uint32_t TableStruct_Message2Server_2eproto::offsets[] PROTOBUF_SECTION_VA | |||||
| ~0u, // no _inlined_string_donated_ | ~0u, // no _inlined_string_donated_ | ||||
| PROTOBUF_FIELD_OFFSET(::protobuf::SkillMsg, _impl_.player_id_), | PROTOBUF_FIELD_OFFSET(::protobuf::SkillMsg, _impl_.player_id_), | ||||
| PROTOBUF_FIELD_OFFSET(::protobuf::SkillMsg, _impl_.skill_id_), | PROTOBUF_FIELD_OFFSET(::protobuf::SkillMsg, _impl_.skill_id_), | ||||
| PROTOBUF_FIELD_OFFSET(::protobuf::SkillMsg, _impl_.skill_param_), | |||||
| }; | }; | ||||
| static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { | static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { | ||||
| {0, -1, -1, sizeof(::protobuf::PlayerMsg)}, | {0, -1, -1, sizeof(::protobuf::PlayerMsg)}, | ||||
| @@ -313,9 +314,9 @@ const char descriptor_table_protodef_Message2Server_2eproto[] PROTOBUF_SECTION_V | |||||
| "\t\n\007message\"-\n\tAttackMsg\022\021\n\tplayer_id\030\001 \001" | "\t\n\007message\"-\n\tAttackMsg\022\021\n\tplayer_id\030\001 \001" | ||||
| "(\003\022\r\n\005angle\030\002 \001(\001\"\032\n\005IDMsg\022\021\n\tplayer_id\030" | "(\003\022\r\n\005angle\030\002 \001(\001\"\032\n\005IDMsg\022\021\n\tplayer_id\030" | ||||
| "\001 \001(\003\"<\n\021TreatAndRescueMsg\022\021\n\tplayer_id\030" | "\001 \001(\003\"<\n\021TreatAndRescueMsg\022\021\n\tplayer_id\030" | ||||
| "\001 \001(\003\022\024\n\014to_player_id\030\002 \001(\003\"/\n\010SkillMsg\022" | |||||
| "\021\n\tplayer_id\030\001 \001(\003\022\020\n\010skill_id\030\002 \001(\005b\006pr" | |||||
| "oto3"; | |||||
| "\001 \001(\003\022\024\n\014to_player_id\030\002 \001(\003\"D\n\010SkillMsg\022" | |||||
| "\021\n\tplayer_id\030\001 \001(\003\022\020\n\010skill_id\030\002 \001(\005\022\023\n\013" | |||||
| "skill_param\030\003 \001(\005b\006proto3"; | |||||
| static const ::_pbi::DescriptorTable* const descriptor_table_Message2Server_2eproto_deps[1] = { | static const ::_pbi::DescriptorTable* const descriptor_table_Message2Server_2eproto_deps[1] = { | ||||
| &::descriptor_table_MessageType_2eproto, | &::descriptor_table_MessageType_2eproto, | ||||
| }; | }; | ||||
| @@ -323,7 +324,7 @@ static ::_pbi::once_flag descriptor_table_Message2Server_2eproto_once; | |||||
| const ::_pbi::DescriptorTable descriptor_table_Message2Server_2eproto = { | const ::_pbi::DescriptorTable descriptor_table_Message2Server_2eproto = { | ||||
| false, | false, | ||||
| false, | false, | ||||
| 684, | |||||
| 705, | |||||
| descriptor_table_protodef_Message2Server_2eproto, | descriptor_table_protodef_Message2Server_2eproto, | ||||
| "Message2Server.proto", | "Message2Server.proto", | ||||
| &descriptor_table_Message2Server_2eproto_once, | &descriptor_table_Message2Server_2eproto_once, | ||||
| @@ -2341,10 +2342,10 @@ namespace protobuf | |||||
| SkillMsg* const _this = this; | SkillMsg* const _this = this; | ||||
| (void)_this; | (void)_this; | ||||
| new (&_impl_) Impl_{ | new (&_impl_) Impl_{ | ||||
| decltype(_impl_.player_id_){}, decltype(_impl_.skill_id_){}, /*decltype(_impl_._cached_size_)*/ {}}; | |||||
| decltype(_impl_.player_id_){}, decltype(_impl_.skill_id_){}, decltype(_impl_.skill_param_){}, /*decltype(_impl_._cached_size_)*/ {}}; | |||||
| _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); | _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); | ||||
| ::memcpy(&_impl_.player_id_, &from._impl_.player_id_, static_cast<size_t>(reinterpret_cast<char*>(&_impl_.skill_id_) - reinterpret_cast<char*>(&_impl_.player_id_)) + sizeof(_impl_.skill_id_)); | |||||
| ::memcpy(&_impl_.player_id_, &from._impl_.player_id_, static_cast<size_t>(reinterpret_cast<char*>(&_impl_.skill_param_) - reinterpret_cast<char*>(&_impl_.player_id_)) + sizeof(_impl_.skill_param_)); | |||||
| // @@protoc_insertion_point(copy_constructor:protobuf.SkillMsg) | // @@protoc_insertion_point(copy_constructor:protobuf.SkillMsg) | ||||
| } | } | ||||
| @@ -2355,7 +2356,7 @@ namespace protobuf | |||||
| (void)arena; | (void)arena; | ||||
| (void)is_message_owned; | (void)is_message_owned; | ||||
| new (&_impl_) Impl_{ | new (&_impl_) Impl_{ | ||||
| decltype(_impl_.player_id_){int64_t{0}}, decltype(_impl_.skill_id_){0}, /*decltype(_impl_._cached_size_)*/ {}}; | |||||
| decltype(_impl_.player_id_){int64_t{0}}, decltype(_impl_.skill_id_){0}, decltype(_impl_.skill_param_){0}, /*decltype(_impl_._cached_size_)*/ {}}; | |||||
| } | } | ||||
| SkillMsg::~SkillMsg() | SkillMsg::~SkillMsg() | ||||
| @@ -2386,7 +2387,7 @@ namespace protobuf | |||||
| // Prevent compiler warnings about cached_has_bits being unused | // Prevent compiler warnings about cached_has_bits being unused | ||||
| (void)cached_has_bits; | (void)cached_has_bits; | ||||
| ::memset(&_impl_.player_id_, 0, static_cast<size_t>(reinterpret_cast<char*>(&_impl_.skill_id_) - reinterpret_cast<char*>(&_impl_.player_id_)) + sizeof(_impl_.skill_id_)); | |||||
| ::memset(&_impl_.player_id_, 0, static_cast<size_t>(reinterpret_cast<char*>(&_impl_.skill_param_) - reinterpret_cast<char*>(&_impl_.player_id_)) + sizeof(_impl_.skill_param_)); | |||||
| _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); | _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); | ||||
| } | } | ||||
| @@ -2421,6 +2422,16 @@ namespace protobuf | |||||
| else | else | ||||
| goto handle_unusual; | goto handle_unusual; | ||||
| continue; | continue; | ||||
| // int32 skill_param = 3; | |||||
| case 3: | |||||
| if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) | |||||
| { | |||||
| _impl_.skill_param_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); | |||||
| CHK_(ptr); | |||||
| } | |||||
| else | |||||
| goto handle_unusual; | |||||
| continue; | |||||
| default: | default: | ||||
| goto handle_unusual; | goto handle_unusual; | ||||
| } // switch | } // switch | ||||
| @@ -2469,6 +2480,13 @@ namespace protobuf | |||||
| target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_skill_id(), target); | target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_skill_id(), target); | ||||
| } | } | ||||
| // int32 skill_param = 3; | |||||
| if (this->_internal_skill_param() != 0) | |||||
| { | |||||
| target = stream->EnsureSpace(target); | |||||
| target = ::_pbi::WireFormatLite::WriteInt32ToArray(3, this->_internal_skill_param(), target); | |||||
| } | |||||
| if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) | if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) | ||||
| { | { | ||||
| target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( | target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( | ||||
| @@ -2500,6 +2518,12 @@ namespace protobuf | |||||
| total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_skill_id()); | total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_skill_id()); | ||||
| } | } | ||||
| // int32 skill_param = 3; | |||||
| if (this->_internal_skill_param() != 0) | |||||
| { | |||||
| total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_skill_param()); | |||||
| } | |||||
| return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); | return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); | ||||
| } | } | ||||
| @@ -2528,6 +2552,10 @@ namespace protobuf | |||||
| { | { | ||||
| _this->_internal_set_skill_id(from._internal_skill_id()); | _this->_internal_set_skill_id(from._internal_skill_id()); | ||||
| } | } | ||||
| if (from._internal_skill_param() != 0) | |||||
| { | |||||
| _this->_internal_set_skill_param(from._internal_skill_param()); | |||||
| } | |||||
| _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); | _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); | ||||
| } | } | ||||
| @@ -2550,7 +2578,7 @@ namespace protobuf | |||||
| using std::swap; | using std::swap; | ||||
| _internal_metadata_.InternalSwap(&other->_internal_metadata_); | _internal_metadata_.InternalSwap(&other->_internal_metadata_); | ||||
| ::PROTOBUF_NAMESPACE_ID::internal::memswap< | ::PROTOBUF_NAMESPACE_ID::internal::memswap< | ||||
| PROTOBUF_FIELD_OFFSET(SkillMsg, _impl_.skill_id_) + sizeof(SkillMsg::_impl_.skill_id_) - PROTOBUF_FIELD_OFFSET(SkillMsg, _impl_.player_id_)>( | |||||
| PROTOBUF_FIELD_OFFSET(SkillMsg, _impl_.skill_param_) + sizeof(SkillMsg::_impl_.skill_param_) - PROTOBUF_FIELD_OFFSET(SkillMsg, _impl_.player_id_)>( | |||||
| reinterpret_cast<char*>(&_impl_.player_id_), | reinterpret_cast<char*>(&_impl_.player_id_), | ||||
| reinterpret_cast<char*>(&other->_impl_.player_id_) | reinterpret_cast<char*>(&other->_impl_.player_id_) | ||||
| ); | ); | ||||
| @@ -1813,6 +1813,7 @@ namespace protobuf | |||||
| { | { | ||||
| kPlayerIdFieldNumber = 1, | kPlayerIdFieldNumber = 1, | ||||
| kSkillIdFieldNumber = 2, | kSkillIdFieldNumber = 2, | ||||
| kSkillParamFieldNumber = 3, | |||||
| }; | }; | ||||
| // int64 player_id = 1; | // int64 player_id = 1; | ||||
| void clear_player_id(); | void clear_player_id(); | ||||
| @@ -1833,6 +1834,16 @@ namespace protobuf | |||||
| int32_t _internal_skill_id() const; | int32_t _internal_skill_id() const; | ||||
| void _internal_set_skill_id(int32_t value); | void _internal_set_skill_id(int32_t value); | ||||
| public: | |||||
| // int32 skill_param = 3; | |||||
| void clear_skill_param(); | |||||
| int32_t skill_param() const; | |||||
| void set_skill_param(int32_t value); | |||||
| private: | |||||
| int32_t _internal_skill_param() const; | |||||
| void _internal_set_skill_param(int32_t value); | |||||
| public: | public: | ||||
| // @@protoc_insertion_point(class_scope:protobuf.SkillMsg) | // @@protoc_insertion_point(class_scope:protobuf.SkillMsg) | ||||
| @@ -1847,6 +1858,7 @@ namespace protobuf | |||||
| { | { | ||||
| int64_t player_id_; | int64_t player_id_; | ||||
| int32_t skill_id_; | int32_t skill_id_; | ||||
| int32_t skill_param_; | |||||
| mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; | mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; | ||||
| }; | }; | ||||
| union | union | ||||
| @@ -2597,6 +2609,30 @@ namespace protobuf | |||||
| // @@protoc_insertion_point(field_set:protobuf.SkillMsg.skill_id) | // @@protoc_insertion_point(field_set:protobuf.SkillMsg.skill_id) | ||||
| } | } | ||||
| // int32 skill_param = 3; | |||||
| inline void SkillMsg::clear_skill_param() | |||||
| { | |||||
| _impl_.skill_param_ = 0; | |||||
| } | |||||
| inline int32_t SkillMsg::_internal_skill_param() const | |||||
| { | |||||
| return _impl_.skill_param_; | |||||
| } | |||||
| inline int32_t SkillMsg::skill_param() const | |||||
| { | |||||
| // @@protoc_insertion_point(field_get:protobuf.SkillMsg.skill_param) | |||||
| return _internal_skill_param(); | |||||
| } | |||||
| inline void SkillMsg::_internal_set_skill_param(int32_t value) | |||||
| { | |||||
| _impl_.skill_param_ = value; | |||||
| } | |||||
| inline void SkillMsg::set_skill_param(int32_t value) | |||||
| { | |||||
| _internal_set_skill_param(value); | |||||
| // @@protoc_insertion_point(field_set:protobuf.SkillMsg.skill_param) | |||||
| } | |||||
| #ifdef __GNUC__ | #ifdef __GNUC__ | ||||
| #pragma GCC diagnostic pop | #pragma GCC diagnostic pop | ||||
| #endif // __GNUC__ | #endif // __GNUC__ | ||||
| @@ -30,49 +30,49 @@ static constexpr ::_pbi::MigrationSchema* schemas = nullptr; | |||||
| static constexpr ::_pb::Message* const* file_default_instances = nullptr; | static constexpr ::_pb::Message* const* file_default_instances = nullptr; | ||||
| const char descriptor_table_protodef_MessageType_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = | const char descriptor_table_protodef_MessageType_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = | ||||
| "\n\021MessageType.proto\022\010protobuf*\202\001\n\nBullet" | |||||
| "Type\022\024\n\020NULL_BULLET_TYPE\020\000\022\020\n\014FLYING_KNI" | |||||
| "FE\020\001\022\034\n\030COMMON_ATTACK_OF_TRICKER\020\002\022\r\n\tBO" | |||||
| "MB_BOMB\020\003\022\020\n\014JUMPY_DUMPTY\020\004\022\r\n\tATOM_BOMB" | |||||
| "\020\005*\241\001\n\tPlaceType\022\023\n\017NULL_PLACE_TYPE\020\000\022\010\n" | |||||
| "\004LAND\020\001\022\010\n\004WALL\020\002\022\t\n\005GRASS\020\003\022\r\n\tCLASSROO" | |||||
| "M\020\004\022\010\n\004GATE\020\005\022\017\n\013HIDDEN_GATE\020\006\022\n\n\006WINDOW" | |||||
| "\020\007\022\t\n\005DOOR3\020\010\022\t\n\005DOOR5\020\t\022\t\n\005DOOR6\020\n\022\t\n\005C" | |||||
| "HEST\020\013*8\n\tShapeType\022\023\n\017NULL_SHAPE_TYPE\020\000" | |||||
| "\022\n\n\006CIRCLE\020\001\022\n\n\006SQUARE\020\002*\256\001\n\010PropType\022\022\n" | |||||
| "\016NULL_PROP_TYPE\020\000\022\r\n\tADD_SPEED\020\001\022\035\n\031ADD_" | |||||
| "LIFE_OR_CLAIRAUDIENCE\020\002\022\020\n\014ADD_HP_OR_AP\020" | |||||
| "\003\022\023\n\017SHIELD_OR_SPEAR\020\004\022\010\n\004KEY3\020\005\022\010\n\004KEY5" | |||||
| "\020\006\022\010\n\004KEY6\020\007\022\033\n\027RECOVERY_FROM_DIZZINESS\020" | |||||
| "\010*n\n\017StudentBuffType\022\023\n\017NULL_SBUFF_TYPE\020" | |||||
| "\000\022\025\n\021STUDENT_ADD_SPEED\020\001\022\014\n\010ADD_LIFE\020\002\022\n" | |||||
| "\n\006SHIELD\020\003\022\025\n\021STUDENT_INVISIBLE\020\004*\251\002\n\013Pl" | |||||
| "ayerState\022\017\n\013NULL_STATUS\020\000\022\010\n\004IDLE\020\001\022\014\n\010" | |||||
| "LEARNING\020\002\022\014\n\010ADDICTED\020\003\022\010\n\004QUIT\020\004\022\r\n\tGR" | |||||
| "ADUATED\020\005\022\013\n\007TREATED\020\006\022\013\n\007RESCUED\020\007\022\013\n\007S" | |||||
| "TUNNED\020\010\022\014\n\010TREATING\020\t\022\014\n\010RESCUING\020\n\022\014\n\010" | |||||
| "SWINGING\020\013\022\r\n\tATTACKING\020\014\022\013\n\007LOCKING\020\r\022\r" | |||||
| "\n\tRUMMAGING\020\016\022\014\n\010CLIMBING\020\017\022\023\n\017OPENING_A" | |||||
| "_CHEST\020\020\022\027\n\023USING_SPECIAL_SKILL\020\021\022\022\n\016OPE" | |||||
| "NING_A_GATE\020\022*~\n\017TrickerBuffType\022\023\n\017NULL" | |||||
| "_TBUFF_TYPE\020\000\022\025\n\021TRICKER_ADD_SPEED\020\001\022\t\n\005" | |||||
| "SPEAR\020\002\022\n\n\006ADD_AP\020\003\022\021\n\rCLAIRAUDIENCE\020\004\022\025" | |||||
| "\n\021TRICKER_INVISIBLE\020\005*J\n\nPlayerType\022\024\n\020N" | |||||
| "ULL_PLAYER_TYPE\020\000\022\022\n\016STUDENT_PLAYER\020\001\022\022\n" | |||||
| "\016TRICKER_PLAYER\020\002*\177\n\013StudentType\022\025\n\021NULL" | |||||
| "_STUDENT_TYPE\020\000\022\013\n\007ATHLETE\020\001\022\013\n\007TEACHER\020" | |||||
| "\002\022\026\n\022STRAIGHT_A_STUDENT\020\003\022\t\n\005ROBOT\020\004\022\016\n\n" | |||||
| "TECH_OTAKU\020\005\022\014\n\010SUNSHINE\020\006*Z\n\013TrickerTyp" | |||||
| "e\022\025\n\021NULL_TRICKER_TYPE\020\000\022\014\n\010ASSASSIN\020\001\022\010" | |||||
| "\n\004KLEE\020\002\022\022\n\016A_NOISY_PERSON\020\003\022\010\n\004IDOL\020\004*P" | |||||
| "\n\tGameState\022\023\n\017NULL_GAME_STATE\020\000\022\016\n\nGAME" | |||||
| "_START\020\001\022\020\n\014GAME_RUNNING\020\002\022\014\n\010GAME_END\020\003" | |||||
| "b\006proto3"; | |||||
| "\n\021MessageType.proto\022\010protobuf*\177\n\nBulletT" | |||||
| "ype\022\024\n\020NULL_BULLET_TYPE\020\000\022\020\n\014FLYING_KNIF" | |||||
| "E\020\001\022\034\n\030COMMON_ATTACK_OF_TRICKER\020\002\022\r\n\tBOM" | |||||
| "B_BOMB\020\003\022\020\n\014JUMPY_DUMPTY\020\004\022\n\n\006STRIKE\020\005*\241" | |||||
| "\001\n\tPlaceType\022\023\n\017NULL_PLACE_TYPE\020\000\022\010\n\004LAN" | |||||
| "D\020\001\022\010\n\004WALL\020\002\022\t\n\005GRASS\020\003\022\r\n\tCLASSROOM\020\004\022" | |||||
| "\010\n\004GATE\020\005\022\017\n\013HIDDEN_GATE\020\006\022\n\n\006WINDOW\020\007\022\t" | |||||
| "\n\005DOOR3\020\010\022\t\n\005DOOR5\020\t\022\t\n\005DOOR6\020\n\022\t\n\005CHEST" | |||||
| "\020\013*8\n\tShapeType\022\023\n\017NULL_SHAPE_TYPE\020\000\022\n\n\006" | |||||
| "CIRCLE\020\001\022\n\n\006SQUARE\020\002*\302\001\n\010PropType\022\022\n\016NUL" | |||||
| "L_PROP_TYPE\020\000\022\r\n\tADD_SPEED\020\001\022\035\n\031ADD_LIFE" | |||||
| "_OR_CLAIRAUDIENCE\020\002\022\020\n\014ADD_HP_OR_AP\020\003\022\023\n" | |||||
| "\017SHIELD_OR_SPEAR\020\004\022\010\n\004KEY3\020\005\022\010\n\004KEY5\020\006\022\010" | |||||
| "\n\004KEY6\020\007\022\033\n\027RECOVERY_FROM_DIZZINESS\020\010\022\022\n" | |||||
| "\016CRAFTING_BENCH\020\t*n\n\017StudentBuffType\022\023\n\017" | |||||
| "NULL_SBUFF_TYPE\020\000\022\025\n\021STUDENT_ADD_SPEED\020\001" | |||||
| "\022\014\n\010ADD_LIFE\020\002\022\n\n\006SHIELD\020\003\022\025\n\021STUDENT_IN" | |||||
| "VISIBLE\020\004*\251\002\n\013PlayerState\022\017\n\013NULL_STATUS" | |||||
| "\020\000\022\010\n\004IDLE\020\001\022\014\n\010LEARNING\020\002\022\014\n\010ADDICTED\020\003" | |||||
| "\022\010\n\004QUIT\020\004\022\r\n\tGRADUATED\020\005\022\013\n\007TREATED\020\006\022\013" | |||||
| "\n\007RESCUED\020\007\022\013\n\007STUNNED\020\010\022\014\n\010TREATING\020\t\022\014" | |||||
| "\n\010RESCUING\020\n\022\014\n\010SWINGING\020\013\022\r\n\tATTACKING\020" | |||||
| "\014\022\013\n\007LOCKING\020\r\022\r\n\tRUMMAGING\020\016\022\014\n\010CLIMBIN" | |||||
| "G\020\017\022\023\n\017OPENING_A_CHEST\020\020\022\027\n\023USING_SPECIA" | |||||
| "L_SKILL\020\021\022\022\n\016OPENING_A_GATE\020\022*~\n\017Tricker" | |||||
| "BuffType\022\023\n\017NULL_TBUFF_TYPE\020\000\022\025\n\021TRICKER" | |||||
| "_ADD_SPEED\020\001\022\t\n\005SPEAR\020\002\022\n\n\006ADD_AP\020\003\022\021\n\rC" | |||||
| "LAIRAUDIENCE\020\004\022\025\n\021TRICKER_INVISIBLE\020\005*J\n" | |||||
| "\nPlayerType\022\024\n\020NULL_PLAYER_TYPE\020\000\022\022\n\016STU" | |||||
| "DENT_PLAYER\020\001\022\022\n\016TRICKER_PLAYER\020\002*\177\n\013Stu" | |||||
| "dentType\022\025\n\021NULL_STUDENT_TYPE\020\000\022\013\n\007ATHLE" | |||||
| "TE\020\001\022\013\n\007TEACHER\020\002\022\026\n\022STRAIGHT_A_STUDENT\020" | |||||
| "\003\022\t\n\005ROBOT\020\004\022\016\n\nTECH_OTAKU\020\005\022\014\n\010SUNSHINE" | |||||
| "\020\006*Z\n\013TrickerType\022\025\n\021NULL_TRICKER_TYPE\020\000" | |||||
| "\022\014\n\010ASSASSIN\020\001\022\010\n\004KLEE\020\002\022\022\n\016A_NOISY_PERS" | |||||
| "ON\020\003\022\010\n\004IDOL\020\004*P\n\tGameState\022\023\n\017NULL_GAME" | |||||
| "_STATE\020\000\022\016\n\nGAME_START\020\001\022\020\n\014GAME_RUNNING" | |||||
| "\020\002\022\014\n\010GAME_END\020\003b\006proto3"; | |||||
| static ::_pbi::once_flag descriptor_table_MessageType_2eproto_once; | static ::_pbi::once_flag descriptor_table_MessageType_2eproto_once; | ||||
| const ::_pbi::DescriptorTable descriptor_table_MessageType_2eproto = { | const ::_pbi::DescriptorTable descriptor_table_MessageType_2eproto = { | ||||
| false, | false, | ||||
| false, | false, | ||||
| 1488, | |||||
| 1504, | |||||
| descriptor_table_protodef_MessageType_2eproto, | descriptor_table_protodef_MessageType_2eproto, | ||||
| "MessageType.proto", | "MessageType.proto", | ||||
| &descriptor_table_MessageType_2eproto_once, | &descriptor_table_MessageType_2eproto_once, | ||||
| @@ -179,6 +179,7 @@ namespace protobuf | |||||
| case 6: | case 6: | ||||
| case 7: | case 7: | ||||
| case 8: | case 8: | ||||
| case 9: | |||||
| return true; | return true; | ||||
| default: | default: | ||||
| return false; | return false; | ||||
| @@ -57,13 +57,13 @@ namespace protobuf | |||||
| COMMON_ATTACK_OF_TRICKER = 2, | COMMON_ATTACK_OF_TRICKER = 2, | ||||
| BOMB_BOMB = 3, | BOMB_BOMB = 3, | ||||
| JUMPY_DUMPTY = 4, | JUMPY_DUMPTY = 4, | ||||
| ATOM_BOMB = 5, | |||||
| STRIKE = 5, | |||||
| BulletType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), | BulletType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), | ||||
| BulletType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() | BulletType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() | ||||
| }; | }; | ||||
| bool BulletType_IsValid(int value); | bool BulletType_IsValid(int value); | ||||
| constexpr BulletType BulletType_MIN = NULL_BULLET_TYPE; | constexpr BulletType BulletType_MIN = NULL_BULLET_TYPE; | ||||
| constexpr BulletType BulletType_MAX = ATOM_BOMB; | |||||
| constexpr BulletType BulletType_MAX = STRIKE; | |||||
| constexpr int BulletType_ARRAYSIZE = BulletType_MAX + 1; | constexpr int BulletType_ARRAYSIZE = BulletType_MAX + 1; | ||||
| const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* BulletType_descriptor(); | const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* BulletType_descriptor(); | ||||
| @@ -163,12 +163,13 @@ namespace protobuf | |||||
| KEY5 = 6, | KEY5 = 6, | ||||
| KEY6 = 7, | KEY6 = 7, | ||||
| RECOVERY_FROM_DIZZINESS = 8, | RECOVERY_FROM_DIZZINESS = 8, | ||||
| CRAFTING_BENCH = 9, | |||||
| PropType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), | PropType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), | ||||
| PropType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() | PropType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() | ||||
| }; | }; | ||||
| bool PropType_IsValid(int value); | bool PropType_IsValid(int value); | ||||
| constexpr PropType PropType_MIN = NULL_PROP_TYPE; | constexpr PropType PropType_MIN = NULL_PROP_TYPE; | ||||
| constexpr PropType PropType_MAX = RECOVERY_FROM_DIZZINESS; | |||||
| constexpr PropType PropType_MAX = CRAFTING_BENCH; | |||||
| constexpr int PropType_ARRAYSIZE = PropType_MAX + 1; | constexpr int PropType_ARRAYSIZE = PropType_MAX + 1; | ||||
| const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* PropType_descriptor(); | const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* PropType_descriptor(); | ||||
| @@ -43,8 +43,8 @@ class StudentAPI(IStudentAPI, IGameTimer): | |||||
| def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: | def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.ThrowProp, propType) | return self.__pool.submit(self.__logic.ThrowProp, propType) | ||||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||||
| return self.__pool.submit(self.__logic.UseSkill, skillID) | |||||
| def UseSkill(self, skillID: int, skillParam: int = 0) -> Future[bool]: | |||||
| return self.__pool.submit(self.__logic.UseSkill, skillID, skillParam) | |||||
| # 与地图交互相关 | # 与地图交互相关 | ||||
| def OpenDoor(self) -> Future[bool]: | def OpenDoor(self) -> Future[bool]: | ||||
| @@ -224,8 +224,8 @@ class TrickerAPI(ITrickerAPI, IGameTimer): | |||||
| def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: | def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.ThrowProp, propType) | return self.__pool.submit(self.__logic.ThrowProp, propType) | ||||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||||
| return self.__pool.submit(self.__logic.UseSkill, skillID) | |||||
| def UseSkill(self, skillID: int, skillParam: int = 0) -> Future[bool]: | |||||
| return self.__pool.submit(self.__logic.UseSkill, skillID, skillParam) | |||||
| # 与地图交互相关 | # 与地图交互相关 | ||||
| def OpenDoor(self) -> Future[bool]: | def OpenDoor(self) -> Future[bool]: | ||||
| @@ -91,14 +91,14 @@ class Communication: | |||||
| else: | else: | ||||
| return throwResult.act_success | return throwResult.act_success | ||||
| def UseSkill(self, skillID: int, playerID: int) -> bool: | |||||
| def UseSkill(self, skillID: int, skillParam: int, playerID: int) -> bool: | |||||
| try: | try: | ||||
| with self.__mtxLimit: | with self.__mtxLimit: | ||||
| if self.__counter >= self.__limit: | if self.__counter >= self.__limit: | ||||
| return False | return False | ||||
| self.__counter += 1 | self.__counter += 1 | ||||
| useResult = self.__THUAI6Stub.UseSkill( | useResult = self.__THUAI6Stub.UseSkill( | ||||
| THUAI62Proto.THUAI62ProtobufSkill(skillID, playerID) | |||||
| THUAI62Proto.THUAI62ProtobufSkill(skillID, skillParam, playerID) | |||||
| ) | ) | ||||
| except grpc.RpcError as e: | except grpc.RpcError as e: | ||||
| return False | return False | ||||
| @@ -132,13 +132,13 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||||
| return self.__pool.submit(logThrow) | return self.__pool.submit(logThrow) | ||||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||||
| def UseSkill(self, skillID: int, skillParam: int = 0) -> Future[bool]: | |||||
| self.__logger.info( | self.__logger.info( | ||||
| f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms" | |||||
| f"UseSkill: skillID = {skillID}, skillParam = {skillParam}, called at {self.__GetTime()}ms" | |||||
| ) | ) | ||||
| def logUse() -> bool: | def logUse() -> bool: | ||||
| result = self.__logic.UseSkill(skillID) | |||||
| result = self.__logic.UseSkill(skillID, skillParam) | |||||
| if not result: | if not result: | ||||
| self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms") | self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms") | ||||
| return result | return result | ||||
| @@ -600,13 +600,13 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||||
| return self.__pool.submit(logThrow) | return self.__pool.submit(logThrow) | ||||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||||
| def UseSkill(self, skillID: int, skillParam: int = 0) -> Future[bool]: | |||||
| self.__logger.info( | self.__logger.info( | ||||
| f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms" | |||||
| f"UseSkill: skillID = {skillID}, skillParam = {skillParam}, called at {self.__GetTime()}ms" | |||||
| ) | ) | ||||
| def logUse() -> bool: | def logUse() -> bool: | ||||
| result = self.__logic.UseSkill(skillID) | |||||
| result = self.__logic.UseSkill(skillID, skillParam) | |||||
| if not result: | if not result: | ||||
| self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms") | self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms") | ||||
| return result | return result | ||||
| @@ -80,7 +80,7 @@ class ILogic(metaclass=ABCMeta): | |||||
| pass | pass | ||||
| @abstractmethod | @abstractmethod | ||||
| def UseSkill(self, skillID: int) -> bool: | |||||
| def UseSkill(self, skillID: int, skillParam: int) -> bool: | |||||
| pass | pass | ||||
| @abstractmethod | @abstractmethod | ||||
| @@ -201,7 +201,7 @@ class IAPI(metaclass=ABCMeta): | |||||
| pass | pass | ||||
| @abstractmethod | @abstractmethod | ||||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||||
| def UseSkill(self, skillID: int, skillParam: int = 0) -> Future[bool]: | |||||
| pass | pass | ||||
| @abstractmethod | @abstractmethod | ||||
| @@ -190,9 +190,9 @@ class Logic(ILogic): | |||||
| self.__logger.debug("Called ThrowProp") | self.__logger.debug("Called ThrowProp") | ||||
| return self.__comm.ThrowProp(propType, self.__playerID) | return self.__comm.ThrowProp(propType, self.__playerID) | ||||
| def UseSkill(self, skillID: int) -> bool: | |||||
| def UseSkill(self, skillID: int, skillParam: int) -> bool: | |||||
| self.__logger.debug("Called UseSkill") | self.__logger.debug("Called UseSkill") | ||||
| return self.__comm.UseSkill(skillID, self.__playerID) | |||||
| return self.__comm.UseSkill(skillID, skillParam, self.__playerID) | |||||
| def SendMessage(self, toID: int, message: Union[str, bytes]) -> bool: | def SendMessage(self, toID: int, message: Union[str, bytes]) -> bool: | ||||
| self.__logger.debug("Called SendMessage") | self.__logger.debug("Called SendMessage") | ||||
| @@ -52,6 +52,7 @@ class PropType(Enum): | |||||
| AddHpOrAp = 6 | AddHpOrAp = 6 | ||||
| ShieldOrSpear = 7 | ShieldOrSpear = 7 | ||||
| RecoveryFromDizziness = 8 | RecoveryFromDizziness = 8 | ||||
| CraftingBench = 9 | |||||
| class BulletType(Enum): | class BulletType(Enum): | ||||
| @@ -60,7 +61,7 @@ class BulletType(Enum): | |||||
| CommonAttackOfTricker = 2 | CommonAttackOfTricker = 2 | ||||
| BombBomb = 3 | BombBomb = 3 | ||||
| JumpyDumpty = 4 | JumpyDumpty = 4 | ||||
| AtomBomb = 5 | |||||
| Strike = 5 | |||||
| class StudentType(Enum): | class StudentType(Enum): | ||||
| @@ -109,6 +109,7 @@ class Proto2THUAI6(NoInstance): | |||||
| MessageType.ADD_LIFE_OR_CLAIRAUDIENCE: THUAI6.PropType.AddLifeOrClairaudience, | MessageType.ADD_LIFE_OR_CLAIRAUDIENCE: THUAI6.PropType.AddLifeOrClairaudience, | ||||
| MessageType.SHIELD_OR_SPEAR: THUAI6.PropType.ShieldOrSpear, | MessageType.SHIELD_OR_SPEAR: THUAI6.PropType.ShieldOrSpear, | ||||
| MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness, | MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness, | ||||
| MessageType.CRAFTING_BENCH: THUAI6.PropType.CraftingBench, | |||||
| } | } | ||||
| playerTypeDict: Final[dict] = { | playerTypeDict: Final[dict] = { | ||||
| @@ -187,7 +188,7 @@ class Proto2THUAI6(NoInstance): | |||||
| MessageType.BOMB_BOMB: THUAI6.BulletType.BombBomb, | MessageType.BOMB_BOMB: THUAI6.BulletType.BombBomb, | ||||
| MessageType.COMMON_ATTACK_OF_TRICKER: THUAI6.BulletType.CommonAttackOfTricker, | MessageType.COMMON_ATTACK_OF_TRICKER: THUAI6.BulletType.CommonAttackOfTricker, | ||||
| MessageType.JUMPY_DUMPTY: THUAI6.BulletType.JumpyDumpty, | MessageType.JUMPY_DUMPTY: THUAI6.BulletType.JumpyDumpty, | ||||
| MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb, | |||||
| MessageType.STRIKE: THUAI6.BulletType.Strike, | |||||
| } | } | ||||
| # 用于将Proto的对象转为THUAI6的对象 | # 用于将Proto的对象转为THUAI6的对象 | ||||
| @@ -357,6 +358,7 @@ class THUAI62Proto(NoInstance): | |||||
| THUAI6.PropType.AddLifeOrClairaudience: MessageType.ADD_LIFE_OR_CLAIRAUDIENCE, | THUAI6.PropType.AddLifeOrClairaudience: MessageType.ADD_LIFE_OR_CLAIRAUDIENCE, | ||||
| THUAI6.PropType.AddSpeed: MessageType.ADD_SPEED, | THUAI6.PropType.AddSpeed: MessageType.ADD_SPEED, | ||||
| THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, | THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, | ||||
| THUAI6.PropType.CraftingBench: MessageType.CRAFTING_BENCH, | |||||
| } | } | ||||
| # 用于将THUAI6的对象转为Proto的对象 | # 用于将THUAI6的对象转为Proto的对象 | ||||
| @@ -421,5 +423,9 @@ class THUAI62Proto(NoInstance): | |||||
| return Message2Server.AttackMsg(player_id=id, angle=angle) | return Message2Server.AttackMsg(player_id=id, angle=angle) | ||||
| @staticmethod | @staticmethod | ||||
| def THUAI62ProtobufSkill(skillID: int, id: int) -> Message2Server.SkillMsg: | |||||
| return Message2Server.SkillMsg(player_id=id, skill_id=skillID) | |||||
| def THUAI62ProtobufSkill( | |||||
| skillID: int, skillParam: int, id: int | |||||
| ) -> Message2Server.SkillMsg: | |||||
| return Message2Server.SkillMsg( | |||||
| player_id=id, skill_id=skillID, skill_param=skillParam | |||||
| ) | |||||
| @@ -1,3 +1,3 @@ | |||||
| grpcio==1.54.0 | |||||
| grpcio-tools==1.54.0 | |||||
| grpcio==1.54.2 | |||||
| grpcio-tools==1.54.2 | |||||
| numpy | numpy | ||||
| @@ -61,6 +61,7 @@ message SkillMsg | |||||
| { | { | ||||
| int64 player_id = 1; | int64 player_id = 1; | ||||
| int32 skill_id = 2; | int32 skill_id = 2; | ||||
| int32 skill_param = 3; | |||||
| } | } | ||||
| // 基本继承于THUAI5,为了使发送的信息尽可能不被浪费,暂定不发这类大包。 | // 基本继承于THUAI5,为了使发送的信息尽可能不被浪费,暂定不发这类大包。 | ||||
| @@ -9,7 +9,7 @@ enum BulletType | |||||
| COMMON_ATTACK_OF_TRICKER = 2; | COMMON_ATTACK_OF_TRICKER = 2; | ||||
| BOMB_BOMB = 3; | BOMB_BOMB = 3; | ||||
| JUMPY_DUMPTY = 4; | JUMPY_DUMPTY = 4; | ||||
| ATOM_BOMB = 5; | |||||
| STRIKE = 5; | |||||
| } | } | ||||
| enum PlaceType // 地图中的所有物件类型 | enum PlaceType // 地图中的所有物件类型 | ||||
| @@ -49,6 +49,7 @@ enum PropType // 地图中的可拾取道具类型 | |||||
| KEY5 = 6; | KEY5 = 6; | ||||
| KEY6 = 7; | KEY6 = 7; | ||||
| RECOVERY_FROM_DIZZINESS = 8; | RECOVERY_FROM_DIZZINESS = 8; | ||||
| CRAFTING_BENCH = 9; | |||||
| } | } | ||||
| enum StudentBuffType // 人类可用的增益效果类型 | enum StudentBuffType // 人类可用的增益效果类型 | ||||
| @@ -78,7 +79,7 @@ enum PlayerState | |||||
| LOCKING = 13; | LOCKING = 13; | ||||
| RUMMAGING = 14; | RUMMAGING = 14; | ||||
| CLIMBING = 15; // 翻窗 | CLIMBING = 15; // 翻窗 | ||||
| OPENING_A_CHEST =16; | |||||
| OPENING_A_CHEST = 16; | |||||
| USING_SPECIAL_SKILL = 17; | USING_SPECIAL_SKILL = 17; | ||||
| OPENING_A_GATE =18; | OPENING_A_GATE =18; | ||||
| } | } | ||||
| @@ -109,7 +110,7 @@ enum StudentType | |||||
| TEACHER = 2; | TEACHER = 2; | ||||
| STRAIGHT_A_STUDENT = 3; | STRAIGHT_A_STUDENT = 3; | ||||
| ROBOT = 4; | ROBOT = 4; | ||||
| TECH_OTAKU =5; | |||||
| TECH_OTAKU = 5; | |||||
| SUNSHINE = 6; | SUNSHINE = 6; | ||||
| } | } | ||||
| @@ -309,7 +309,7 @@ $$ | |||||
| - 不鼓励选手面向地图编程,因为移动过程中你可以受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。 | - 不鼓励选手面向地图编程,因为移动过程中你可以受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。 | ||||
| ### 人物 | ### 人物 | ||||
| - 眩晕状态中的玩家不能再次被眩晕 | |||||
| - 眩晕状态中的玩家不能再次被眩晕(除非是ShowTime) | |||||
| ### 初始状态 | ### 初始状态 | ||||
| - 初赛玩家出生点固定且一定为空地 | - 初赛玩家出生点固定且一定为空地 | ||||
| @@ -342,6 +342,7 @@ $$ | |||||
| - 开锁门进度中断后清空 | - 开锁门进度中断后清空 | ||||
| ### 窗 | ### 窗 | ||||
| - 由于窗户被占用导致翻窗失败会使先前行动停止 | |||||
| - 翻越窗户是一种交互行为,翻窗一共有两个过程 | - 翻越窗户是一种交互行为,翻窗一共有两个过程 | ||||
| - 跳上窗:从当前位置到窗边缘中点,位置瞬移,时间=距离/爬窗速度。中断时,停留在原位置 | - 跳上窗:从当前位置到窗边缘中点,位置瞬移,时间=距离/爬窗速度。中断时,停留在原位置 | ||||
| - 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度。中断时,停留在另一侧格子中心 | - 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度。中断时,停留在另一侧格子中心 | ||||
| @@ -1,5 +1,5 @@ | |||||
| # 游戏机制与平衡性调整更新草案 | # 游戏机制与平衡性调整更新草案 | ||||
| v1.5 | |||||
| v1.6 | |||||
| ## 说明 | ## 说明 | ||||
| - 该草案尚未完全确定,请大家不要过分依靠该文档进行修改自己的代码 | - 该草案尚未完全确定,请大家不要过分依靠该文档进行修改自己的代码 | ||||
| @@ -21,9 +21,9 @@ v1.5 | |||||
| - 未攻击至目标时的后摇改为1200ms | - 未攻击至目标时的后摇改为1200ms | ||||
| - 增强为“可以攻击未写完的作业” | - 增强为“可以攻击未写完的作业” | ||||
| - 增强为“可以攻击使门被打开(可以重新被锁上)” | - 增强为“可以攻击使门被打开(可以重新被锁上)” | ||||
| - 改为“当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上90°,180° ,270° 发出3个小炸弹” | |||||
| - 小炸弹JumpyDumpty | - 小炸弹JumpyDumpty | ||||
| - 小炸弹不受道具增益影响 | - 小炸弹不受道具增益影响 | ||||
| - 修改为“小炸弹与自己无碰撞体积” | |||||
| - strike(新增) | - strike(新增) | ||||
| - 可以攻击未写完的作业 | - 可以攻击未写完的作业 | ||||
| @@ -105,3 +105,14 @@ v1.5 | |||||
| - 普通攻击改为strike | - 普通攻击改为strike | ||||
| - Klee | - Klee | ||||
| - 被动技能Lucky!(新增):开局获得随机的一个道具(不会是钥匙) | - 被动技能Lucky!(新增):开局获得随机的一个道具(不会是钥匙) | ||||
| - 主动技能SparksNSplash(新增): | |||||
| - CD:45s, 持续时间:10s | |||||
| - 技能使用瞬间,对于输入的额外参数PlayerID代表的角色,距离最近的本已停止运动的小炸弹开始追踪该角色(每50ms向该角色直线移动) | |||||
| - 主动技能 蹦蹦炸弹 JumpyBomb | |||||
| - 当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上0°,45°,90°,135°,180°,225°,270°,315° 发出8个小炸弹 | |||||
| - Idol | |||||
| 主动技能ShowTime改为 | |||||
| "持续时间内 | |||||
| - 使警戒范围外的学生眩晕并每**500ms**发送向自己移动**500ms**的指令(速度为学生本应速度*二者距离/警戒范围) | |||||
| - 对于视野范围(不是可视区域)内的学生每**500ms**加**1500**的沉迷度 | |||||
| - 捣蛋鬼变为0.8倍速" | |||||
| @@ -21,11 +21,14 @@ | |||||
| - docs:更新了 游戏机制与平衡性调整更新草案.pdf | - docs:更新了 游戏机制与平衡性调整更新草案.pdf | ||||
| - change:更改了地图的文件路径 | - change:更改了地图的文件路径 | ||||
| # 最新更新 | |||||
| # 5月10日更新 | |||||
| - fix:修复JumpyDumpty的初始位置错误的问题 | - fix:修复JumpyDumpty的初始位置错误的问题 | ||||
| - fix:修正和重新说明攻击距离 | - fix:修正和重新说明攻击距离 | ||||
| - **攻击距离是指攻击(子弹)的移动距离,也就是说理论上最远被攻击的学生的中心与捣蛋鬼的中心=学生的半径+捣蛋鬼的半径+攻击距离+子弹半径(200)×2** | - **攻击距离是指攻击(子弹)的移动距离,也就是说理论上最远被攻击的学生的中心与捣蛋鬼的中心=学生的半径+捣蛋鬼的半径+攻击距离+子弹半径(200)×2** | ||||
| - hotfix:修复小炸弹初始化类型错误的问题 | - hotfix:修复小炸弹初始化类型错误的问题 | ||||
| - remove:去除了“实际上唤醒或勉励不同的人是有效的” | - remove:去除了“实际上唤醒或勉励不同的人是有效的” | ||||
| - **重复发出同一类型的交互指令和移动指令是无效的** | - **重复发出同一类型的交互指令和移动指令是无效的** | ||||
| - feat&fix:修复并**将`SendMessage`改为`SendTextMessage`与`SendBinaryMessage`** | |||||
| - feat&fix:修复并**将`SendMessage`改为`SendTextMessage`与`SendBinaryMessage`** | |||||
| # 最新更新 | |||||
| - docs:更新了 游戏机制与平衡性调整更新草案.pdf | |||||
| @@ -52,7 +52,7 @@ | |||||
| <Button Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Name="UninstBtn" Content="卸载选手包" Command="{Binding ClickUninstCommand}" Visibility="{Binding MenuVis}" /> | <Button Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Name="UninstBtn" Content="卸载选手包" Command="{Binding ClickUninstCommand}" Visibility="{Binding MenuVis}" /> | ||||
| <Button Grid.Row="7" Grid.Column="2" Grid.ColumnSpan="2" Name="MenuBackBtn" Content="回到登陆界面" Command="{Binding ClickBackCommand}" Visibility="{Binding MenuVis}" /> | <Button Grid.Row="7" Grid.Column="2" Grid.ColumnSpan="2" Name="MenuBackBtn" Content="回到登陆界面" Command="{Binding ClickBackCommand}" Visibility="{Binding MenuVis}" /> | ||||
| <TextBlock Grid.Row="3" Grid.Column="3" Text="正在处理……" Grid.ColumnSpan="2" Visibility="{Binding ProgressVis}"/> | |||||
| <TextBlock Grid.Row="3" Grid.Column="3" Text="{Binding ProcessingIntro}" Grid.ColumnSpan="2" Visibility="{Binding ProgressVis}"/> | |||||
| <ProgressBar Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="7" Minimum="0" Maximum="100" Name="Progress" Visibility="{Binding ProgressVis}" IsIndeterminate="True"/> | <ProgressBar Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="7" Minimum="0" Maximum="100" Name="Progress" Visibility="{Binding ProgressVis}" IsIndeterminate="True"/> | ||||
| <TextBlock Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="4" Text="操作完成!你可以继续操作或退出" Visibility="{Binding CompleteVis}"/> | <TextBlock Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="4" Text="操作完成!你可以继续操作或退出" Visibility="{Binding CompleteVis}"/> | ||||
| @@ -81,10 +81,21 @@ | |||||
| <TextBlock Grid.Row="5" Grid.Column="1" Foreground="Red" Text=" 用户名或密码错误!" Visibility="{Binding LoginFailVis}"/> | <TextBlock Grid.Row="5" Grid.Column="1" Foreground="Red" Text=" 用户名或密码错误!" Visibility="{Binding LoginFailVis}"/> | ||||
| </Grid> | </Grid> | ||||
| </StackPanel> | </StackPanel> | ||||
| <Button Grid.Row="7" Grid.Column="1" Name="Login" Content="登录" Command="{Binding ClickLoginCommand}" Visibility="{Binding LoginVis}"/> | |||||
| <Button Grid.Row="7" Grid.Column="2" Name="Launch" FontSize="11" Content="{Binding LaunchBtnCont}" Command="{Binding ClickLaunchCommand}" Visibility="{Binding LoginVis}"/> | |||||
| <Button Grid.Row="7" Grid.Column="3" Name="ShiftLanguage" FontSize="11" Content="更改语言" Command="{Binding ClickShiftLanguageCommand}" Visibility="{Binding LaunchVis}"/> | |||||
| <StackPanel Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="3"> | |||||
| <Grid> | |||||
| <Grid.RowDefinitions> | |||||
| <RowDefinition Height="20"/> | |||||
| </Grid.RowDefinitions> | |||||
| <Grid.ColumnDefinitions> | |||||
| <ColumnDefinition Width="70"/> | |||||
| <ColumnDefinition Width="70"/> | |||||
| <ColumnDefinition Width="60"/> | |||||
| </Grid.ColumnDefinitions> | |||||
| <Button Grid.Row="0" Grid.Column="0" Name="Login" Content="登录" Command="{Binding ClickLoginCommand}" Visibility="{Binding LoginVis}"/> | |||||
| <Button Grid.Row="0" Grid.Column="1" Name="Launch" Content="{Binding LaunchBtnCont}" Command="{Binding ClickLaunchCommand}" Visibility="{Binding LoginVis}" IsEnabled="{Binding UpdatePlanned}"/> | |||||
| <Button Grid.Row="0" Grid.Column="2" Name="ShiftLanguage" FontSize="11" Content="配置启动器" Command="{Binding ClickShiftLanguageCommand}" Visibility="{Binding LaunchVis}" IsEnabled="False"/> | |||||
| </Grid> | |||||
| </StackPanel> | |||||
| <Button Grid.Row="7" Grid.Column="4" Grid.ColumnSpan="2" Name="Edit" Content="修改文件" Command="{Binding ClickEditCommand}" Visibility="{Binding LoginVis}"/> | <Button Grid.Row="7" Grid.Column="4" Grid.ColumnSpan="2" Name="Edit" Content="修改文件" Command="{Binding ClickEditCommand}" Visibility="{Binding LoginVis}"/> | ||||
| @@ -114,5 +125,40 @@ | |||||
| <Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" IsEnabled="False" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" /> | <Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" IsEnabled="False" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" /> | ||||
| <TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="暂不支持" IsEnabled="False" Visibility="{Binding WebVis}" /> | <TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="暂不支持" IsEnabled="False" Visibility="{Binding WebVis}" /> | ||||
| <!--objects below are enabled--> | |||||
| <StackPanel Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="7"> | |||||
| <Grid> | |||||
| <Grid.RowDefinitions> | |||||
| <RowDefinition Height="20"/> | |||||
| </Grid.RowDefinitions> | |||||
| <Grid.ColumnDefinitions> | |||||
| <ColumnDefinition Width="90"/> | |||||
| <ColumnDefinition Width="90"/> | |||||
| <ColumnDefinition Width="90"/> | |||||
| <ColumnDefinition Width="*"/> | |||||
| </Grid.ColumnDefinitions> | |||||
| <Button Grid.Column="0" Name ="ConfigServer" Content="服务端" Command="{Binding ClickCfgServCommand}" IsEnabled="{Binding ServerCfgNotSelected}" Visibility="{Binding CfgVis}"/> | |||||
| <Button Grid.Column="1" Name ="ConfigAI" Content="客户端" Command="{Binding ClickCfgCliCommand}" IsEnabled="{Binding CliCfhNotSelected}" Visibility="{Binding CfgVis}"/> | |||||
| <Button Grid.Column="2" Name ="ConfigCliend" Content="图形界面" Command="{Binding ClickCfgGUICommand}" IsEnabled="{Binding GUICfgNotSelected}" Visibility="{Binding CfgVis}"/> | |||||
| </Grid> | |||||
| </StackPanel> | |||||
| <StackPanel Grid.Row="3" Grid.Column="1" Grid.RowSpan="5" Grid.ColumnSpan="7"> | |||||
| <Grid> | |||||
| <Grid.RowDefinitions> | |||||
| <RowDefinition Height="20"/> | |||||
| <RowDefinition Height="20"/> | |||||
| <RowDefinition Height="20"/> | |||||
| <RowDefinition Height="20"/> | |||||
| <RowDefinition Height="20"/> | |||||
| </Grid.RowDefinitions> | |||||
| <Grid.ColumnDefinitions> | |||||
| <ColumnDefinition Width="50"/> | |||||
| <ColumnDefinition Width="75"/> | |||||
| <ColumnDefinition Width="25"/> | |||||
| <ColumnDefinition Width="75"/> | |||||
| <ColumnDefinition Width="*"/> | |||||
| </Grid.ColumnDefinitions> | |||||
| </Grid> | |||||
| </StackPanel> | |||||
| </Grid> | </Grid> | ||||
| </Window> | </Window> | ||||
| @@ -405,7 +405,7 @@ namespace starter.viewmodel.settings | |||||
| /// <summary> | /// <summary> | ||||
| /// 关于介绍的屏幕显示信息 | /// 关于介绍的屏幕显示信息 | ||||
| /// </summary> | /// </summary> | ||||
| public enum Status { newUser, menu, move, working, disconnected, error, successful, login, web }; | |||||
| public enum Status { newUser, menu, move, working, initializing, disconnected, error, successful, login, web, launch }; | |||||
| public Status status | public Status status | ||||
| { | { | ||||
| get; set; | get; set; | ||||
| @@ -881,7 +881,7 @@ namespace Downloader | |||||
| int upcnt = updateFileName.Count; | int upcnt = updateFileName.Count; | ||||
| if (upcnt <= 20) | if (upcnt <= 20) | ||||
| { | { | ||||
| while (newFileName.TryDequeue(out var filename)) | |||||
| while (updateFileName.TryDequeue(out var filename)) | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| @@ -22,6 +22,7 @@ namespace starter.viewmodel.settings | |||||
| //定义BackgroundWorker | //定义BackgroundWorker | ||||
| BackgroundWorker asyncDownloader; | BackgroundWorker asyncDownloader; | ||||
| BackgroundWorker asyncUpdater; | BackgroundWorker asyncUpdater; | ||||
| BackgroundWorker asyncInitializer; | |||||
| /// <summary> | /// <summary> | ||||
| /// Model object | /// Model object | ||||
| /// </summary> | /// </summary> | ||||
| @@ -38,7 +39,7 @@ namespace starter.viewmodel.settings | |||||
| Status = SettingsModel.Status.working; | Status = SettingsModel.Status.working; | ||||
| string currentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName) | string currentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName) | ||||
| ?? throw new Exception("Fail to get current directory"); | ?? throw new Exception("Fail to get current directory"); | ||||
| MessageBox.Show("更新器工作正常"); | |||||
| //MessageBox.Show("更新器工作正常"); | |||||
| if (!Program.Tencent_cos_download.SelfUpdateDismissed()) | if (!Program.Tencent_cos_download.SelfUpdateDismissed()) | ||||
| { | { | ||||
| switch (Program.Tencent_cos_download.CheckSelfVersion()) | switch (Program.Tencent_cos_download.CheckSelfVersion()) | ||||
| @@ -53,49 +54,91 @@ namespace starter.viewmodel.settings | |||||
| } | } | ||||
| } | } | ||||
| //实例化BackgroundWorker | |||||
| asyncDownloader = new BackgroundWorker(); | |||||
| asyncUpdater = new BackgroundWorker(); | |||||
| //指示BackgroundWorker是否可以报告进度更新 | |||||
| //当该属性值为True是,将可以成功调用ReportProgress方法,否则将引发InvalidOperationException异常。 | |||||
| asyncDownloader.WorkerReportsProgress = true; | |||||
| asyncUpdater.WorkerReportsProgress = true; | |||||
| //挂载方法: | |||||
| asyncDownloader.DoWork += AsyncDownloader_DoWork; | |||||
| asyncUpdater.DoWork += AsyncUpdater_DoWork; | |||||
| //完成通知器: | |||||
| asyncDownloader.RunWorkerCompleted += AsyncDownloader_RunWorkerCompleted; | |||||
| asyncUpdater.RunWorkerCompleted += AsyncUpdater_RunWorkerCompleted; | |||||
| UpdateInfoVis = Visibility.Collapsed; | UpdateInfoVis = Visibility.Collapsed; | ||||
| if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload()) | |||||
| asyncInitializer = new BackgroundWorker(); | |||||
| asyncInitializer.WorkerReportsProgress = true; | |||||
| asyncInitializer.DoWork += AsyncInitializer_DoWork; | |||||
| asyncInitializer.RunWorkerCompleted += AsyncInitializer_RunWorkerCompleted; | |||||
| asyncInitializer.RunWorkerAsync(); | |||||
| Status = SettingsModel.Status.initializing; | |||||
| } | |||||
| private void AsyncInitializer_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) | |||||
| { | |||||
| if (e.Result == null) | |||||
| { | |||||
| Status = SettingsModel.Status.error; | |||||
| } | |||||
| else if ((int)e.Result == 1) | |||||
| { | { | ||||
| obj.checkUpdate(); | |||||
| Status = SettingsModel.Status.login; | Status = SettingsModel.Status.login; | ||||
| this.RaisePropertyChanged("WindowWidth"); | |||||
| this.RaisePropertyChanged("LaunchVis"); | this.RaisePropertyChanged("LaunchVis"); | ||||
| if (obj.RecallUser()) | |||||
| RememberMe = true; | |||||
| else | |||||
| RememberMe = false; | |||||
| this.RaisePropertyChanged("RememberMe"); | this.RaisePropertyChanged("RememberMe"); | ||||
| this.RaisePropertyChanged("SwitchOSBtnCont"); | this.RaisePropertyChanged("SwitchOSBtnCont"); | ||||
| //在启动时立刻检查更新,确保选手启动最新版选手包 | |||||
| //若有更新,将启动键改为更新键; | |||||
| //相应地,使用login界面启动; | |||||
| //结构:上方为登录框架,下方有“修改选手包”按钮 | |||||
| //下面几行是用来运行测试的代码 | |||||
| //Program.RunProgram.StartServerForDebug("0.0.0.0",8888,4,1,600,"video"); | |||||
| //Program.RunProgram.RunCpp("127.0.0.1",8888,4,1,false,true,false); | |||||
| //Program.RunProgram.RunGUIClient("127.0.0.1", 8888, 0, true); | |||||
| this.RaisePropertyChanged("UpdateBtnCont"); | |||||
| this.RaisePropertyChanged("LaunchBtnCont"); | |||||
| this.RaisePropertyChanged("Updateinfo"); | |||||
| this.RaisePropertyChanged("UpdatePlanned"); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| Route = Environment.GetEnvironmentVariable("USERPROFILE") + "\\THUAI6"; | Route = Environment.GetEnvironmentVariable("USERPROFILE") + "\\THUAI6"; | ||||
| Status = SettingsModel.Status.newUser; | Status = SettingsModel.Status.newUser; | ||||
| this.RaisePropertyChanged("WindowWidth"); | |||||
| } | |||||
| } | |||||
| private void AsyncInitializer_DoWork(object? sender, DoWorkEventArgs e) | |||||
| { | |||||
| if (asyncInitializer.CancellationPending) | |||||
| { | |||||
| Status = SettingsModel.Status.error; | |||||
| e.Cancel = true; | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| //实例化BackgroundWorker | |||||
| asyncDownloader = new BackgroundWorker(); | |||||
| asyncUpdater = new BackgroundWorker(); | |||||
| //指示BackgroundWorker是否可以报告进度更新 | |||||
| //当该属性值为True是,将可以成功调用ReportProgress方法,否则将引发InvalidOperationException异常。 | |||||
| asyncDownloader.WorkerReportsProgress = true; | |||||
| asyncUpdater.WorkerReportsProgress = true; | |||||
| //挂载方法: | |||||
| asyncDownloader.DoWork += AsyncDownloader_DoWork; | |||||
| asyncUpdater.DoWork += AsyncUpdater_DoWork; | |||||
| //完成通知器: | |||||
| asyncDownloader.RunWorkerCompleted += AsyncDownloader_RunWorkerCompleted; | |||||
| asyncUpdater.RunWorkerCompleted += AsyncUpdater_RunWorkerCompleted; | |||||
| if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload()) | |||||
| { | |||||
| obj.checkUpdate(); | |||||
| if (obj.RecallUser()) | |||||
| RememberMe = true; | |||||
| else | |||||
| RememberMe = false; | |||||
| //在启动时立刻检查更新,确保选手启动最新版选手包 | |||||
| //若有更新,将启动键改为更新键; | |||||
| //相应地,使用login界面启动; | |||||
| //结构:上方为登录框架,下方有“修改选手包”按钮 | |||||
| //下面几行是用来运行测试的代码 | |||||
| //Program.RunProgram.StartServerForDebug("0.0.0.0",8888,4,1,600,"video"); | |||||
| //Program.RunProgram.RunCpp("127.0.0.1",8888,4,1,false,true,false); | |||||
| //Program.RunProgram.RunGUIClient("127.0.0.1", 8888, 0, true); | |||||
| e.Result = 1; | |||||
| } | |||||
| else | |||||
| { | |||||
| e.Result = 2; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -153,6 +196,7 @@ namespace starter.viewmodel.settings | |||||
| this.RaisePropertyChanged("UpdateInfo"); | this.RaisePropertyChanged("UpdateInfo"); | ||||
| this.RaisePropertyChanged("LaunchBtnCont"); | this.RaisePropertyChanged("LaunchBtnCont"); | ||||
| } | } | ||||
| this.RaisePropertyChanged("UpdatePlanned"); | |||||
| } | } | ||||
| } | } | ||||
| @@ -257,6 +301,7 @@ namespace starter.viewmodel.settings | |||||
| this.RaisePropertyChanged("LaunchVis"); | this.RaisePropertyChanged("LaunchVis"); | ||||
| this.RaisePropertyChanged("NewUserVis"); | this.RaisePropertyChanged("NewUserVis"); | ||||
| this.RaisePropertyChanged("ConfirmBtnCont"); | this.RaisePropertyChanged("ConfirmBtnCont"); | ||||
| this.RaisePropertyChanged("ProcessingIntro"); | |||||
| } | } | ||||
| } | } | ||||
| public string Intro | public string Intro | ||||
| @@ -298,6 +343,21 @@ namespace starter.viewmodel.settings | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| public string ProcessingIntro | |||||
| { | |||||
| get | |||||
| { | |||||
| switch (Status) | |||||
| { | |||||
| case SettingsModel.Status.working: | |||||
| return "正在下载"; | |||||
| case SettingsModel.Status.initializing: | |||||
| return "正在检查更新"; | |||||
| default: | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| } | |||||
| public string AbortOrSelLanguage | public string AbortOrSelLanguage | ||||
| { | { | ||||
| get | get | ||||
| @@ -453,7 +513,7 @@ namespace starter.viewmodel.settings | |||||
| { | { | ||||
| get | get | ||||
| { | { | ||||
| return Status == SettingsModel.Status.working ? Visibility.Visible : Visibility.Collapsed; | |||||
| return (Status == SettingsModel.Status.working || Status == SettingsModel.Status.initializing) ? Visibility.Visible : Visibility.Collapsed; | |||||
| } | } | ||||
| } | } | ||||
| public Visibility CompleteVis | public Visibility CompleteVis | ||||
| @@ -508,6 +568,13 @@ namespace starter.viewmodel.settings | |||||
| return obj.status == SettingsModel.Status.login && (!obj.UpdatePlanned) ? Visibility.Visible : Visibility.Collapsed; | return obj.status == SettingsModel.Status.login && (!obj.UpdatePlanned) ? Visibility.Visible : Visibility.Collapsed; | ||||
| } | } | ||||
| } | } | ||||
| public Visibility CfgVis | |||||
| { | |||||
| get | |||||
| { | |||||
| return obj.status == SettingsModel.Status.launch ? Visibility.Visible : Visibility.Collapsed; | |||||
| } | |||||
| } | |||||
| public string UpdateBtnCont | public string UpdateBtnCont | ||||
| { | { | ||||
| @@ -534,9 +601,9 @@ namespace starter.viewmodel.settings | |||||
| if (obj.UpdatePlanned) | if (obj.UpdatePlanned) | ||||
| ans = "更新"; | ans = "更新"; | ||||
| else if (obj.launchLanguage == SettingsModel.LaunchLanguage.cpp) | else if (obj.launchLanguage == SettingsModel.LaunchLanguage.cpp) | ||||
| ans = "启动c++包"; | |||||
| ans = "启动选手包"; | |||||
| else | else | ||||
| ans = "启动python包"; | |||||
| ans = "启动选手包"; | |||||
| return ans; | return ans; | ||||
| } | } | ||||
| } | } | ||||
| @@ -570,6 +637,11 @@ namespace starter.viewmodel.settings | |||||
| } | } | ||||
| } | } | ||||
| public bool UpdatePlanned | |||||
| { | |||||
| get { return obj.UpdatePlanned; } | |||||
| } | |||||
| public string RouteSelectWindow(string type) | public string RouteSelectWindow(string type) | ||||
| { | { | ||||
| if (type == "Folder") | if (type == "Folder") | ||||
| @@ -719,6 +791,7 @@ namespace starter.viewmodel.settings | |||||
| this.RaisePropertyChanged("UpdateBtnCont"); | this.RaisePropertyChanged("UpdateBtnCont"); | ||||
| this.RaisePropertyChanged("UpdateInfo"); | this.RaisePropertyChanged("UpdateInfo"); | ||||
| this.RaisePropertyChanged("LaunchVis"); | this.RaisePropertyChanged("LaunchVis"); | ||||
| this.RaisePropertyChanged("UpdatePlanned"); | |||||
| } | } | ||||
| })); | })); | ||||
| } | } | ||||
| @@ -1,6 +1,5 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -27,7 +26,6 @@ namespace GameClass.GameObj | |||||
| public bool HasSpear => hasSpear; | public bool HasSpear => hasSpear; | ||||
| /// <summary> | /// <summary> | ||||
| /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="target">被尝试攻击者</param> | /// <param name="target">被尝试攻击者</param> | ||||
| /// <returns>是否可以攻击到</returns> | /// <returns>是否可以攻击到</returns> | ||||
| @@ -36,7 +34,7 @@ namespace GameClass.GameObj | |||||
| public override bool IgnoreCollideExecutor(IGameObj targetObj) | public override bool IgnoreCollideExecutor(IGameObj targetObj) | ||||
| { | { | ||||
| if (targetObj == Parent && CanMove) return true; | |||||
| if (targetObj == Parent) return true; | |||||
| if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) | if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) | ||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| @@ -1,10 +1,5 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Numerics; | |||||
| using System.Runtime.InteropServices; | |||||
| using System.Threading; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -324,7 +324,17 @@ namespace GameClass.GameObj | |||||
| return (playerState != PlayerStateType.Deceased && playerState != PlayerStateType.Escaped | return (playerState != PlayerStateType.Deceased && playerState != PlayerStateType.Escaped | ||||
| && playerState != PlayerStateType.Addicted && playerState != PlayerStateType.Rescued | && playerState != PlayerStateType.Addicted && playerState != PlayerStateType.Rescued | ||||
| && playerState != PlayerStateType.Swinging && playerState != PlayerStateType.TryingToAttack | && playerState != PlayerStateType.Swinging && playerState != PlayerStateType.TryingToAttack | ||||
| && playerState != PlayerStateType.ClimbingThroughWindows && playerState != PlayerStateType.Stunned); | |||||
| && playerState != PlayerStateType.ClimbingThroughWindows | |||||
| && playerState != PlayerStateType.Stunned && playerState != PlayerStateType.Charmed); | |||||
| } | |||||
| } | |||||
| public bool CanPinDown() | |||||
| { | |||||
| lock (actionLock) | |||||
| { | |||||
| return (playerState != PlayerStateType.Deceased && playerState != PlayerStateType.Escaped | |||||
| && playerState != PlayerStateType.Addicted && playerState != PlayerStateType.Rescued | |||||
| && playerState != PlayerStateType.Stunned && playerState != PlayerStateType.Charmed); | |||||
| } | } | ||||
| } | } | ||||
| public bool InteractingWithMapWithoutMoving() | public bool InteractingWithMapWithoutMoving() | ||||
| @@ -345,8 +355,9 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| lock (actionLock) | lock (actionLock) | ||||
| return !(playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | return !(playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | ||||
| || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued | |||||
| || playerState == PlayerStateType.Treated || playerState == PlayerStateType.Stunned | |||||
| || playerState == PlayerStateType.Addicted | |||||
| || playerState == PlayerStateType.Rescued || playerState == PlayerStateType.Treated | |||||
| || playerState == PlayerStateType.Stunned || playerState == PlayerStateType.Charmed | |||||
| || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | ||||
| } | } | ||||
| private GameObj? whatInteractingWith = null; | private GameObj? whatInteractingWith = null; | ||||
| @@ -354,28 +365,24 @@ namespace GameClass.GameObj | |||||
| public long ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | public long ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | ||||
| { | { | ||||
| lock (actionLock) | |||||
| { | |||||
| whatInteractingWith = gameObj; | |||||
| if (value != PlayerStateType.Moving) | |||||
| IsMoving = false; | |||||
| playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; | |||||
| //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); | |||||
| return ++stateNum; | |||||
| } | |||||
| //只能被SetPlayerState引用 | |||||
| whatInteractingWith = gameObj; | |||||
| if (value != PlayerStateType.Moving) | |||||
| IsMoving = false; | |||||
| playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; | |||||
| //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); | |||||
| return ++stateNum; | |||||
| } | } | ||||
| public long ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | public long ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | ||||
| { | { | ||||
| lock (actionLock) | |||||
| { | |||||
| whatInteractingWith = gameObj; | |||||
| if (value != PlayerStateType.Moving) | |||||
| IsMoving = false; | |||||
| playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; | |||||
| //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); | |||||
| return stateNum; | |||||
| } | |||||
| //只能被SetPlayerState引用 | |||||
| whatInteractingWith = gameObj; | |||||
| if (value != PlayerStateType.Moving) | |||||
| IsMoving = false; | |||||
| playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; | |||||
| //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); | |||||
| return stateNum; | |||||
| } | } | ||||
| public long SetPlayerStateNaturally() | public long SetPlayerStateNaturally() | ||||
| @@ -1,5 +1,7 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System.Numerics; | |||||
| using System; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -25,15 +27,66 @@ namespace GameClass.GameObj | |||||
| return false; | return false; | ||||
| } | } | ||||
| private XY stage = new(0, 0); | |||||
| public XY Stage | |||||
| { | |||||
| get | |||||
| { | |||||
| GameObjReaderWriterLock.EnterReadLock(); | |||||
| try | |||||
| { | |||||
| return stage; | |||||
| } | |||||
| finally { GameObjReaderWriterLock.ExitReadLock(); } | |||||
| } | |||||
| } | |||||
| private Character? whoIsClimbing = null; | private Character? whoIsClimbing = null; | ||||
| public Character? WhoIsClimbing | public Character? WhoIsClimbing | ||||
| { | { | ||||
| get => whoIsClimbing; | |||||
| set | |||||
| get | |||||
| { | |||||
| GameObjReaderWriterLock.EnterReadLock(); | |||||
| try | |||||
| { | |||||
| return whoIsClimbing; | |||||
| } | |||||
| finally { GameObjReaderWriterLock.ExitReadLock(); } | |||||
| } | |||||
| } | |||||
| public bool TryToClimb(Character character) | |||||
| { | |||||
| GameObjReaderWriterLock.EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| if (whoIsClimbing == null) | |||||
| { | |||||
| stage = new(0, 0); | |||||
| whoIsClimbing = character; | |||||
| return true; | |||||
| } | |||||
| else return false; | |||||
| } | |||||
| finally { GameObjReaderWriterLock.ExitWriteLock(); } | |||||
| } | |||||
| public void FinishClimbing() | |||||
| { | |||||
| GameObjReaderWriterLock.EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| whoIsClimbing = null; | |||||
| } | |||||
| finally { GameObjReaderWriterLock.ExitWriteLock(); } | |||||
| } | |||||
| public void Enter2Stage(XY xy) | |||||
| { | |||||
| GameObjReaderWriterLock.EnterWriteLock(); | |||||
| try | |||||
| { | { | ||||
| lock (gameObjLock) | |||||
| whoIsClimbing = value; | |||||
| stage = xy; | |||||
| } | } | ||||
| finally { GameObjReaderWriterLock.ExitWriteLock(); } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -8,8 +8,23 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| protected readonly object actionLock = new(); | protected readonly object actionLock = new(); | ||||
| public object ActionLock => actionLock; | public object ActionLock => actionLock; | ||||
| //player.actionLock>其他.actionLock | |||||
| private readonly ReaderWriterLockSlim moveReaderWriterLock = new(); | private readonly ReaderWriterLockSlim moveReaderWriterLock = new(); | ||||
| public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock; | public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock; | ||||
| private Semaphore threadNum = new(1, 1); | |||||
| public Semaphore ThreadNum | |||||
| { | |||||
| get | |||||
| { | |||||
| return threadNum; | |||||
| } | |||||
| set | |||||
| { | |||||
| threadNum = value; | |||||
| } | |||||
| } | |||||
| protected long stateNum = 0; | protected long stateNum = 0; | ||||
| public long StateNum | public long StateNum | ||||
| { | { | ||||
| @@ -61,14 +76,27 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| // 移动,改变坐标 | // 移动,改变坐标 | ||||
| public long MovingSetPos(XY moveVec) | |||||
| public long MovingSetPos(XY moveVec, long stateNo) | |||||
| { | { | ||||
| if (moveVec.x != 0 || moveVec.y != 0) | if (moveVec.x != 0 || moveVec.y != 0) | ||||
| lock (actionLock) | |||||
| { | |||||
| moveReaderWriterLock.EnterReadLock(); | |||||
| try | |||||
| { | { | ||||
| facingDirection = moveVec; | |||||
| this.position += moveVec; | |||||
| lock (actionLock) | |||||
| { | |||||
| if (!canMove || isRemoved) return -1; | |||||
| if (stateNo != stateNum) return -1; | |||||
| facingDirection = moveVec; | |||||
| this.position += moveVec; | |||||
| } | |||||
| } | } | ||||
| finally | |||||
| { | |||||
| moveReaderWriterLock.ExitReadLock(); | |||||
| } | |||||
| } | |||||
| return moveVec * moveVec; | return moveVec * moveVec; | ||||
| } | } | ||||
| @@ -20,18 +20,6 @@ namespace GameEngine | |||||
| private readonly ITimer gameTimer; | private readonly ITimer gameTimer; | ||||
| private readonly Action<IMoveable> EndMove; | private readonly Action<IMoveable> EndMove; | ||||
| public readonly uint[,] ProtoGameMap; | |||||
| public PlaceType GetPlaceType(XY Position) | |||||
| { | |||||
| try | |||||
| { | |||||
| return (PlaceType)ProtoGameMap[Position.x / GameData.numOfPosGridPerCell, Position.y / GameData.numOfPosGridPerCell]; | |||||
| } | |||||
| catch | |||||
| { | |||||
| return PlaceType.Null; | |||||
| } | |||||
| } | |||||
| public IGameObj? CheckCollision(IMoveable obj, XY Pos) | public IGameObj? CheckCollision(IMoveable obj, XY Pos) | ||||
| { | { | ||||
| @@ -52,7 +40,6 @@ namespace GameEngine | |||||
| Action<IMoveable> EndMove | Action<IMoveable> EndMove | ||||
| ) | ) | ||||
| { | { | ||||
| this.ProtoGameMap = gameMap.ProtoGameMap; | |||||
| this.gameTimer = gameMap.Timer; | this.gameTimer = gameMap.Timer; | ||||
| this.EndMove = EndMove; | this.EndMove = EndMove; | ||||
| this.OnCollision = OnCollision; | this.OnCollision = OnCollision; | ||||
| @@ -64,21 +51,57 @@ namespace GameEngine | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="obj">移动物体,默认obj.Rigid为true</param> | /// <param name="obj">移动物体,默认obj.Rigid为true</param> | ||||
| /// <param name="moveVec">移动的位移向量</param> | /// <param name="moveVec">移动的位移向量</param> | ||||
| private void MoveMax(IMoveable obj, XY moveVec) | |||||
| private bool MoveMax(IMoveable obj, XY moveVec, long stateNum) | |||||
| { | { | ||||
| /*由于四周是墙,所以人物永远不可能与越界方块碰撞*/ | /*由于四周是墙,所以人物永远不可能与越界方块碰撞*/ | ||||
| XY nextPos = obj.Position + moveVec; | XY nextPos = obj.Position + moveVec; | ||||
| double maxLen = collisionChecker.FindMax(obj, nextPos, moveVec); | double maxLen = collisionChecker.FindMax(obj, nextPos, moveVec); | ||||
| maxLen = Math.Min(maxLen, obj.MoveSpeed / GameData.numOfStepPerSecond); | maxLen = Math.Min(maxLen, obj.MoveSpeed / GameData.numOfStepPerSecond); | ||||
| obj.MovingSetPos(new XY(moveVec, maxLen)); | |||||
| return (obj.MovingSetPos(new XY(moveVec, maxLen), stateNum)) >= 0; | |||||
| } | |||||
| private bool LoopDo(IMoveable obj, double direction, ref double deltaLen, long stateNum) | |||||
| { | |||||
| double moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||||
| XY res = new(direction, moveVecLength); | |||||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||||
| bool flag; // 循环标志 | |||||
| do | |||||
| { | |||||
| flag = false; | |||||
| IGameObj? collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res); | |||||
| if (collisionObj == null) | |||||
| break; | |||||
| switch (OnCollision(obj, collisionObj, res)) | |||||
| { | |||||
| case AfterCollision.ContinueCheck: | |||||
| flag = true; | |||||
| break; | |||||
| case AfterCollision.Destroyed: | |||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||||
| return false; | |||||
| case AfterCollision.MoveMax: | |||||
| if (!MoveMax(obj, res, stateNum)) return false; | |||||
| moveVecLength = 0; | |||||
| res = new XY(direction, moveVecLength); | |||||
| break; | |||||
| } | |||||
| } while (flag); | |||||
| long moveL = obj.MovingSetPos(res, stateNum); | |||||
| if (moveL == -1) return false; | |||||
| deltaLen = deltaLen + moveVecLength - Math.Sqrt(moveL); | |||||
| return true; | |||||
| } | } | ||||
| public void MoveObj(IMoveable obj, int moveTime, double direction, long threadNum) | |||||
| public void MoveObj(IMoveable obj, int moveTime, double direction, long stateNum) | |||||
| { | { | ||||
| if (!gameTimer.IsGaming) return; | if (!gameTimer.IsGaming) return; | ||||
| lock (obj.ActionLock) | lock (obj.ActionLock) | ||||
| { | { | ||||
| if (!obj.IsAvailableForMove) return; | |||||
| if (!obj.IsAvailableForMove) { EndMove(obj); return; } | |||||
| obj.IsMoving = true; | obj.IsMoving = true; | ||||
| } | } | ||||
| new Thread | new Thread | ||||
| @@ -87,9 +110,9 @@ namespace GameEngine | |||||
| { | { | ||||
| double moveVecLength = 0.0; | double moveVecLength = 0.0; | ||||
| XY res = new(direction, moveVecLength); | XY res = new(direction, moveVecLength); | ||||
| double deltaLen = 0; // 转向,并用deltaLen存储行走的误差 | |||||
| double deltaLen = (double)0.0; // 转向,并用deltaLen存储行走的误差 | |||||
| IGameObj? collisionObj = null; | IGameObj? collisionObj = null; | ||||
| bool isDestroyed = false; | |||||
| bool isEnded = false; | |||||
| bool flag; // 循环标志 | bool flag; // 循环标志 | ||||
| do | do | ||||
| @@ -106,34 +129,82 @@ namespace GameEngine | |||||
| break; | break; | ||||
| case AfterCollision.Destroyed: | case AfterCollision.Destroyed: | ||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | ||||
| isDestroyed = true; | |||||
| isEnded = true; | |||||
| break; | break; | ||||
| case AfterCollision.MoveMax: | case AfterCollision.MoveMax: | ||||
| break; | break; | ||||
| } | } | ||||
| } while (flag); | } while (flag); | ||||
| if (!isDestroyed) | |||||
| if (isEnded) | |||||
| { | { | ||||
| new FrameRateTaskExecutor<int>( | |||||
| () => gameTimer.IsGaming && obj.CanMove && !obj.IsRemoved && obj.IsMoving, | |||||
| () => | |||||
| obj.IsMoving = false; | |||||
| EndMove(obj); | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (moveTime >= GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond) | |||||
| { | |||||
| Thread.Sleep(GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||||
| new FrameRateTaskExecutor<int>( | |||||
| () => gameTimer.IsGaming, | |||||
| () => | |||||
| { | |||||
| if (obj.StateNum == stateNum && obj.CanMove && !obj.IsRemoved) | |||||
| return !(isEnded = true); | |||||
| return !(isEnded = !LoopDo(obj, direction, ref deltaLen, stateNum)); | |||||
| }, | |||||
| GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond, | |||||
| () => | |||||
| { | |||||
| return 0; | |||||
| }, | |||||
| maxTotalDuration: moveTime - GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond | |||||
| ) | |||||
| { | { | ||||
| moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||||
| res = new XY(direction, moveVecLength); | |||||
| //对人特殊处理 | |||||
| if (threadNum > 0 && obj.StateNum != threadNum) return false; | |||||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||||
| bool flag; // 循环标志 | |||||
| do | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| TimeExceedAction = b => | |||||
| { | { | ||||
| flag = false; | |||||
| collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res); | |||||
| if (collisionObj == null) | |||||
| break; | |||||
| if (b) | |||||
| Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!"); | |||||
| #if DEBUG | |||||
| else | |||||
| { | |||||
| Console.WriteLine("Debug info: Object moving time exceed for once."); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| }.Start(); | |||||
| if (!isEnded && obj.StateNum == stateNum && obj.CanMove && !obj.IsRemoved) | |||||
| isEnded = !LoopDo(obj, direction, ref deltaLen, stateNum); | |||||
| } | |||||
| if (isEnded) | |||||
| { | |||||
| obj.IsMoving = false; | |||||
| EndMove(obj); | |||||
| return; | |||||
| } | |||||
| if (obj.StateNum == stateNum && obj.CanMove && !obj.IsRemoved) | |||||
| { | |||||
| int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||||
| if (leftTime > 0) | |||||
| { | |||||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||||
| } | |||||
| do | |||||
| { | |||||
| flag = false; | |||||
| moveVecLength = (double)deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||||
| res = new XY(direction, moveVecLength); | |||||
| if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null) | |||||
| { | |||||
| obj.MovingSetPos(res, stateNum); | |||||
| } | |||||
| else | |||||
| { | |||||
| switch (OnCollision(obj, collisionObj, res)) | switch (OnCollision(obj, collisionObj, res)) | ||||
| { | { | ||||
| case AfterCollision.ContinueCheck: | case AfterCollision.ContinueCheck: | ||||
| @@ -141,87 +212,19 @@ namespace GameEngine | |||||
| break; | break; | ||||
| case AfterCollision.Destroyed: | case AfterCollision.Destroyed: | ||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | ||||
| isDestroyed = true; | |||||
| return false; | |||||
| isEnded = true; | |||||
| break; | |||||
| case AfterCollision.MoveMax: | case AfterCollision.MoveMax: | ||||
| if (threadNum == 0 || obj.StateNum == threadNum) | |||||
| MoveMax(obj, res); | |||||
| MoveMax(obj, res, stateNum); | |||||
| moveVecLength = 0; | moveVecLength = 0; | ||||
| res = new XY(direction, moveVecLength); | res = new XY(direction, moveVecLength); | ||||
| break; | break; | ||||
| } | } | ||||
| } while (flag); | |||||
| if (threadNum == 0 || obj.StateNum == threadNum) | |||||
| deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res)); | |||||
| return true; | |||||
| }, | |||||
| GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond, | |||||
| () => | |||||
| { | |||||
| int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||||
| bool flag; | |||||
| do | |||||
| { | |||||
| flag = false; | |||||
| if (!isDestroyed) | |||||
| { | |||||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||||
| res = new XY(direction, moveVecLength); | |||||
| if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null) | |||||
| { | |||||
| if (threadNum == 0 || obj.StateNum == threadNum) | |||||
| obj.MovingSetPos(res); | |||||
| } | |||||
| else | |||||
| { | |||||
| switch (OnCollision(obj, collisionObj, res)) | |||||
| { | |||||
| case AfterCollision.ContinueCheck: | |||||
| flag = true; | |||||
| break; | |||||
| case AfterCollision.Destroyed: | |||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||||
| isDestroyed = true; | |||||
| break; | |||||
| case AfterCollision.MoveMax: | |||||
| if (threadNum == 0 || obj.StateNum == threadNum) | |||||
| MoveMax(obj, res); | |||||
| moveVecLength = 0; | |||||
| res = new XY(direction, moveVecLength); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } while (flag); | |||||
| if (leftTime > 0 && obj.IsMoving) | |||||
| { | |||||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||||
| } | |||||
| lock (obj.ActionLock) | |||||
| obj.IsMoving = false; // 结束移动 | |||||
| EndMove(obj); | |||||
| return 0; | |||||
| }, | |||||
| maxTotalDuration: moveTime | |||||
| ) | |||||
| { | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| TimeExceedAction = b => | |||||
| { | |||||
| if (b) | |||||
| Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!"); | |||||
| #if DEBUG | |||||
| else | |||||
| { | |||||
| Console.WriteLine("Debug info: Object moving time exceed for once."); | |||||
| } | } | ||||
| #endif | |||||
| } | |||||
| }.Start(); | |||||
| } while (flag); | |||||
| } | |||||
| obj.IsMoving = false; // 结束移动 | |||||
| EndMove(obj); | |||||
| } | } | ||||
| } | } | ||||
| ).Start(); | ).Start(); | ||||
| @@ -36,26 +36,59 @@ namespace Gaming | |||||
| public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) | public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) | ||||
| { | { | ||||
| if (moveTimeInMilliseconds < 5) return false; | if (moveTimeInMilliseconds < 5) return false; | ||||
| if (!playerToMove.Commandable()) return false; | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, | |||||
| characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving)); | |||||
| long stateNum = characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving); | |||||
| if (stateNum == -1) return false; | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| playerToMove.ThreadNum.WaitOne(); | |||||
| if (stateNum != playerToMove.StateNum) | |||||
| playerToMove.ThreadNum.Release(); | |||||
| else | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, stateNum); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| public bool MovePlayerWhenStunned(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) | public bool MovePlayerWhenStunned(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) | ||||
| { | { | ||||
| if (!playerToMove.Commandable() && playerToMove.PlayerState != PlayerStateType.Stunned) return false; | |||||
| characterManager.BeStunned(playerToMove, moveTimeInMilliseconds); | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, playerToMove.StateNum); | |||||
| if (playerToMove.CharacterType == CharacterType.Robot) return false; | |||||
| long stateNum = characterManager.SetPlayerState(playerToMove, PlayerStateType.Charmed); | |||||
| if (stateNum == -1) return false; | |||||
| new Thread | |||||
| (() => | |||||
| { | |||||
| playerToMove.ThreadNum.WaitOne(); | |||||
| if (stateNum != playerToMove.StateNum) | |||||
| playerToMove.ThreadNum.Release(); | |||||
| else | |||||
| { | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, playerToMove.StateNum); | |||||
| Thread.Sleep(moveTimeInMilliseconds); | |||||
| lock (playerToMove.ActionLock) | |||||
| { | |||||
| if (stateNum == playerToMove.StateNum) | |||||
| playerToMove.SetPlayerStateNaturally(); | |||||
| } | |||||
| } | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| public bool Stop(Character player) | public bool Stop(Character player) | ||||
| { | { | ||||
| if (player.Commandable()) | |||||
| lock (player.ActionLock) | |||||
| { | { | ||||
| characterManager.SetPlayerState(player); | |||||
| return true; | |||||
| if (player.Commandable()) | |||||
| { | |||||
| characterManager.SetPlayerState(player); | |||||
| return true; | |||||
| } | |||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -279,12 +312,11 @@ namespace Gaming | |||||
| } | } | ||||
| public bool ClimbingThroughWindow(Character player) | public bool ClimbingThroughWindow(Character player) | ||||
| { | { | ||||
| if (!player.Commandable()) | |||||
| return false; | |||||
| Window? windowForClimb = (Window?)gameMap.OneForInteractInACross(player.Position, GameObjType.Window); | Window? windowForClimb = (Window?)gameMap.OneForInteractInACross(player.Position, GameObjType.Window); | ||||
| if (windowForClimb == null) return false; | |||||
| if (windowForClimb == null || windowForClimb.WhoIsClimbing != null) | |||||
| return false; | |||||
| long stateNum = characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows, windowForClimb); | |||||
| if (stateNum == -1) return false; | |||||
| XY windowToPlayer = new( | XY windowToPlayer = new( | ||||
| (Math.Abs(player.Position.x - windowForClimb.Position.x) > GameData.numOfPosGridPerCell / 2) ? (GameData.numOfPosGridPerCell / 2 * (player.Position.x > windowForClimb.Position.x ? 1 : -1)) : 0, | (Math.Abs(player.Position.x - windowForClimb.Position.x) > GameData.numOfPosGridPerCell / 2) ? (GameData.numOfPosGridPerCell / 2 * (player.Position.x > windowForClimb.Position.x ? 1 : -1)) : 0, | ||||
| @@ -296,59 +328,57 @@ namespace Gaming | |||||
| if (player.IsGhost() && !characterInWindow.IsGhost()) | if (player.IsGhost() && !characterInWindow.IsGhost()) | ||||
| characterManager.BeAttacked((Student)(characterInWindow), player.Attack(characterInWindow.Position)); | characterManager.BeAttacked((Student)(characterInWindow), player.Attack(characterInWindow.Position)); | ||||
| return false; | return false; | ||||
| }*/ | |||||
| } | |||||
| //Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer); | |||||
| // gameMap.Add(addWall); | |||||
| Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer); | |||||
| gameMap.Add(addWall);*/ | |||||
| characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows); | |||||
| long threadNum = player.StateNum; | |||||
| windowForClimb.WhoIsClimbing = player; | |||||
| new Thread | new Thread | ||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||||
| loopToDo: () => { }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| finallyReturn: () => 0, | |||||
| maxTotalDuration: (int)((windowToPlayer + windowForClimb.Position - player.Position).Length() * 1000 / player.MoveSpeed) | |||||
| ) | |||||
| .Start(); | |||||
| if (player.PlayerState != PlayerStateType.ClimbingThroughWindows) | |||||
| { | |||||
| windowForClimb.WhoIsClimbing = null; | |||||
| return; | |||||
| } | |||||
| player.ReSetPos(windowToPlayer + windowForClimb.Position); | |||||
| player.MoveSpeed = player.SpeedOfClimbingThroughWindows; | |||||
| moveEngine.MoveObj(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle(), threadNum); | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||||
| loopToDo: () => | |||||
| ( | |||||
| () => | |||||
| { | { | ||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| finallyReturn: () => 0, | |||||
| maxTotalDuration: (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed) | |||||
| ) | |||||
| .Start(); | |||||
| XY PosJumpOff = windowForClimb.Position - 2 * windowToPlayer; | |||||
| player.ReSetPos(PosJumpOff); | |||||
| player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed); | |||||
| windowForClimb.WhoIsClimbing = null; | |||||
| // gameMap.Remove(addWall); | |||||
| if (threadNum == player.StateNum) | |||||
| { | |||||
| characterManager.SetPlayerState(player); | |||||
| } | |||||
| } | |||||
| ) | |||||
| player.ThreadNum.WaitOne(); | |||||
| if (stateNum != player.StateNum) | |||||
| { | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (!windowForClimb.TryToClimb(player)) | |||||
| { | |||||
| player.ThreadNum.Release(); | |||||
| player.SetPlayerStateNaturally(); | |||||
| } | |||||
| else | |||||
| { | |||||
| Thread.Sleep((int)((windowToPlayer + windowForClimb.Position - player.Position).Length() * 1000 / player.MoveSpeed)); | |||||
| lock (player.ActionLock) | |||||
| { | |||||
| if (player.StateNum != stateNum) return; | |||||
| player.ReSetPos(windowToPlayer + windowForClimb.Position); | |||||
| windowForClimb.Enter2Stage(windowForClimb.Position - 2 * windowToPlayer); | |||||
| } | |||||
| player.MoveSpeed = player.SpeedOfClimbingThroughWindows; | |||||
| moveEngine.MoveObj(player, GameData.numOfPosGridPerCell * 3 * 1000 / player.MoveSpeed / 2, (-1 * windowToPlayer).Angle(), stateNum); | |||||
| Thread.Sleep(GameData.numOfPosGridPerCell * 3 * 1000 / player.MoveSpeed / 2); | |||||
| player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed); | |||||
| lock (player.ActionLock) | |||||
| { | |||||
| if (stateNum == player.StateNum) | |||||
| { | |||||
| characterManager.SetPlayerState(player); | |||||
| windowForClimb.FinishClimbing(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | { IsBackground = true }.Start(); | ||||
| return true; | return true; | ||||
| @@ -400,7 +430,6 @@ namespace Gaming | |||||
| timeInterval: GameData.frameDuration, | timeInterval: GameData.frameDuration, | ||||
| finallyReturn: () => 0 | finallyReturn: () => 0 | ||||
| ) | ) | ||||
| .Start(); | .Start(); | ||||
| if (doorToLock.OpenOrLockDegree >= GameData.degreeOfLockingOrOpeningTheDoor) | if (doorToLock.OpenOrLockDegree >= GameData.degreeOfLockingOrOpeningTheDoor) | ||||
| { | { | ||||
| @@ -462,6 +491,7 @@ namespace Gaming | |||||
| }, | }, | ||||
| EndMove: obj => | EndMove: obj => | ||||
| { | { | ||||
| obj.ThreadNum.Release(); | |||||
| // Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | // Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | ||||
| } | } | ||||
| ); | ); | ||||
| @@ -195,7 +195,9 @@ namespace Gaming | |||||
| { | { | ||||
| Debugger.Output(bullet, "Attack in " + bullet.Position.ToString()); | Debugger.Output(bullet, "Attack in " + bullet.Position.ToString()); | ||||
| gameMap.Add(bullet); | gameMap.Add(bullet); | ||||
| moveEngine.MoveObj(bullet, (int)(bullet.AttackDistance * 1000 / bullet.MoveSpeed), angle, ++bullet.StateNum); // 这里时间参数除出来的单位要是ms | moveEngine.MoveObj(bullet, (int)(bullet.AttackDistance * 1000 / bullet.MoveSpeed), angle, ++bullet.StateNum); // 这里时间参数除出来的单位要是ms | ||||
| if (bullet.CastTime > 0) | if (bullet.CastTime > 0) | ||||
| { | { | ||||
| characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); | characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); | ||||
| @@ -25,28 +25,52 @@ namespace Gaming | |||||
| if (nowPlayerState == value) return -1; | if (nowPlayerState == value) return -1; | ||||
| switch (nowPlayerState) | switch (nowPlayerState) | ||||
| { | { | ||||
| case PlayerStateType.OpeningTheChest: | |||||
| if (player.NoHp()) return -1; | |||||
| ((Chest)player.WhatInteractingWith!).StopOpen(); | |||||
| return player.ChangePlayerState(value, gameObj); | |||||
| case PlayerStateType.OpeningTheDoorway: | |||||
| if (player.NoHp()) return -1; | |||||
| Doorway doorway = (Doorway)player.WhatInteractingWith!; | |||||
| doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; | |||||
| doorway.OpenStartTime = 0; | |||||
| return player.ChangePlayerState(value, gameObj); | |||||
| case PlayerStateType.Escaped: | |||||
| case PlayerStateType.Deceased: | |||||
| return -1; | |||||
| case PlayerStateType.Addicted: | case PlayerStateType.Addicted: | ||||
| if (value == PlayerStateType.Rescued) | if (value == PlayerStateType.Rescued) | ||||
| return player.ChangePlayerStateInOneThread(value, gameObj); | return player.ChangePlayerStateInOneThread(value, gameObj); | ||||
| else | |||||
| else if (value == PlayerStateType.Null) | |||||
| return player.ChangePlayerState(value, gameObj); | return player.ChangePlayerState(value, gameObj); | ||||
| else return -1; | |||||
| case PlayerStateType.Rescued: | case PlayerStateType.Rescued: | ||||
| if (value == PlayerStateType.Addicted) | if (value == PlayerStateType.Addicted) | ||||
| return player.ChangePlayerStateInOneThread(value, gameObj); | return player.ChangePlayerStateInOneThread(value, gameObj); | ||||
| else | |||||
| else if (value == PlayerStateType.Null) | |||||
| return player.ChangePlayerState(value, gameObj); | |||||
| else return -1; | |||||
| case PlayerStateType.TryingToAttack: | |||||
| case PlayerStateType.Stunned: | |||||
| case PlayerStateType.Charmed: | |||||
| case PlayerStateType.Swinging: | |||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows) | |||||
| return player.ChangePlayerState(value, gameObj); | |||||
| else return -1; | |||||
| case PlayerStateType.ClimbingThroughWindows: | |||||
| if (value != PlayerStateType.Moving) | |||||
| { | |||||
| Window window = (Window)player.WhatInteractingWith!; | |||||
| window.FinishClimbing(); | |||||
| if (window.Stage.x == 0) | |||||
| player.ThreadNum.Release(); | |||||
| else player.ReSetPos(window.Stage); | |||||
| return player.ChangePlayerState(value, gameObj); | return player.ChangePlayerState(value, gameObj); | ||||
| } | |||||
| else return -1; | |||||
| case PlayerStateType.OpeningTheChest: | |||||
| ((Chest)player.WhatInteractingWith!).StopOpen(); | |||||
| return player.ChangePlayerState(value, gameObj); | |||||
| case PlayerStateType.OpeningTheDoorway: | |||||
| Doorway doorway = (Doorway)player.WhatInteractingWith!; | |||||
| doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; | |||||
| doorway.OpenStartTime = 0; | |||||
| return player.ChangePlayerState(value, gameObj); | |||||
| default: | default: | ||||
| if (player.NoHp()) return -1; | |||||
| return player.ChangePlayerState(value, gameObj); | return player.ChangePlayerState(value, gameObj); | ||||
| } | } | ||||
| } | } | ||||
| @@ -163,7 +187,7 @@ namespace Gaming | |||||
| newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.DistanceFloor3(newPlayer.Position, person.Position)); | newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.DistanceFloor3(newPlayer.Position, person.Position)); | ||||
| else newPlayer.AddBgm(BgmType.GhostIsComing, 0); | else newPlayer.AddBgm(BgmType.GhostIsComing, 0); | ||||
| } | } | ||||
| if (newPlayer.CharacterType != CharacterType.Teacher && newPlayer.CharacterType != CharacterType.Robot && !newPlayer.NoHp() && newPlayer.PlayerState != PlayerStateType.Stunned && XY.DistanceFloor3(newPlayer.Position, person.Position) <= GameData.PinningDownRange) | |||||
| if (newPlayer.CharacterType != CharacterType.Teacher && newPlayer.CharacterType != CharacterType.Robot && newPlayer.CanPinDown() && XY.DistanceFloor3(newPlayer.Position, person.Position) <= GameData.PinningDownRange) | |||||
| { | { | ||||
| TimePinningDown += GameData.checkInterval; | TimePinningDown += GameData.checkInterval; | ||||
| newPlayer.AddScore(GameData.StudentScorePinDown(TimePinningDown) - ScoreAdded); | newPlayer.AddScore(GameData.StudentScorePinDown(TimePinningDown) - ScoreAdded); | ||||
| @@ -54,7 +54,7 @@ namespace Gaming | |||||
| else player.AddAp(GameData.PropDuration); | else player.AddAp(GameData.PropDuration); | ||||
| break; | break; | ||||
| case PropType.RecoveryFromDizziness: | case PropType.RecoveryFromDizziness: | ||||
| if (player.PlayerState == PlayerStateType.Stunned) | |||||
| if (player.PlayerState == PlayerStateType.Stunned || player.PlayerState == PlayerStateType.Charmed) | |||||
| { | { | ||||
| player.AddScore(GameData.ScorePropRecoverFromDizziness); | player.AddScore(GameData.ScorePropRecoverFromDizziness); | ||||
| player.SetPlayerStateNaturally(); | player.SetPlayerStateNaturally(); | ||||
| @@ -1,4 +1,5 @@ | |||||
| using System; | using System; | ||||
| using System.Threading; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| namespace Preparation.Interface | namespace Preparation.Interface | ||||
| @@ -11,7 +12,8 @@ namespace Preparation.Interface | |||||
| public bool IsRemoved { get; } | public bool IsRemoved { get; } | ||||
| public bool IsAvailableForMove { get; } | public bool IsAvailableForMove { get; } | ||||
| public long StateNum { get; } | public long StateNum { get; } | ||||
| public long MovingSetPos(XY moveVec); | |||||
| public Semaphore ThreadNum { get; set; } | |||||
| public long MovingSetPos(XY moveVec, long stateNum); | |||||
| public void ReSetCanMove(bool value); | public void ReSetCanMove(bool value); | ||||
| public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞 | public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞 | ||||
| { | { | ||||
| @@ -24,6 +24,7 @@ namespace Preparation.Utility | |||||
| ClimbingThroughWindows = 15, | ClimbingThroughWindows = 15, | ||||
| UsingSkill = 16, | UsingSkill = 16, | ||||
| OpeningTheDoorway = 17, | OpeningTheDoorway = 17, | ||||
| Charmed = 18, | |||||
| } | } | ||||
| public enum GameObjType | public enum GameObjType | ||||
| { | { | ||||
| @@ -6,13 +6,13 @@ namespace Preparation.Utility | |||||
| public static class GameData | public static class GameData | ||||
| { | { | ||||
| #region 基本常数 | #region 基本常数 | ||||
| public const int numOfStepPerSecond = 20; // 每秒行走的步数 | |||||
| public const int numOfStepPerSecond = 100; // 每秒行走的步数 | |||||
| public const int tolerancesLength = 3; | public const int tolerancesLength = 3; | ||||
| public const int adjustLength = 3; | public const int adjustLength = 3; | ||||
| public const int frameDuration = 50; // 每帧时长 | public const int frameDuration = 50; // 每帧时长 | ||||
| public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | |||||
| public const int checkInterval = 10; | |||||
| public const long gameDuration = 600000; // 游戏时长600000ms = 10min | public const long gameDuration = 600000; // 游戏时长600000ms = 10min | ||||
| public const int LimitOfStopAndMove = 15; | public const int LimitOfStopAndMove = 15; | ||||
| @@ -116,6 +116,7 @@ namespace Preparation.Utility | |||||
| case Preparation.Utility.PlayerStateType.Rescuing: | case Preparation.Utility.PlayerStateType.Rescuing: | ||||
| return PlayerState.Rescuing; | return PlayerState.Rescuing; | ||||
| case Preparation.Utility.PlayerStateType.Stunned: | case Preparation.Utility.PlayerStateType.Stunned: | ||||
| case Preparation.Utility.PlayerStateType.Charmed: | |||||
| return PlayerState.Stunned; | return PlayerState.Stunned; | ||||
| case Preparation.Utility.PlayerStateType.Swinging: | case Preparation.Utility.PlayerStateType.Swinging: | ||||
| return PlayerState.Swinging; | return PlayerState.Swinging; | ||||