diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c4945ea --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +[*.cs] +# 针对枚举成员的命名规则:要求使用 PascalCase +dotnet_naming_rule.enum_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.enum_members_should_be_pascal_case.symbols = enum_members +dotnet_naming_rule.enum_members_should_be_pascal_case.style = pascal_caser + +# 定义符号:这里适用于所有 const 字段(通常枚举成员会被识别为 const 字段) +dotnet_naming_symbols.enum_members.applicable_kinds = field +dotnet_naming_symbols.enum_members.required_modifiers = const + +# 定义命名风格:PascalCase +dotnet_naming_style.pascal_caser.capitalization = pascal_case +dotnet_naming_style.pascal_caser.required_prefix = +dotnet_naming_style.pascal_caser.required_suffix = +dotnet_naming_style.pascal_caser.word_separator = \ No newline at end of file diff --git a/CAPI/cpp/API/include/structures.h b/CAPI/cpp/API/include/structures.h index 2446964..ec3ae2a 100644 --- a/CAPI/cpp/API/include/structures.h +++ b/CAPI/cpp/API/include/structures.h @@ -219,23 +219,25 @@ namespace THUAI8 CharacterState characterActiveState; CharacterState blindState; - double blindTime; - CharacterState knockbackState; - double knockbackTime; + long blindTime; + // CharacterState knockbackState; + // double knockbackTime; CharacterState stunnedState; - double stunnedTime; + long stunnedTime; CharacterState invisibleState; - double invisibleTime; - CharacterState healingState; - double healingTime; - CharacterState berserkState; - double berserkTime; + long invisibleTime; + // CharacterState healingState; + // double healingTime; + // CharacterState berserkState; + // double berserkTime; CharacterState burnedState; - double burnedTime; - CharacterState harmCutState; - double harmCutTime; + long burnedTime; + double harmCut; + long harmCutTime; CharacterState deceasedState; + CharacterState characterPassiveState; + int32_t x; int32_t y; @@ -244,29 +246,30 @@ namespace THUAI8 int32_t viewRange; int32_t commonAttack; - double commonAttackCD; + long commonAttackCD; int32_t commonAttackRange; - double skillAttackCD; + long skillAttackCD; int32_t economyDepletion; int32_t killScore; int32_t hp; - EquipmentType shieldEquipment; - int32_t shild; - EquipmentType shoesEquipment; - double shoesTime; + int32_t shieldEquipment; + // int32_t shild; + int32_t shoesEquipment; + long shoesEquipmentTime; + long purificationEquipmentTime; - CharacterBuffType attackBuff; - double attackBuffTime; - CharacterBuffType defenseBuff; - double defenseBuffTime; - CharacterBuffType speedBuff; - double speedBuffTime; - CharacterBuffType visionBuff; - double visionBuffTime; + // CharacterBuffType attackBuff; + long attackBuffTime; + // CharacterBuffType defenseBuff; + // long defenseBuffTime; + // CharacterBuffType speedBuff; + long speedBuffTime; + // CharacterBuffType visionBuff; + long visionBuffTime; }; struct Team diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index 9b8887c..4240e45 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -508,7 +508,7 @@ void Logic::LoadBufferCase(const protobuf::MessageOfObj& item) break; case THUAI8::MessageOfObj::TrapMessage: // 寰呭畾 - if (item.trap_message().team_id() == teamID || AssistFunction::HaveView(x, y, item.trap_message().x(), item.trap_message().y(), viewRange, bufferState->gameMap) && currentState->characterSelf->visionBuff == THUAI8::CharacterBuffType::VisionBuff) + if (item.trap_message().team_id() == teamID || AssistFunction::HaveView(x, y, item.trap_message().x(), item.trap_message().y(), viewRange, bufferState->gameMap) && currentState->characterSelf->visionBuffTime > 0) { auto pos = THUAI8::cellxy_t( AssistFunction::GridToCell(item.trap_message().x()), @@ -603,7 +603,7 @@ void Logic::LoadBufferCase(const protobuf::MessageOfObj& item) { for (const auto& character : bufferState->characters) { - if (AssistFunction::HaveView(character->x, character->y, targetX, targetY, character->viewRange, bufferState->gameMap) && character->visionBuff == THUAI8::CharacterBuffType::VisionBuff) + if (AssistFunction::HaveView(character->x, character->y, targetX, targetY, character->viewRange, bufferState->gameMap) && character->visionBuffTime > 0) return true; } return false; diff --git a/CAPI/python/AI.py b/CAPI/python/AI.py new file mode 100644 index 0000000..7e4ed7c --- /dev/null +++ b/CAPI/python/AI.py @@ -0,0 +1,55 @@ +import PyAPI.structures as THUAI8 +from PyAPI.Interface import ICharacterAPI, ITeamAPI, IAI +from PyAPI.utils import AssistFunction +from typing import Union, Final, cast, List +from PyAPI.constants import Constants +import queue +import time + +class Setting: + # 涓哄亣鍒檖lay()鏈熼棿纭繚娓告垙鐘舵佷笉鏇存柊锛屼负鐪熷垯鍙繚璇佹父鎴忕姸鎬佸湪璋冪敤鐩稿叧鏂规硶鏃朵笉鏇存柊锛屽ぇ鑷翠竴甯ф洿鏂颁竴娆 + @staticmethod + def Asynchronous() -> bool: + return False + + @staticmethod + def ShipTypes() -> List[THUAI8.CharacterType]: + return [ + THUAI8.CharacterType.Monk, + THUAI8.CharacterType.MonkeyKing, + THUAI8.CharacterType.Pigsy, + THUAI8.CharacterType.ShaWujing, + THUAI8.CharacterType.Whitedragonhorse, + THUAI8.CharacterType.JiuTouYuanSheng, + THUAI8.CharacterType.Honghaier, + THUAI8.CharacterType.Gyuumao, + THUAI8.CharacterType.Princess_Iron_Fan, + THUAI8.CharacterType.Spider, + ] +numOfGridPerCell: Final[int] = 1000 + +class AI(IAI): + def __init__(self, pID: int): + self.__playerID = pID + + def ShipPlay(self, api: IShipAPI) -> None: + # 鍏叡鎿嶄綔 + if self.__playerID == 1: + # player1鐨勬搷浣 + return + elif self.__playerID == 2: + # player2鐨勬搷浣 + return + elif self.__playerID == 3: + # player3鐨勬搷浣 + return + elif self.__playerID == 4: + # player4鐨勬搷浣 + return + elif self.__playerID == 5: + # player4鐨勬搷浣 + return + + def TeamPlay(self, api: ITeamAPI) -> None: + # player0鐨勬搷浣 + return diff --git a/CAPI/python/API.py b/CAPI/python/API.py new file mode 100644 index 0000000..ff5fb1f --- /dev/null +++ b/CAPI/python/API.py @@ -0,0 +1,245 @@ +from PyAPI.structures import THUAI8 +from PyAPI.Interface import ILogic, IAI, IGameTimer, ICharacterAPI, ITeamAPI +from concurrent.futures import ThreadPoolExecutor, Future +from typing import List, Optional, Tuple, cast, Union +import math + + +class IAPI: + @staticmethod + def CellToGrid(cell: int) -> int: + return cell * 1000 + 500 + + @staticmethod + def GridToCell(grid: int) -> int: + return grid // 1000 + + +class CharacterAPI(ICharacterAPI, IGameTimer): + def __init__(self, logic: ILogic) -> None: + self.__logic = logic + self.__pool = ThreadPoolExecutor(20) + + # region 瀹炵幇IGameTimer鎺ュ彛 + def StartTimer(self) -> None: + pass + + def EndTimer(self) -> None: + pass + + def Play(self, ai: IAI) -> None: + ai.Play(self) + # endregion + + # region 瀹炵幇IAPI鎺ュ彛 + def SendTextMessage(self, toPlayerID: int, message: str) -> Future[bool]: + return self.__pool.submit(self.__logic.Send, toPlayerID, message, False) + + def SendBinaryMessage(self, toPlayerID: int, message: str) -> Future[bool]: + return self.__pool.submit(self.__logic.Send, toPlayerID, message, True) + + def HaveMessage(self) -> bool: + return self.__logic.HaveMessage() + + def GetMessage(self) -> Tuple[int, str]: + return self.__logic.GetMessage() + + def GetFrameCount(self) -> int: + return self.__logic.GetCounter() + + def Wait(self) -> bool: + return self.__logic.WaitThread() + + def EndAllAction(self) -> Future[bool]: + return self.__pool.submit(self.__logic.EndAllAction) + + def GetCharacters(self) -> List[THUAI8.Character]: + return self.__logic.GetCharacters() + + def GetEnemyCharacters(self) -> List[THUAI8.Character]: + return self.__logic.GetEnemyCharacters() + + def GetFullMap(self) -> List[List[THUAI8.PlaceType]]: + return self.__logic.GetFullMap() + + def GetGameInfo(self) -> THUAI8.GameInfo: + return self.__logic.GetGameInfo() + + def GetPlaceType(self, cellX: int, cellY: int) -> THUAI8.PlaceType: + return self.__logic.GetPlaceType(cellX, cellY) + + def GetEnconomyResourceState(self, cellX: int, cellY: int) -> Optional[THUAI8.EconomyResourceState]: + return self.__logic.GetEnconomyResourceState(cellX, cellY) + + def GetAdditionResourceState(self, cellX: int, cellY: int) -> Optional[THUAI8.AdditionResourceState]: + return self.__logic.GetAdditionResourceState(cellX, cellY) + + def GetConstructionState(self, cellX: int, cellY: int) -> Optional[THUAI8.ConstructionState]: + return self.__logic.GetConstructionState(cellX, cellY) + + def GetPlayerGUIDs(self) -> List[int]: + return self.__logic.GetPlayerGUIDs() + + def GetEnergy(self) -> int: + return self.__logic.GetEnergy() + + def GetScore(self) -> int: + return self.__logic.GetScore() + + def Print(self, string: str) -> None: + pass + + def PrintCharacter(self) -> None: + pass + + def PrintTeam(self) -> None: + pass + + def PrintSelfInfo(self) -> None: + pass + # endregion + + # region 瀹炵幇ICharacterAPI鎺ュ彛 + def Move(self, speed: int, timeInMilliseconds: int, angleInRadian: float) -> Future[bool]: + return self.__pool.submit(self.__logic.Move, speed, timeInMilliseconds, angleInRadian) + + def MoveRight(self, speed: int, timeInMilliseconds: int) -> Future[bool]: + return self.Move(speed, timeInMilliseconds, math.pi/2) + + def MoveUp(self, speed: int, timeInMilliseconds: int) -> Future[bool]: + return self.Move(speed, timeInMilliseconds, math.pi) + + def MoveLeft(self, speed: int, timeInMilliseconds: int) -> Future[bool]: + return self.Move(speed, timeInMilliseconds, math.pi*3/2) + + def MoveDown(self, speed: int, timeInMilliseconds: int) -> Future[bool]: + return self.Move(speed, timeInMilliseconds, 0) + + def Skill_Attack(self, attackedPlayerID: int) -> Future[bool]: + return self.__pool.submit(self.__logic.Skill_Attack, attackedPlayerID) + + def Common_Attack(self, attackedPlayerID: int) -> Future[bool]: + return self.__pool.submit(self.__logic.Common_Attack, attackedPlayerID) + + def Recover(self, recover: int) -> Future[bool]: + return self.__pool.submit(self.__logic.Recover, recover) + + def Harvest(self) -> Future[bool]: + return self.__pool.submit(self.__logic.Produce) + + def Rebuild(self, constructionType: THUAI8.ConstructionType) -> Future[bool]: + return self.__pool.submit(self.__logic.Rebuild, constructionType) + + def Construct(self, constructionType: THUAI8.ConstructionType) -> Future[bool]: + return self.__pool.submit(self.__logic.Construct, constructionType) + + def GetSelfInfo(self) -> THUAI8.Character: + return cast(THUAI8.Character, self.__logic.CharacterGetSelfInfo()) + + def HaveView(self, targetX: int, targetY: int) -> bool: + self_info = self.GetSelfInfo() + return self.__logic.HaveView( + self_info.x, self_info.y, + targetX, targetY, + self_info.viewRange + ) + # endregion + + +class TeamAPI(ITeamAPI, IGameTimer): + def __init__(self, logic: ILogic) -> None: + self.__logic = logic + self.__pool = ThreadPoolExecutor(20) + + # region 瀹炵幇IGameTimer鎺ュ彛 + def StartTimer(self) -> None: + pass + + def EndTimer(self) -> None: + pass + + def Play(self, ai: IAI) -> None: + ai.Play(self) + # endregion + + # region 瀹炵幇IAPI鎺ュ彛 + def SendTextMessage(self, toPlayerID: int, message: str) -> Future[bool]: + return self.__pool.submit(self.__logic.Send, toPlayerID, message, False) + + def SendBinaryMessage(self, toPlayerID: int, message: str) -> Future[bool]: + return self.__pool.submit(self.__logic.Send, toPlayerID, message, True) + + def HaveMessage(self) -> bool: + return self.__logic.HaveMessage() + + def GetMessage(self) -> Tuple[int, str]: + return self.__logic.GetMessage() + + def GetFrameCount(self) -> int: + return self.__logic.GetCounter() + + def Wait(self) -> bool: + return self.__logic.WaitThread() + + def EndAllAction(self) -> Future[bool]: + return self.__pool.submit(self.__logic.EndAllAction) + + def GetCharacters(self) -> List[THUAI8.Character]: + return self.__logic.GetCharacters() + + def GetEnemyCharacters(self) -> List[THUAI8.Character]: + return self.__logic.GetEnemyCharacters() + + def GetFullMap(self) -> List[List[THUAI8.PlaceType]]: + return self.__logic.GetFullMap() + + def GetGameInfo(self) -> THUAI8.GameInfo: + return self.__logic.GetGameInfo() + + def GetPlaceType(self, cellX: int, cellY: int) -> THUAI8.PlaceType: + return self.__logic.GetPlaceType(cellX, cellY) + + def GetEnconomyResourceState(self, cellX: int, cellY: int) -> Optional[THUAI8.EconomyResourceState]: + return self.__logic.GetEnconomyResourceState(cellX, cellY) + + def GetAdditionResourceState(self, cellX: int, cellY: int) -> Optional[THUAI8.AdditionResourceState]: + return self.__logic.GetAdditionResourceState(cellX, cellY) + + def GetConstructionState(self, cellX: int, cellY: int) -> Optional[THUAI8.ConstructionState]: + return self.__logic.GetConstructionState(cellX, cellY) + + def GetPlayerGUIDs(self) -> List[int]: + return self.__logic.GetPlayerGUIDs() + + def GetEnergy(self) -> int: + return self.__logic.GetEnergy() + + def GetScore(self) -> int: + return self.__logic.GetScore() + + def Print(self, string: str) -> None: + pass + + def PrintCharacter(self) -> None: + pass + + def PrintTeam(self) -> None: + pass + + def PrintSelfInfo(self) -> None: + pass + # endregion + + # region 瀹炵幇ITeamAPI鎺ュ彛 + def GetSelfInfo(self) -> THUAI8.Team: + return cast(THUAI8.Team, self.__logic.TeamGetSelfInfo()) + + def InstallEquipment(self, playerID: int, equipmentType: THUAI8.EquipmentType) -> Future[bool]: + return self.__pool.submit(self.__logic.InstallEquipment, playerID, equipmentType) + + def Recycle(self, playerID: int) -> Future[bool]: + return self.__pool.submit(self.__logic.Recycle, playerID) + + def BuildCharacter(self, CharacterType: THUAI8.CharacterType, birthIndex: int) -> Future[bool]: + return self.__pool.submit(self.__logic.BuildCharacter, CharacterType, birthIndex) + # endregion \ No newline at end of file diff --git a/CAPI/python/DebugAPI.py b/CAPI/python/DebugAPI.py new file mode 100644 index 0000000..82f39a9 --- /dev/null +++ b/CAPI/python/DebugAPI.py @@ -0,0 +1,325 @@ +import PyAPI.structures as THUAI8 +import logging +import os +import datetime +from concurrent.futures import ThreadPoolExecutor, Future +from typing import List, Tuple, Optional, Dict, Any, Union +import math +from PyAPI.structures import PlaceType, ConstructionType, CharacterType, GameInfo, Character, ConstructionState, EconomyResourceState, AdditionResourceState +from PyAPI.Interface import ILogic, IAI + +PI = math.pi + +class CharacterDebugAPI: + def __init__(self, logic: ILogic, file: bool, print: bool, warnOnly: bool, CharacterID: int): + self.logic = logic + self.playerID = CharacterID + self.startPoint = datetime.datetime.now() + self.__pool = ThreadPoolExecutor(20) + self.logger = logging.getLogger(f"api {self.playerID}") + self.logger.setLevel(logging.DEBUG) + + formatter = logging.Formattter( + f"[api {self.playerID}] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", + "%H:%M:%S" + ) + + if not os.path.exists("logs"): + os.makedirs("logs") + + fileHandler = logging.FileHandler(f"logs/api-{self.playerID}-log.txt", mode="w+", encoding="utf-8") + printHandler = logging.StreamHandler() + + fileHandler.setFormatter(formatter) + printHandler.setFormatter(formatter) + + fileHandler.setLevel(logging.TRACE if file else logging.OFF) + print_level = logging.WARN if warnOnly else (logging.INFO if print else logging.OFF) + printHandler.setLevel(print_level) + + self.logger.addHandler(fileHandler) + self.logger.addHandler(printHandler) + self.logger.propagate = False + + def StartTimer(self) -> None: + self.startPoint = datetime.datetime.now() + self.logger.info("=== AI.play() ===") + self.logger.info(f"StartTimer: {self.startPoint.strftime('%H:%M:%S')}") + + def EndTimer(self) -> None: + elapsed = (datetime.datetime.now() - self.startPoint).total_seconds() * 1000 + self.logger.info(f"Time elapsed: {elapsed:.2f}ms") + + def GetFrameCount(self) -> int: + return self.logic.GetCounter() + + def SendTextMessage(self, toID: int, message: str) -> Future[bool]: + self.logger.info(f"SendTextMessage: toID={toID}, message={message}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logSend, toID, message, False) + + def SendBinaryMessage(self, toID: int, message: bytes) -> Future[bool]: + self.logger.info(f"SendBinaryMessage: toID={toID}, message={message}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logSend, toID, message, True) + + def __logSend(self, toID: int, message: Union[str, bytes], isBinary: bool) -> bool: + result = self.logic.Send(toID, message, isBinary) + if not result: + self.logger.warning(f"Send failed at {self.__GetTime()}ms") + return result + + def HaveMessage(self) -> bool: + self.logger.info(f"HaveMessage: called at {self.__GetTime()}ms") + result = self.logic.HaveMessage() + if not result: + self.logger.warning(f"HaveMessage failed at {self.__GetTime()}ms") + return result + + def GetMessage(self) -> Tuple[int, str]: + self.logger.info(f"GetMessage: called at {self.__GetTime()}ms") + result = self.logic.GetMessage() + if result[0] == -1: + self.logger.warning(f"GetMessage failed at {self.__GetTime()}ms") + return result + + def Wait(self) -> bool: + self.logger.info(f"Wait: called at {self.__GetTime()}ms") + return False if self.logic.GetCounter() == -1 else self.logic.WaitThread() + + def Move(self, timeInMilliseconds: int, angleInRadian: float) -> Future[bool]: + self.logger.info(f"Move: time={timeInMilliseconds}ms, angle={angleInRadian}rad, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logMove, timeInMilliseconds, angleInRadian) + + def __logMove(self, time: int, angle: float) -> bool: + result = self.logic.Move(time, angle) + if not result: + self.logger.warning(f"Move failed at {self.__GetTime()}ms") + return result + + def MoveDown(self, time: int) -> Future[bool]: + return self.Move(time, 0) + + def MoveRight(self, time: int) -> Future[bool]: + return self.Move(time, PI * 0.5) + + def MoveUp(self, time: int) -> Future[bool]: + return self.Move(time, PI) + + def MoveLeft(self, time: int) -> Future[bool]: + return self.Move(time, PI * 1.5) + + def Skill_Attack(self, angleInRadian: float) -> Future[bool]: + self.logger.info(f"Skill_Attack: angle={angleInRadian}rad, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logSkillAttack, angleInRadian) + + def __logSkillAttack(self, angle: float) -> bool: + result = self.logic.SkillAttack(angle) + if not result: + self.logger.warning(f"Skill_Attack failed at {self.__GetTime()}ms") + return result + + def Common_Attack(self, angleInRadian: float) -> Future[bool]: + self.logger.info(f"Common_Attack: angle={angleInRadian}rad, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logCommonAttack, angleInRadian) + + def __logCommonAttack(self, angle: float) -> bool: + result = self.logic.CommonAttack(angle) + if not result: + self.logger.warning(f"Common_Attack failed at {self.__GetTime()}ms") + return result + + def Recover(self, recover: int) -> Future[bool]: + self.logger.info(f"Recover: {recover}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logRecover, recover) + + def __logRecover(self, recover: int) -> bool: + result = self.logic.Recover(recover) + if not result: + self.logger.warning(f"Recover failed at {self.__GetTime()}ms") + return result + + def Harvest(self) -> Future[bool]: + self.logger.info(f"Harvest: called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logHarvest) + + def __logHarvest(self) -> bool: + result = self.logic.Harvest() + if not result: + self.logger.warning(f"Harvest failed at {self.__GetTime()}ms") + return result + + def Rebuild(self, constructionType: ConstructionType) -> Future[bool]: + self.logger.info(f"Rebuild: {constructionType}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logRebuild, constructionType) + + def __logRebuild(self, ct: ConstructionType) -> bool: + result = self.logic.Rebuild(ct) + if not result: + self.logger.warning(f"Rebuild failed at {self.__GetTime()}ms") + return result + + def Construct(self, constructionType: ConstructionType) -> Future[bool]: + self.logger.info(f"Construct: {constructionType}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logConstruct, constructionType) + + def __logConstruct(self, ct: ConstructionType) -> bool: + result = self.logic.Construct(ct) + if not result: + self.logger.warning(f"Construct failed at {self.__GetTime()}ms") + return result + + def GetCharacters(self) -> List[Character]: + self.logger.info(f"GetCharacters: called at {self.__GetTime()}ms") + result = self.logic.GetCharacters() + if not result: + self.logger.warning(f"GetCharacters failed at {self.__GetTime()}ms") + return result + + def GetEnemyCharacters(self) -> List[Character]: + self.logger.info(f"GetEnemyCharacters: called at {self.__GetTime()}ms") + result = self.logic.GetEnemyCharacters() + if not result: + self.logger.warning(f"GetEnemyCharacters failed at {self.__GetTime()}ms") + return result + + def GetFullMap(self) -> List[List[PlaceType]]: + self.logger.info(f"GetFullMap: called at {self.__GetTime()}ms") + result = self.logic.GetFullMap() + if not result: + self.logger.warning(f"GetFullMap failed at {self.__GetTime()}ms") + return result + + def GetGameInfo(self) -> GameInfo: + self.logger.info(f"GetGameInfo: called at {self.__GetTime()}ms") + result = self.logic.GetGameInfo() + if not result: + self.logger.warning(f"GetGameInfo failed at {self.__GetTime()}ms") + return result + + def GetPlaceType(self, cellX: int, cellY: int) -> Optional[PlaceType]: + self.logger.info(f"GetPlaceType: cellX={cellX}, cellY={cellY}, called at {self.__GetTime()}ms") + result = self.logic.GetPlaceType(cellX, cellY) + if not result: + self.logger.warning(f"GetPlaceType failed at {self.__GetTime()}ms") + return result + + def GetEnconomyResourceState(self, cellX: int, cellY: int) -> Optional[EconomyResourceState]: + self.logger.info(f"GetEnconomyResourceState: cellX={cellX}, cellY={cellY}, called at {self.__GetTime()}ms") + result = self.logic.GetEnconomyResourceState(cellX, cellY) + if not result: + self.logger.warning(f"GetEnconomyResourceState failed at {self.__GetTime()}ms") + return result + + def GetAdditionResourceState(self, cellX: int, cellY: int) -> Optional[AdditionResourceState]: + self.logger.info(f"GetAdditionResourceState: cellX={cellX}, cellY={cellY}, called at {self.__GetTime()}ms") + result = self.logic.GetAdditionResourceState(cellX, cellY) + if not result: + self.logger.warning(f"GetAdditionResourceState failed at {self.__GetTime()}ms") + return result + + def GetConstructionState(self, cellX: int, cellY: int) -> Optional[ConstructionState]: + self.logger.info(f"GetConstructionState: cellX={cellX}, cellY={cellY}, called at {self.__GetTime()}ms") + result = self.logic.GetConstructionState(cellX, cellY) + if not result: + self.logger.warning(f"GetConstructionState failed at {self.__GetTime()}ms") + return result + + def GetPlayerGUIDs(self) -> List[int]: + self.logger.info(f"GetPlayerGUIDs: called at {self.__GetTime()}ms") + result = self.logic.GetPlayerGUIDs() + if not result: + self.logger.warning(f"GetPlayerGUIDs failed at {self.__GetTime()}ms") + return result + + def GetEnergy(self) -> int: + self.logger.info(f"GetEnergy: called at {self.__GetTime()}ms") + result = self.logic.GetEnergy() + if result == -1: + self.logger.warning(f"GetEnergy failed at {self.__GetTime()}ms") + return result + + def GetScore(self) -> int: + self.logger.info(f"GetScore: called at {self.__GetTime()}ms") + result = self.logic.GetScore() + if result == -1: + self.logger.warning(f"GetScore failed at {self.__GetTime()}ms") + return result + + def GetSelfInfo(self) -> Character: + self.logger.info(f"GetSelfInfo: called at {self.__GetTime()}ms") + result = self.logic.GetSelfInfo() + if not result: + self.logger.warning(f"GetSelfInfo failed at {self.__GetTime()}ms") + return result + + def Print(self, string: str) -> None: + self.logger.info(string) + + def PrintCharacter(self) -> None: + for char in self.logic.GetCharacters(): + self.logger.info("******Character Info******") + self.logger.info(f"type={char.characterType}, ID={char.characterID}, GUID={char.guid}, x={char.x}, y={char.y}") + self.logger.info(f"state={char.characterState}, speed={char.speed}, view={char.viewRange}, facing={char.facingDirection}") + self.logger.info("**************************") + + def PrintSelfInfo(self) -> None: + selfInfo = self.GetSelfInfo() + self.logger.info("******Self Info******") + self.logger.info(f"type={selfInfo.characterType}, ID={selfInfo.characterID}, GUID={selfInfo.guid}") + self.logger.info(f"x={selfInfo.x}, y={selfInfo.y}, state={selfInfo.characterState}") + self.logger.info("*********************") + + def EndAllAction(self) -> Future[bool]: + self.logger.info(f"EndAllAction: called at {self.__GetTime()}ms") + return self.__pool.submit(self.logic.EndAllAction) + + def __GetTime(self) -> float: + return (datetime.datetime.now() - self.startPoint).total_seconds() * 1000 + + def Play(self, ai: IAI) -> None: + ai.play(self) + +class TeamDebugAPI(CharacterDebugAPI): + def __init__(self, logic: ILogic, file: bool, print: bool, warnOnly: bool, playerID: int): + super().__init__(logic, file, print, warnOnly, playerID) + # 瑕嗙洊鐖剁被logger閰嶇疆 + self.logger.handlers.clear() + formatter = logging.Formatter( + f"[api{self.playerID}] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", + "%H:%M:%S" + ) + fileHandler = logging.FileHandler(f"logs/api-{self.playerID}-log.txt", mode="w+", encoding="utf-8") + printHandler = logging.StreamHandler() + fileHandler.setFormatter(formatter) + printHandler.setFormatter(formatter) + fileHandler.setLevel(logging.TRACE if file else logging.OFF) + print_level = logging.WARN if warnOnly else (logging.INFO if print else logging.OFF) + printHandler.setLevel(print_level) + self.logger.addHandler(fileHandler) + self.logger.addHandler(printHandler) + + def InstallEquipment(self, playerID: int, equipmentType: Any) -> Future[bool]: + self.logger.info(f"InstallEquipment: playerID={playerID}, type={equipmentType}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logInstall, playerID, equipmentType) + + def __logInstall(self, pid: int, et: Any) -> bool: + result = self.logic.InstallEquipment(pid, et) + if not result: + self.logger.warning(f"InstallEquipment failed at {self.__GetTime()}ms") + return result + + def BuildCharacter(self, characterType: CharacterType, birthIndex: int) -> Future[bool]: + self.logger.info(f"BuildCharacter: type={characterType}, index={birthIndex}, called at {self.__GetTime()}ms") + return self.__pool.submit(self.__logBuild, characterType, birthIndex) + + def __logBuild(self, ct: CharacterType, bi: int) -> bool: + result = self.logic.BuildCharacter(ct, bi) + if not result: + self.logger.warning(f"BuildCharacter failed at {self.__GetTime()}ms") + return result + + def PrintSelfInfo(self) -> None: + selfInfo = self.logic.GetSelfInfo() + self.logger.info("******Team Info******") + self.logger.info(f"teamID={selfInfo.teamID}, playerID={selfInfo.playerID}") + self.logger.info(f"score={selfInfo.score}, energy={selfInfo.energy}") + self.logger.info("*********************") \ No newline at end of file diff --git a/dependency/proto/Message2Clients.proto b/dependency/proto/Message2Clients.proto index 087d16b..15501b5 100644 --- a/dependency/proto/Message2Clients.proto +++ b/dependency/proto/Message2Clients.proto @@ -25,56 +25,62 @@ message MessageOfCharacter // 琚姩鐘舵 CharacterState blind_state = 6; - double blind_time = 7; - CharacterState knockback_state = 8; - double knockback_time = 9; - CharacterState stunned_state = 10; - double stunned_time = 11; - CharacterState invisible_state = 12; - double invisible_time = 13; - CharacterState healing_state = 14; - double healing_time = 15; - CharacterState berserk_state = 16; - double berserk_time = 17; - CharacterState burned_state = 18; - double burned_time = 19; - CharacterState harm_cut_state = 20; - double harm_cut_time = 21; - CharacterState deceased_state = 22; // 姝讳骸鐘舵佷笉闇瑕佹寔缁椂闂 + int64 blind_time = 7; + // CharacterState knockback_state = 8; + // double knockback_time = 9; + CharacterState stunned_state = 8; + int64 stunned_time = 9; + CharacterState invisible_state = 10; + int64 invisible_time = 11; + // CharacterState healing_state = 14; + // long healing_time = 15; + // CharacterState berserk_state = 16; + // long berserk_time = 17; + CharacterState burned_state = 12; + int64 burned_time = 13; + double harm_cut = 14; + int64 harm_cut_time = 15; + CharacterState deceased_state = 16; // 姝讳骸鐘舵佷笉闇瑕佹寔缁椂闂 - int32 x = 23; - int32 y = 24; + CharacterState character_passive_state = 17; // 鏈鏂拌鍔ㄧ姸鎬佺姸鎬 - double facing_direction = 25; - int32 speed = 26; - int32 view_range = 27; + int32 x = 18; + int32 y = 19; - int32 common_attack = 28; - double common_attack_cd = 29; - int32 common_attack_range = 30; + double facing_direction = 20; + int32 speed = 21; + int32 view_range = 22; - double skill_attack_cd = 31; + int32 common_attack = 23; + int64 common_attack_cd = 24; + int32 common_attack_range = 25; - int32 economy_depletion = 32; // 缁忔祹璧勬簮娑堣 - int32 kill_score = 33; // 鍑绘潃寰楀垎 + int64 skill_attack_cd = 26; + + int32 economy_depletion = 27; // 缁忔祹璧勬簮娑堣 + int32 kill_score = 28; // 鍑绘潃寰楀垎 - int32 hp = 34; + int32 hp = 29; // 鍏跺畠瑁呭閮芥槸鐩存帴娑堣楋紝涓嶉渶瑕佽褰 - EquipmentType shield_equipment = 35; // NULL_EQUIPMENT_TYPE琛ㄧず娌℃湁瑁呭 - int32 shild = 36; // 鎶ょ浘鍓╀綑 - EquipmentType shoes_equipment = 37; - double shoes_time = 38; + int32 shield_equipment = 30; // 鎶ょ浘鍓╀綑鍊硷紝鍙惈瑁呭 + // EquipmentType shoes_equipment = ; // 闉嬪瓙瑁呭 + int32 shoes_equipment = 31; + int64 shoes_equipment_time = 32; + // EquipmentType purification_equipment = ; + int64 purification_equipment_time = 33; + // EquipmentType invisibility_equipment = ; + // long invisibility_equipment_time = ; + // EquipmentType berserk_equipment = ; + // long berserk_equipment_time = ; // 鍔犳垚璧勬簮鐨凚uff - CharacterBuffType attack_buff = 39; - double attack_buff_time = 40; - CharacterBuffType defense_buff = 41; - double defense_buff_time = 42; - CharacterBuffType speed_buff = 43; - double speed_buff_time = 44; - CharacterBuffType vision_buff = 45; - double vision_buff_time = 46; + // CharacterBuffType attack_buff = 39; + int64 attack_buff_time = 34; + // CharacterBuffType speed_buff = 43; + int64 speed_buff_time = 35; + // CharacterBuffType vision_buff = 45; + int64 vision_buff_time = 36; } message MessageOfBarracks diff --git a/dependency/proto/MessageType.proto b/dependency/proto/MessageType.proto index 94d5b75..d2e7bcc 100644 --- a/dependency/proto/MessageType.proto +++ b/dependency/proto/MessageType.proto @@ -61,7 +61,6 @@ enum CharacterState // 瑙掕壊鐘舵 CONSTRUCTING = 5; MOVING = 6; - BLIND = 7; KNOCKED_BACK = 8; STUNNED = 9; @@ -69,8 +68,8 @@ enum CharacterState // 瑙掕壊鐘舵 HEALING = 11; BERSERK = 12; BURNED = 13; - HARM_CUT = 14; - DECEASED = 15; + // HARM_CUT = 14; + DECEASED = 14; } enum CharacterBuffType diff --git a/docs/CAPI.md b/docs/CAPI.md new file mode 100644 index 0000000..dccfe10 --- /dev/null +++ b/docs/CAPI.md @@ -0,0 +1,66 @@ +# 鎺ュ彛涓瑙 +``` + //閫氱敤鎺ュ彛 + //鍙戦佷俊鎭佹帴鍙椾俊鎭紝娉ㄦ剰鏀舵秷鎭槸鏃犳秷鎭垯杩斿洖-1鍜岀┖鈥渟tring鈥 + virtual std::future SendTextMessage(int32_t toPlayerID, std::string) = 0; + virtual std::future SendBinaryMessage(int32_t toPlayerID, std::string) = 0; + [[nodiscard]] virtual bool HaveMessage() = 0; + [[nodiscard]] virtual std::pair GetMessage() = 0; + + //鑾峰彇娓告垙鐩墠鎵杩涜鐨勫抚鏁 + [[nodiscard]] virtual int32_t GetFrameCount() const = 0; + + //绛夊緟涓嬩竴甯 + virtual bool Wait() = 0; + virtual std::future EndAllAction() = 0; + [[nodiscard]] virtual std::vector> GetCharacters() const = 0; + [[nodiscard]] virtual std::vector> GetEnemyCharacters() const = 0; + [[nodiscard]] virtual std::vector> GetFullMap() const = 0; + [[nodiscard]] virtual std::shared_ptr GetGameInfo() const = 0; + [[nodiscard]] virtual THUAI8::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual std::optional GetEnconomyResourceState(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual std::optional GetAdditionResourceState(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual std::optional GetConstructionState(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual std::vector GetPlayerGUIDs() const = 0; + [[nodiscard]] virtual int32_t GetEnergy() const = 0; + [[nodiscard]] virtual int32_t GetScore() const = 0; + + //鎺у埗瑙掕壊杩涜绉诲姩 + virtual std::future Move(int32_t speed, int64_t timeInMilliseconds, double angleInRadian) = 0; + //鍚戠壒瀹氭柟鍚戠Щ鍔 + virtual std::future MoveRight(int32_t speed, int64_t timeInMilliseconds) = 0; + virtual std::future MoveUp(int32_t speed, int64_t timeInMilliseconds) = 0; + virtual std::future MoveLeft(int32_t speed, int64_t timeInMilliseconds) = 0; + virtual std::future MoveDown(int32_t speed, int64_t timeInMilliseconds) = 0; + virtual std::future Skill_Attack(int64_t attackedPlayerID) = 0; + virtual std::future Common_Attack(int64_t attackedPlayerID) = 0; + virtual std::future Recover(int64_t recover) = 0; + virtual std::future Harvest() = 0; + virtual std::future Rebuild(THUAI8::ConstructionType constructionType) = 0; + virtual std::future Construct(THUAI8::ConstructionType constructionType) = 0; + virtual std::shared_ptr GetSelfInfo() const = 0; + virtual bool HaveView(int32_t targetX, int32_t targetY) const = 0; + + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; + virtual std::future InstallEquipment(int32_t playerID, THUAI8::EquipmentType equipmenttype) = 0; + virtual std::future Recycle(int32_t playerID) = 0; + virtual std::future BuildCharacter(THUAI8::CharacterType CharacterType, int32_t birthIndex) = 0; + + // 鑾峰彇鎸囧畾鏍煎瓙涓績鐨勫潗鏍 + [[nodiscard]] static inline int32_t CellToGrid(int32_t cell) noexcept + { + return cell * numOfGridPerCell + numOfGridPerCell / 2; + } + + // 鑾峰彇鎸囧畾鍧愭爣鐐规墍浣嶄簬鐨勬牸瀛愮殑 X 搴忓彿 + [[nodiscard]] static inline int32_t GridToCell(int32_t grid) noexcept + { + return grid / numOfGridPerCell; + } + + // 鐢ㄤ簬DEBUG鐨勮緭鍑哄嚱鏁帮紝閫夋墜浠呭湪寮鍚疍ebug妯″紡鐨勬儏鍐典笅鍙互浣跨敤 + + virtual void Print(std::string str) const = 0; + virtual void PrintCharacter() const = 0; + virtual void PrintTeam() const = 0; + virtual void PrintSelfInfo() const = 0; diff --git a/docs/THUAI8娓告垙瑙勫垯.md b/docs/THUAI8娓告垙瑙勫垯.md index 97b9a43..8e650ff 100644 --- a/docs/THUAI8娓告垙瑙勫垯.md +++ b/docs/THUAI8娓告垙瑙勫垯.md @@ -1,4 +1,4 @@ -# THUAI8娓告垙閫夐锛堟敼绋匡級 +# THUAI8 瑗挎父鐪熺粡鍔 ## 娓告垙鑳屾櫙 @@ -198,12 +198,12 @@ 鍚勭被鍨嬪缓绛戠殑鍔熻兘銆佹崯鑰楄涓嬭〃锛 -| 鍚嶇О | 鍔熻兘 | 鑺辫垂/鐮村潖寰楀垎 | 琛閲 | 寤洪犳椂闂 | -| :------: | :----------------------------------------------------------: | :-----------: | :--: | :------: | -| 鍏佃惀 | 瑙掕壊鍑虹敓鐐癸紝寮灞鑷甫涓搴у叺钀ワ紝鑷冲鍙啀淇缓涓ゅ骇鍏佃惀銆傚悓鏃跺崐寰1000鑼冨洿鍐呯殑宸辨柟瑙掕壊鍙寔缁洖琛锛10鐐/s锛 | 1w/6000 | 600 | 15s | -| 鍐滃満 | 姣忓骇鍐滃満姣忕浜у嚭100缁忔祹锛岃嚦澶氬彲鍐嶄慨寤4涓啘鍦恒 | 8000/4000 | 400 | 10s | -| 鍧戞礊闄烽槺 | 淇缓鍚庢晫鏂逛笉鍙銆傚綋鏁屾柟瑙掕壊瑙︾浠ラ櫡闃变负涓績鐨勪節瀹牸鏃讹紝鍙楀埌姣忕20鐐圭殑浼ゅ锛屾寔缁5s锛屽悓鏃朵細鏆撮湶瑙嗛噹 | 1000 | / | 5s | -| 鐗㈢闄烽槺 | 淇缓鍚庢晫鏂逛笉鍙銆傚綋鏁屾柟瑙掕壊瑙︾浠ラ櫡闃变负涓績鐨勪節瀹牸鏃讹紝浼氳瀹氳韩30s锛屾棤娉曠Щ鍔紝涓旀毚闇茶閲 | 1000 | / | 5s | +| 鍚嶇О | 鍔熻兘 | 鑺辫垂/鐮村潖寰楀垎 | 琛閲 | 寤洪犳椂闂 | +| :------: | :--------------------------------------------------------------------------------------------------: | :-----------: | :---: | :------: | +| 鍏佃惀 | 瑙掕壊鍑虹敓鐐癸紝寮灞鑷甫涓搴у叺钀ワ紝鑷冲鍙啀淇缓涓ゅ骇鍏佃惀銆傚悓鏃跺崐寰1000鑼冨洿鍐呯殑宸辨柟瑙掕壊鍙寔缁洖琛锛10鐐/s锛 | 1w/6000 | 600 | 15s | +| 鍐滃満 | 姣忓骇鍐滃満姣忕浜у嚭100缁忔祹锛岃嚦澶氬彲鍐嶄慨寤4涓啘鍦恒 | 8000/4000 | 400 | 10s | +| 鍧戞礊闄烽槺 | 淇缓鍚庢晫鏂逛笉鍙銆傚綋鏁屾柟瑙掕壊瑙︾浠ラ櫡闃变负涓績鐨勪節瀹牸鏃讹紝鍙楀埌姣忕20鐐圭殑浼ゅ锛屾寔缁5s锛屽悓鏃朵細鏆撮湶瑙嗛噹 | 1000 | / | 5s | +| 鐗㈢闄烽槺 | 淇缓鍚庢晫鏂逛笉鍙銆傚綋鏁屾柟瑙掕壊瑙︾浠ラ櫡闃变负涓績鐨勪節瀹牸鏃讹紝浼氳瀹氳韩30s锛屾棤娉曠Щ鍔紝涓旀毚闇茶閲 | 1000 | / | 5s | **寤虹瓚鐨勪慨寤**锛氶櫎鈥濆潙娲為櫡闃扁滃拰鈥濈墷绗奸櫡闃扁滃锛屽湴鍥句笂鏈夌壒瀹氱殑寤虹瓚鐐逛綅锛岃鑹茬Щ鍔ㄥ埌寤虹瓚鐐逛綅涔濆鏍煎唴鏃讹紝鍙互寮濮嬩慨寤哄缓绛戙傗濆潙娲為櫡闃扁滃拰鈥濈墷绗奸櫡闃扁滃彲浠ュ湪鍦板浘涓婁换鎰忎竴澶勨濈┖鍦扳滄垨鈥濊崏涓涒滀慨寤猴紝瑙掕壊淇缓瀹屾垚锛屼細鍑虹幇鍦ㄨ窛绂昏鑹蹭腑蹇冩渶杩戠殑鏂规牸澶勩傛涓ょ寤虹瓚褰㈠悓鈥濈┖鍦扳滃拰鈥濊崏涓涒滐紝鍦ㄦ湭瑙﹀彂鎯呭喌涓嬩笉浼氶樆闅旇鑹茬Щ鍔ㄣ diff --git a/interface/AvaloniaUI_debug_interface/debug_interface/Assets/tangseng2.png b/interface/AvaloniaUI_debug_interface/debug_interface/Assets/tangseng2.png new file mode 100644 index 0000000..c93b2e0 Binary files /dev/null and b/interface/AvaloniaUI_debug_interface/debug_interface/Assets/tangseng2.png differ diff --git a/interface/AvaloniaUI_debug_interface/debug_interface/Controls/MapHelper.cs b/interface/AvaloniaUI_debug_interface/debug_interface/Controls/MapHelper.cs new file mode 100644 index 0000000..b36cfb6 --- /dev/null +++ b/interface/AvaloniaUI_debug_interface/debug_interface/Controls/MapHelper.cs @@ -0,0 +1,262 @@ +锘// MapHelper.cs +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Media; +using debug_interface.Models; +using debug_interface.ViewModels; +using System; +using System.Collections.Generic; + +namespace debug_interface.Controls +{ + public static class MapHelper + { + private static Dictionary cellRectangles = new Dictionary(); + private static Grid? gridContainer; + + /// + /// 鍒濆鍖栧湴鍥剧綉鏍 + /// + public static Grid CreateMapGrid(MapViewModel mapViewModel) + { + // 娓呯┖鐜版湁璁板綍 + cellRectangles.Clear(); + + // 鍒涘缓Grid瀹瑰櫒锛岃缃负50x50鐨勭綉鏍 + var grid = new Grid(); + gridContainer = grid; + + // 瀹氫箟鍒 + for (int i = 0; i < 50; i++) + { + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); + } + + // 瀹氫箟琛 + for (int i = 0; i < 50; i++) + { + grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); + } + + // 缁樺埗鍗曞厓鏍 + for (int i = 0; i < 50; i++) + { + for (int j = 0; j < 50; j++) + { + int index = i * 50 + j; + + if (index < mapViewModel.MapCells.Count) + { + var cell = mapViewModel.MapCells[index]; + + // 鍒涘缓鐭╁舰鍗曞厓鏍 + var rectangle = new Rectangle + { + Fill = cell.DisplayColor, + Margin = new Thickness(0), + [Grid.RowProperty] = i, + [Grid.ColumnProperty] = j + }; + + // 涓哄崟鍏冩牸娣诲姞鏂囨湰锛堝鏋滄湁锛 + if (!string.IsNullOrEmpty(cell.DisplayText)) + { + var textBlock = new TextBlock + { + Text = cell.DisplayText, + FontSize = 6, + TextAlignment = TextAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + [Grid.RowProperty] = i, + [Grid.ColumnProperty] = j, + ZIndex = 1 // 纭繚鏂囨湰鍦ㄧ煩褰笂鏂 + }; + grid.Children.Add(textBlock); + } + + // 瀛樺偍鐭╁舰寮曠敤浠ヤ究鍚庣画鏇存柊 + cellRectangles[index] = rectangle; + grid.Children.Add(rectangle); + } + } + } + + // 娣诲姞缃戞牸绾匡紙鍦ㄥ崟鍏冩牸涓婃柟锛 + AddGridLines(grid); + + return grid; + } + /// + /// 鍒濆鍖栧湴鍥剧綉鏍 + /// + public static void InitializeMapGrid(Grid grid, MapViewModel mapViewModel) + { + // 娓呯┖鎵鏈夌幇鏈夊唴瀹 + grid.Children.Clear(); + grid.RowDefinitions.Clear(); + grid.ColumnDefinitions.Clear(); + cellRectangles.Clear(); + gridContainer = grid; + + // 瀹氫箟鍒 + for (int i = 0; i < 50; i++) + { + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); + } + + // 瀹氫箟琛 + for (int i = 0; i < 50; i++) + { + grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); + } + + // 缁樺埗鍗曞厓鏍 + for (int i = 0; i < 50; i++) + { + for (int j = 0; j < 50; j++) + { + int index = i * 50 + j; + + if (index < mapViewModel.MapCells.Count) + { + var cell = mapViewModel.MapCells[index]; + + // 鍒涘缓鐭╁舰鍗曞厓鏍 + var rectangle = new Rectangle + { + Fill = cell.DisplayColor, + Margin = new Thickness(0), + [Grid.RowProperty] = i, + [Grid.ColumnProperty] = j + }; + + // 涓哄崟鍏冩牸娣诲姞鏂囨湰锛堝鏋滄湁锛 + if (!string.IsNullOrEmpty(cell.DisplayText)) + { + var textBlock = new TextBlock + { + Text = cell.DisplayText, + FontSize = 6, + TextAlignment = TextAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + [Grid.RowProperty] = i, + [Grid.ColumnProperty] = j, + ZIndex = 1 // 纭繚鏂囨湰鍦ㄧ煩褰笂鏂 + }; + grid.Children.Add(textBlock); + } + + // 瀛樺偍鐭╁舰寮曠敤浠ヤ究鍚庣画鏇存柊 + cellRectangles[index] = rectangle; + grid.Children.Add(rectangle); + } + } + } + + // 娣诲姞缃戞牸绾匡紙鍦ㄥ崟鍏冩牸涓婃柟锛 + AddGridLines(grid); + } + + /// + /// 娣诲姞缃戞牸绾 + /// + private static void AddGridLines(Grid grid) + { + // 娣诲姞姘村钩缃戞牸绾 + for (int i = 0; i <= 50; i++) + { + var line = new Line + { + StartPoint = new Point(0, 0), + EndPoint = new Point(1, 0), + Stroke = Brushes.Gray, + StrokeThickness = 1, + Stretch = Stretch.Fill, + ZIndex = 2 // 纭繚缃戞牸绾垮湪鏈涓婂眰 + }; + + if (i < 50) // 鏈鍚庝竴琛屼笉闇瑕佹坊鍔 + { + line.SetValue(Grid.RowProperty, i); + line.SetValue(Grid.ColumnSpanProperty, 50); + line.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Bottom; + grid.Children.Add(line); + } + } + + // 娣诲姞鍨傜洿缃戞牸绾 + for (int j = 0; j <= 50; j++) + { + var line = new Line + { + StartPoint = new Point(0, 0), + EndPoint = new Point(0, 1), + Stroke = Brushes.Gray, + StrokeThickness = 1, + Stretch = Stretch.Fill, + ZIndex = 2 // 纭繚缃戞牸绾垮湪鏈涓婂眰 + }; + + if (j < 50) // 鏈鍚庝竴鍒椾笉闇瑕佹坊鍔 + { + line.SetValue(Grid.ColumnProperty, j); + line.SetValue(Grid.RowSpanProperty, 50); + line.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Right; + grid.Children.Add(line); + } + } + } + + /// + /// 鏇存柊鍗曞厓鏍奸鑹 + /// + public static void UpdateCellColor(int x, int y, IBrush color) + { + int index = x * 50 + y; + if (cellRectangles.ContainsKey(index)) + { + cellRectangles[index].Fill = color; + } + } + + /// + /// 鏇存柊鍗曞厓鏍兼枃鏈 + /// + public static void UpdateCellText(int x, int y, string text) + { + if (gridContainer == null) return; + + // 鏌ユ壘瀵瑰簲浣嶇疆鐨凾extBlock骞舵洿鏂 + foreach (var child in gridContainer.Children) + { + if (child is TextBlock textBlock && + Grid.GetRow(textBlock) == x && + Grid.GetColumn(textBlock) == y) + { + textBlock.Text = text; + return; + } + } + + // 濡傛灉娌℃湁鎵惧埌鐜版湁鐨凾extBlock锛屽垱寤烘柊鐨 + if (!string.IsNullOrEmpty(text)) + { + var textBlock = new TextBlock + { + Text = text, + FontSize = 6, + TextAlignment = TextAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + [Grid.RowProperty] = x, + [Grid.ColumnProperty] = y, + ZIndex = 1 + }; + gridContainer.Children.Add(textBlock); + } + } + } +} \ No newline at end of file diff --git a/interface/AvaloniaUI_debug_interface/debug_interface/ViewModels/CharacterViewModel.cs b/interface/AvaloniaUI_debug_interface/debug_interface/ViewModels/CharacterViewModel.cs index 5393022..ec1c2ba 100644 --- a/interface/AvaloniaUI_debug_interface/debug_interface/ViewModels/CharacterViewModel.cs +++ b/interface/AvaloniaUI_debug_interface/debug_interface/ViewModels/CharacterViewModel.cs @@ -24,16 +24,7 @@ namespace debug_interface.ViewModels // 鍙兘鍊: "绌虹疆","寮閲","鏀诲嚮","閲婃斁鎶鑳","寤洪","绉诲姩" [ObservableProperty] private string activeState = "绌虹疆"; - //public string ActiveState - //{ - // get => activeState; - // set - // { - // if (value == activeState) return; - // activeState = value; - // OnPropertyChanged(nameof(DisplayStates)); - // } - //} + // 琚姩鐘舵侊紙鍙彔鍔狅級 // 鍙兘鍊: "鑷寸洸","鍑婚","瀹氳韩","闅愯韩" 绛夛紝鍙敱鏈嶅姟鍣ㄦ帶鍒跺鍑 public ObservableCollection PassiveStates { get; } = new ObservableCollection(); diff --git a/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml b/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml index 4465001..b7ac18f 100644 --- a/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml +++ b/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml @@ -1,4 +1,4 @@ - + - - - - - - - - - - - - - - - - + + + - - - + + + \ No newline at end of file diff --git a/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml.cs b/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml.cs index 7765428..2c33bc6 100644 --- a/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml.cs +++ b/interface/AvaloniaUI_debug_interface/debug_interface/Views/MapView.axaml.cs @@ -4,18 +4,22 @@ using Avalonia.Controls; using Avalonia.Controls.Shapes; using Avalonia.Media; using Avalonia.VisualTree; +using debug_interface.Controls; +using debug_interface.Models; using debug_interface.ViewModels; using System; using System.Collections.Generic; using System.Collections.Specialized; + namespace debug_interface.Views { public partial class MapView : UserControl { + private Canvas? characterCanvas; - private ItemsControl? mapItemsControl; - private Dictionary characterEllipses = new Dictionary(); + private Grid? mapGrid; + private Dictionary characterElements = new Dictionary(); private MainWindowViewModel? viewModel; public MapView() @@ -26,10 +30,9 @@ namespace debug_interface.Views this.DataContextChanged += MapView_DataContextChanged; } + private void MapView_DataContextChanged(object? sender, EventArgs e) { - // When the data context changes, get the parent window's DataContext - // which should be the MainWindowViewModel var mainWindow = this.FindAncestorOfType(); if (mainWindow != null && mainWindow.DataContext is MainWindowViewModel vm) { @@ -40,9 +43,8 @@ namespace debug_interface.Views private void MapView_AttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { characterCanvas = this.FindControl("CharacterCanvas"); - mapItemsControl = this.FindControl("MapItemsControl"); + mapGrid = this.FindControl("MapGrid"); // 修改这里,对应XAML - // Get the MainWindowViewModel from the parent MainWindow var mainWindow = this.FindAncestorOfType(); if (mainWindow != null && mainWindow.DataContext is MainWindowViewModel vm) { @@ -50,9 +52,9 @@ namespace debug_interface.Views } } + private void SetupViewModel(MainWindowViewModel vm) { - // Clean up previous handlers if any if (viewModel != null) { viewModel.RedTeamCharacters.CollectionChanged -= RedTeamCharacters_CollectionChanged; @@ -61,32 +63,52 @@ namespace debug_interface.Views viewModel = vm; - // Set the ItemsSource programmatically - if (mapItemsControl != null && viewModel.MapVM != null) + // 初始化地图网格 + if (mapGrid != null && viewModel.MapVM != null) { - mapItemsControl.ItemsSource = viewModel.MapVM.MapCells; + // 直接使用现有的mapGrid + MapHelper.InitializeMapGrid(mapGrid, viewModel.MapVM); + } - // Listen for changes to character collections + // 监听角色集合变化 viewModel.RedTeamCharacters.CollectionChanged += RedTeamCharacters_CollectionChanged; viewModel.BlueTeamCharacters.CollectionChanged += BlueTeamCharacters_CollectionChanged; - // Initialize existing characters + // 初始化角色 RefreshCharacters(); - - // Initialize random positions if not set InitializeRandomPositions(); + + // 监听地图单元格变化(如果模型提供了这种能力) + if (viewModel.MapVM != null) + { + // 如果MapCell类型实现了INotifyPropertyChanged,您可以在这里监听属性变化 + foreach (var cell in viewModel.MapVM.MapCells) + { + cell.PropertyChanged += (s, e) => { + if (s is MapCell mapCell) + { + if (e.PropertyName == nameof(MapCell.DisplayColor)) + { + MapHelper.UpdateCellColor(mapCell.CellX, mapCell.CellY, mapCell.DisplayColor); + } + else if (e.PropertyName == nameof(MapCell.DisplayText)) + { + MapHelper.UpdateCellText(mapCell.CellX, mapCell.CellY, mapCell.DisplayText); + } + } + }; + } + } } private void RefreshCharacters() { if (characterCanvas == null || viewModel == null) return; - // Clear existing characters characterCanvas.Children.Clear(); - characterEllipses.Clear(); + characterElements.Clear(); - // Re-add all characters InitializeCharacters(viewModel.RedTeamCharacters, Colors.Red); InitializeCharacters(viewModel.BlueTeamCharacters, Colors.Blue); } @@ -117,6 +139,7 @@ namespace debug_interface.Views } } + private void InitializeCharacters(System.Collections.ObjectModel.ObservableCollection characters, Color color) where T : CharacterViewModel { if (characterCanvas == null) return; @@ -126,44 +149,72 @@ namespace debug_interface.Views var character = characters[i]; var id = color == Colors.Red ? $"red_{i}" : $"blue_{i}"; - var ellipse = new Ellipse + // 创建一个Grid作为容器,包含边框和文本/图标 + var grid = new Grid { - Width = 12, - Height = 12, - Fill = new SolidColorBrush(color), - Stroke = new SolidColorBrush(Colors.White), - StrokeThickness = 1, + Width = 15, + Height = 15, + }; + + // 创建带颜色边框的圆形 + var borderellipse = new Ellipse + { + Width = 15, + Height = 15, + Fill = new SolidColorBrush(Colors.White), // 白色背景 + Stroke = new SolidColorBrush(color), // 队伍颜色边框 + StrokeThickness = 2, Tag = character.Name, }; - // Set tooltip - ToolTip.SetTip(ellipse, character.Name); + grid.Children.Add(borderellipse); - // Set initial position - Canvas.SetLeft(ellipse, character.PosY * 15); - Canvas.SetTop(ellipse, character.PosX * 15); + // ===== 选项1: 显示数字编号 ===== + // 如果不需要数字编号,注释掉下面这段代码 + //var textBlock = new TextBlock + //{ + // Text = (i + 1).ToString(), // 使用编号(从1开始) + // HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + // VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + // FontSize = 8, + // Foreground = new SolidColorBrush(color), // 文本颜色与队伍颜色一致 + // FontWeight = FontWeight.Bold, + //}; + //grid.Children.Add(textBlock); - characterCanvas.Children.Add(ellipse); - characterEllipses[id] = ellipse; + // 设置提示信息 + ToolTip.SetTip(grid, character.Name); - // Set up property changed handlers + // 设置初始位置 + Canvas.SetLeft(grid, character.PosY * 15); + Canvas.SetTop(grid, character.PosX * 15); + + characterCanvas.Children.Add(grid); + + // 存储Grid到字典中 + characterElements[id] = grid; + + // 设置属性更改处理器 character.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(CharacterViewModel.PosX) || e.PropertyName == nameof(CharacterViewModel.PosY)) { - UpdateCharacterPosition(ellipse, character.PosX, character.PosY); + // 更新Grid的位置 + UpdateCharacterPosition(grid, character.PosX, character.PosY); } }; } } - private void UpdateCharacterPosition(Ellipse ellipse, int x, int y) + // 修改位置更新方法,接受任何UIElement + private void UpdateCharacterPosition(Control element, int x, int y) { - // Convert grid position to pixels - Canvas.SetLeft(ellipse, y * 15); - Canvas.SetTop(ellipse, x * 15); + // 转换网格位置为像素 + Canvas.SetLeft(element, y * 15); + Canvas.SetTop(element, x * 15); } + private void RedTeamCharacters_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { // When collection changes, refresh all characters for simplicity diff --git a/interface/AvaloniaUI_debug_interface/debug_interface/debug_interface.csproj b/interface/AvaloniaUI_debug_interface/debug_interface/debug_interface.csproj index ed018dc..557318c 100644 --- a/interface/AvaloniaUI_debug_interface/debug_interface/debug_interface.csproj +++ b/interface/AvaloniaUI_debug_interface/debug_interface/debug_interface.csproj @@ -6,6 +6,7 @@ true app.manifest true + debug_interface @@ -28,11 +29,6 @@ - - - - - diff --git a/logic/ClientTest/ClientTest.csproj b/logic/ClientTest/ClientTest.csproj new file mode 100644 index 0000000..ddb4a42 --- /dev/null +++ b/logic/ClientTest/ClientTest.csproj @@ -0,0 +1,20 @@ +锘 + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + diff --git a/logic/ClientTest/Program.cs b/logic/ClientTest/Program.cs new file mode 100644 index 0000000..c137a10 --- /dev/null +++ b/logic/ClientTest/Program.cs @@ -0,0 +1,44 @@ +锘縰sing Grpc.Core; +using Protobuf; + +namespace ClientTest +{ + public class Program + { + public static Task Main(string[] args) + { + Thread.Sleep(3000); + Channel channel = new("127.0.0.1:8888", ChannelCredentials.Insecure); + var client = new AvailableService.AvailableServiceClient(channel); + CharacterMsg playerInfo = new() + { + CharacterId = 0, + TeamId = 0, + CharacterType = CharacterType.TangSeng + }; + var call = client.AddCharacter(playerInfo); + MoveMsg moveMsg = new() + { + CharacterId = 0, + TeamId = 0, + TimeInMilliseconds = 100, + Angle = 0 + }; + int tot = 0; + /*while (call.ResponseStream.MoveNext().Result) + { + var currentGameInfo = call.ResponseStream.Current; + if (currentGameInfo.GameState == GameState.GameStart) break; + }*/ + while (true) + { + Thread.Sleep(50); + MoveRes boolRes = client.Move(moveMsg); + //if (boolRes.ActSuccess == false) break; + tot++; + if (tot % 10 == 0) moveMsg.Angle += 1; + } + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/logic/GameClass/GameObj/Character.cs b/logic/GameClass/GameObj/Character.cs index 2b0027b..7b1bb65 100644 --- a/logic/GameClass/GameObj/Character.cs +++ b/logic/GameClass/GameObj/Character.cs @@ -20,6 +20,7 @@ public class Character : Movable, ICharacter public InVariableRange AttackPower { get; } public InVariableRange AttackSize { get; } public InVariableRange Shield { get; } + public InVariableRange NiuShield { get; } public InVariableRange Shoes { get; }//绉婚熷姞鎴愶紙娉ㄦ剰鏄姞鎴愬硷紝瀹為檯绉婚熶负鍩虹绉婚+绉婚熷姞鎴愶級 public CharacterType CharacterType { get; } public bool trapped { get; set; } = false; @@ -30,6 +31,7 @@ public class Character : Movable, ICharacter public bool blind { get; set; } = false; public double HarmCut = 0.0;//浼ゅ鍑忓厤锛岃鍊艰寖鍥翠负0-1锛屼负姣斾緥鍑忎激銆 public double ATKFrequency = 1.0;//鏀诲嚮棰戠巼锛屽嵆姣忕鏀诲嚮娆℃暟銆 + public long LastAttackTime = long.MaxValue; public long TrapTime = long.MaxValue; public long CageTime = long.MaxValue; public long BurnedTime = long.MaxValue; @@ -42,10 +44,15 @@ public class Character : Movable, ICharacter public long QuickStepTime = long.MaxValue; public int CrazyManNum = 0; public int EconomyDepletion = 0; + public bool IsShield = false; public bool CanSeeAll = false;//瑙嗛噹涔嬬伒buff鐢熸晥鏃朵负true public long WideViewTime = long.MaxValue;//瑙嗛噹涔嬬伒璁℃椂鍣 public bool Purified = false;//鍑鍖栬嵂姘存晥鏋滐紝璇ユ晥鏋滀笅鍏嶇柅鎺у埗 public long PurifiedTime = long.MaxValue; + public long ShoesTime = long.MaxValue;//闉嬪瓙buff璁℃椂鍣 + public bool IsShoes = false; + public long BerserkTime = long.MaxValue;//鐙傛毚buff璁℃椂鍣 + public bool IsBerserk = false; public void StartSkillCD() { skillCD = Environment.TickCount64; @@ -244,6 +251,7 @@ public class Character : Movable, ICharacter ViewRange = Occupation.ViewRange; Shoes = new(0); Shield = new(0); + NiuShield = new(0); AttackSize = new(Occupation.BaseAttackSize); AttackPower = new(Occupation.AttackPower); MoneyPool = pool; @@ -280,24 +288,45 @@ public class Character : Movable, ICharacter } case EquipmentType.SMALL_SHIELD: { + if (IsShield) + { + return false; + } Shield.AddPositiveV(GameData.Shield1); SubMoney(EquipmentFactory.FindCost(equiptype)); + IsShield = true; return true; } case EquipmentType.MEDIUM_SHIELD: { + if (IsShield) + { + return false; + } Shield.AddPositiveV(GameData.Shield2); SubMoney(EquipmentFactory.FindCost(equiptype)); + IsShield = true; return true; } case EquipmentType.LARGE_SHIELD: { + if (IsShield) + { + return false; + } Shield.AddPositiveV(GameData.Shield3); SubMoney(EquipmentFactory.FindCost(equiptype)); + IsShield = true; return true; } case EquipmentType.SPEEDBOOTS: { + if (IsShoes) + { + return false; + } + IsShoes = true; + ShoesTime = Environment.TickCount64; Shoes.AddPositiveV(GameData.ShoesSpeed); SubMoney(EquipmentFactory.FindCost(equiptype)); return true; @@ -305,11 +334,18 @@ public class Character : Movable, ICharacter case EquipmentType.INVISIBILITY_POTION: { SetCharacterState(CharacterState1, CharacterState.INVISIBLE);//姝ゅ缂哄皯鏃堕棿闄愬埗 + visible = false; SubMoney(EquipmentFactory.FindCost(equiptype)); return true; } case EquipmentType.BERSERK_POTION: { + if (IsBerserk) + { + return false; + } + IsBerserk = true; + BerserkTime = Environment.TickCount64; SetCharacterState(CharacterState1, CharacterState.BERSERK);//姝ゅ缂哄皯鏃堕棿闄愬埗 AttackPower.AddPositiveV((long)(0.2 * AttackPower.GetValue())); ATKFrequency = GameData.CrazyATKFreq; diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index 1feda76..50f4d5a 100644 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -1,4 +1,5 @@ 锘縰sing GameClass.GameObj.Areas; +using GameClass.GameObj.Equipments; using GameClass.MapGenerator; using Preparation.Interface; using Preparation.Utility; @@ -21,6 +22,7 @@ namespace GameClass.GameObj.Map public PlaceType[,] ProtoGameMap => protoGameMap; private readonly MyTimer timer = new(); + public List Homes { get; } public IMyTimer Timer => timer; private readonly long currentHomeNum = 0; public bool TeamExists(long teamID) @@ -242,9 +244,16 @@ namespace GameClass.GameObj.Map case PlaceType.SPACE: Add(new Space(GameData.GetCellCenterPos(i, j))); break; + case PlaceType.HOME: + if (i < 25) + Add(new Home(GameData.GetCellCenterPos(i, j), currentHomeNum++, 1)); + else + Add(new Home(GameData.GetCellCenterPos(i, j), currentHomeNum++, 0)); + break; } } } + Homes = GameObjDict[GameObjType.HOME].Cast()?.ToNewList()!; } } } \ No newline at end of file diff --git a/logic/GameClass/GameObj/Occupations/BaiLongma.cs b/logic/GameClass/GameObj/Occupations/BaiLongma.cs index d37d744..af8893f 100644 --- a/logic/GameClass/GameObj/Occupations/BaiLongma.cs +++ b/logic/GameClass/GameObj/Occupations/BaiLongma.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class BaiLongma : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.BaiLongmaHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.BaiLongmacost; diff --git a/logic/GameClass/GameObj/Occupations/HongHaier.cs b/logic/GameClass/GameObj/Occupations/HongHaier.cs index a0e66d8..2845623 100644 --- a/logic/GameClass/GameObj/Occupations/HongHaier.cs +++ b/logic/GameClass/GameObj/Occupations/HongHaier.cs @@ -6,7 +6,7 @@ namespace GameClass.GameObj.Occupations { public class HongHaier : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.HongHaierHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.HongHaiercost; diff --git a/logic/GameClass/GameObj/Occupations/JiuLing.cs b/logic/GameClass/GameObj/Occupations/JiuLing.cs index 08ed056..ec20dff 100644 --- a/logic/GameClass/GameObj/Occupations/JiuLing.cs +++ b/logic/GameClass/GameObj/Occupations/JiuLing.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class JiuLing : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.JiuLingHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = 0; diff --git a/logic/GameClass/GameObj/Occupations/Monkid.cs b/logic/GameClass/GameObj/Occupations/Monkid.cs index 5c99543..0bb2481 100644 --- a/logic/GameClass/GameObj/Occupations/Monkid.cs +++ b/logic/GameClass/GameObj/Occupations/Monkid.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class Monkid : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.MonkidHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.Monkidcost; diff --git a/logic/GameClass/GameObj/Occupations/NiuMowang.cs b/logic/GameClass/GameObj/Occupations/NiuMowang.cs index 8ccc339..42e356e 100644 --- a/logic/GameClass/GameObj/Occupations/NiuMowang.cs +++ b/logic/GameClass/GameObj/Occupations/NiuMowang.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class NiuMowang : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.NiuMowangHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.NiuMowangcost; diff --git a/logic/GameClass/GameObj/Occupations/Pawn.cs b/logic/GameClass/GameObj/Occupations/Pawn.cs index e02b33a..00bb8eb 100644 --- a/logic/GameClass/GameObj/Occupations/Pawn.cs +++ b/logic/GameClass/GameObj/Occupations/Pawn.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class Pawn : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.PawnHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.Pawncost; diff --git a/logic/GameClass/GameObj/Occupations/ShaWujing.cs b/logic/GameClass/GameObj/Occupations/ShaWujing.cs index d0aab95..8e639c7 100644 --- a/logic/GameClass/GameObj/Occupations/ShaWujing.cs +++ b/logic/GameClass/GameObj/Occupations/ShaWujing.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class ShaWujing : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.ShaWujingHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.ShaWujingcost; diff --git a/logic/GameClass/GameObj/Occupations/SunWukong.cs b/logic/GameClass/GameObj/Occupations/SunWukong.cs index 89da9c7..b180748 100644 --- a/logic/GameClass/GameObj/Occupations/SunWukong.cs +++ b/logic/GameClass/GameObj/Occupations/SunWukong.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class SunWukong : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.SunWukongHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.SunWukongcost; diff --git a/logic/GameClass/GameObj/Occupations/TangSeng.cs b/logic/GameClass/GameObj/Occupations/TangSeng.cs index ef50ce4..42f8c69 100644 --- a/logic/GameClass/GameObj/Occupations/TangSeng.cs +++ b/logic/GameClass/GameObj/Occupations/TangSeng.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class TangSeng : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.TangSengHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = 0; diff --git a/logic/GameClass/GameObj/Occupations/TieShan.cs b/logic/GameClass/GameObj/Occupations/TieShan.cs index 48d2952..922db33 100644 --- a/logic/GameClass/GameObj/Occupations/TieShan.cs +++ b/logic/GameClass/GameObj/Occupations/TieShan.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class TieShan : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.TieShanHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.TieShancost; diff --git a/logic/GameClass/GameObj/Occupations/ZhiZhujing.cs b/logic/GameClass/GameObj/Occupations/ZhiZhujing.cs index 38a6b3c..a6301ee 100644 --- a/logic/GameClass/GameObj/Occupations/ZhiZhujing.cs +++ b/logic/GameClass/GameObj/Occupations/ZhiZhujing.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class ZhiZhujing : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.ZhiZhujingHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.ZhiZhujingcost; diff --git a/logic/GameClass/GameObj/Occupations/ZhuBajie.cs b/logic/GameClass/GameObj/Occupations/ZhuBajie.cs index 1f62dd8..8e109d9 100644 --- a/logic/GameClass/GameObj/Occupations/ZhuBajie.cs +++ b/logic/GameClass/GameObj/Occupations/ZhuBajie.cs @@ -5,7 +5,7 @@ namespace GameClass.GameObj.Occupations { public class ZhuBajie : IOccupation { - public int MoveSpeed { get; } = GameData.NumOfStepPerSecond; + public int MoveSpeed { get; } = GameData.BaseCharacterSpeed; public int MaxHp { get; } = GameData.ZhuBajieHP; public int ViewRange { get; } = GameData.Viewrange; public int Cost { get; } = GameData.ZhuBajiecost; diff --git a/logic/GameEngine/MoveEngine.cs b/logic/GameEngine/MoveEngine.cs index 44a81ae..6586bc1 100644 --- a/logic/GameEngine/MoveEngine.cs +++ b/logic/GameEngine/MoveEngine.cs @@ -132,7 +132,7 @@ namespace GameEngine return true; } - public void MoveObj(IMovable obj, int moveTime, double direction, long stateNum) + public void MoveObj(IMovable obj, int moveTime, double direction, long stateNum, long Shoes = 0) { GameEngineLogging.logger.ConsoleLogDebug( Logger.ObjInfo(obj) @@ -143,7 +143,6 @@ namespace GameEngine if (!obj.IsAvailableForMove) { EndMove(obj); return; } obj.IsMoving.SetROri(true); } - new Thread ( () => @@ -237,7 +236,7 @@ namespace GameEngine do { flag = false; - moveVecLength = (double)deltaLen + leftTime * obj.MoveSpeed / GameData.NumOfPosGridPerCell; + moveVecLength = (double)deltaLen + leftTime * (obj.MoveSpeed + Shoes) / GameData.NumOfPosGridPerCell; res = new XY(direction, moveVecLength); if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null) { diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index bb17de8..2076a5f 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -53,7 +53,7 @@ namespace Gaming characterToMove.ThreadNum.Release(); return; } - moveEngine.MoveObj(characterToMove, moveTimeInMilliseconds, moveDirection, characterToMove.StateNum); + moveEngine.MoveObj(characterToMove, moveTimeInMilliseconds, moveDirection, characterToMove.StateNum, characterToMove.Shoes); Thread.Sleep(moveTimeInMilliseconds); //characterToMove.ResetCharacterState(stateNum); } @@ -61,6 +61,34 @@ namespace Gaming { IsBackground = true }.Start(); return true; } + public bool KnockBackCharacter(Character characterToMove, double moveDirection) + { + long stateNum = characterToMove.SetCharacterState(characterToMove.CharacterState1, CharacterState.KNOCKED_BACK); + CharacterState tempState = characterToMove.CharacterState2; + if (stateNum == -1) + { + ActionManagerLogging.logger.ConsoleLogDebug("Character can not be knocked back"); + return false; + } + new Thread + ( + () => + { + characterToMove.ThreadNum.WaitOne(); + if (!characterToMove.StartThread(stateNum)) + { + characterToMove.ThreadNum.Release(); + return; + } + moveEngine.MoveObj(characterToMove, GameData.KnockedBackTime, moveDirection, characterToMove.StateNum, GameData.KnockedBackSpeed); + Thread.Sleep(GameData.KnockedBackTime); + characterToMove.SetCharacterState(characterToMove.CharacterState1, tempState); + //characterToMove.ResetCharacterState(stateNum); + } + ) + { IsBackground = true }.Start(); + return true; + } public static bool Stop(Character character) { lock (character.ActionLock) diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 8069f98..42b40b5 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -58,7 +58,11 @@ namespace Gaming { return false; } + long nowtime = Environment.TickCount64; + if (nowtime - character.LastAttackTime < 1 / (character.ATKFrequency * 1000)) + return false; characterManager.BeAttacked(gameobj, character); + character.LastAttackTime = nowtime; if (character.CharacterState2 == CharacterState.INVISIBLE || character.visible == false) { character.visible = true; @@ -80,7 +84,11 @@ namespace Gaming { return false; } + long nowtime = Environment.TickCount64; + if (nowtime - character.LastAttackTime < 1 / (character.ATKFrequency * 1000)) + return false; ARManager.BeAttacked(gameobj, character); + character.LastAttackTime = nowtime; if (character.CharacterState2 == CharacterState.INVISIBLE) character.SetCharacterState(character.CharacterState1, CharacterState.NULL_CHARACTER_STATE);//鐮撮殣 return true; @@ -99,7 +107,11 @@ namespace Gaming { return false; } + long nowtime = Environment.TickCount64; + if (nowtime - character.LastAttackTime < 1 / (character.ATKFrequency * 1000)) + return false; gameobj.BeAttacked(character); + character.LastAttackTime = nowtime; if (character.CharacterState2 == CharacterState.INVISIBLE) character.SetCharacterState(character.CharacterState1, CharacterState.NULL_CHARACTER_STATE);//鐮撮殣 return true; diff --git a/logic/Gaming/CharacterManager.cs b/logic/Gaming/CharacterManager.cs index f638d54..e42b3a2 100644 --- a/logic/Gaming/CharacterManager.cs +++ b/logic/Gaming/CharacterManager.cs @@ -44,14 +44,27 @@ namespace Gaming return; } long subHP = (long)(obj.AttackPower * (1 - character.HarmCut)); - if (character.Shield > 0) + /*if (character.Shield > 0) { character.Shield.SubPositiveV(subHP); } else { character.HP.SubPositiveV(subHP); + }*/ + character.NiuShield.SubPositiveV(subHP); + if (character.NiuShield > subHP) + { + return; } + subHP -= character.NiuShield; + character.Shield.SubPositiveV(subHP); + if (character.Shield > subHP) + { + return; + } + subHP -= character.Shield; + character.HP.SubPositiveV(subHP); if (character.HP == 0) { long score = 0; @@ -67,7 +80,6 @@ namespace Gaming Remove(character); } } - public void BeAttacked(Character character, long AP)//姝ら儴鍒嗛傜敤浜庝腑绔嬭祫婧愭敾鍑诲強鎶鑳芥敾鍑 { long subHP = (long)(AP * (1 - character.HarmCut)); @@ -276,6 +288,34 @@ namespace Gaming } } + public void CheckBerkserk(Character character) + { + long nowtime = Environment.TickCount64; + if (character.IsBerserk) + { + if (nowtime - character.BerserkTime >= GameData.CrazyTime) + { + character.AttackPower.SetRNow(character.Occupation.AttackPower); + character.Shoes.SubPositiveV(GameData.CrazySpeed); + character.ATKFrequency = GameData.ATKFreq; + character.BerserkTime = long.MaxValue; + } + } + } + public void CheckShoes(Character character) + { + long nowtime = Environment.TickCount64; + if (character.IsShoes) + { + if (nowtime - character.ShoesTime >= GameData.ShoesTime) + { + character.Shoes.SubPositiveV(GameData.ShoesSpeed); + character.ShoesTime = long.MaxValue; + character.IsShoes = false; + } + } + + } } } -} \ No newline at end of file +} diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index cb83f2d..8b83c86 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -28,7 +28,7 @@ namespace Gaming private readonly Map gameMap; public Map GameMap => gameMap; private readonly Random random = new(); - public long AddPlayer(PlayerInitInfo playerInitInfo) + public long AddCharacter(PlayerInitInfo playerInitInfo) { if (teamList[(int)playerInitInfo.teamID].CharacterNum >= GameData.CharacterTotalNumMax) { @@ -341,9 +341,9 @@ namespace Gaming gameMap = new(mapResource); characterManager = new(this, gameMap); ARManager = new(this, gameMap, characterManager); - skillCastManager = new(this, gameMap, characterManager, ARManager); actionManager = new(this, gameMap, characterManager); attackManager = new(this, gameMap, characterManager); + skillCastManager = new(this, gameMap, characterManager, ARManager, actionManager); teamList = []; gameMap.GameObjDict[GameObjType.HOME].Cast()?.ForEach( delegate (GameObj gameObj) @@ -380,7 +380,7 @@ namespace Gaming } return false; } - public bool Attack(long teamID, long characterID, double angle, long ATKteamID, long ATKcharacterID) + public bool Attack(long teamID, long characterID, long ATKteamID, long ATKcharacterID) { if (!gameMap.Timer.IsGaming) return false; diff --git a/logic/Gaming/SkillCastManager.cs b/logic/Gaming/SkillCastManager.cs index 497f981..d74ae14 100644 --- a/logic/Gaming/SkillCastManager.cs +++ b/logic/Gaming/SkillCastManager.cs @@ -22,12 +22,14 @@ namespace Gaming private readonly CharacterManager characterManager; private readonly MoveEngine moveEngine; private readonly A_ResourceManager ARManager; - public SkillCastManager(Game game, Map gameMap, CharacterManager characterManager, A_ResourceManager a_ResourceManager) + private readonly ActionManager actionManager; + public SkillCastManager(Game game, Map gameMap, CharacterManager characterManager, A_ResourceManager a_ResourceManager, ActionManager actionManager) { this.game = game; this.gameMap = gameMap; this.characterManager = characterManager; this.ARManager = a_ResourceManager; + this.actionManager = actionManager; moveEngine = new( gameMap: gameMap, OnCollision: (obj, collisionObj, moveVec) => @@ -202,7 +204,18 @@ namespace Gaming if (ObjBeingShot.Purified == true) continue; else + { ObjBeingShot.SetCharacterState(ObjBeingShot.CharacterState1, CharacterState.KNOCKED_BACK); + double angleToBeKnockedBack; + double tantheta = (ObjBeingShot.Position.y - character.Position.y) / (ObjBeingShot.Position.x - character.Position.x); + if ((ObjBeingShot.Position.x - character.Position.x) > 0) + angleToBeKnockedBack = Math.Atan(tantheta); + else if ((ObjBeingShot.Position.y - character.Position.y) > 0) + angleToBeKnockedBack = Math.PI - Math.Atan(tantheta); + else + angleToBeKnockedBack = -Math.PI - Math.Atan(tantheta); + actionManager.KnockBackCharacter(ObjBeingShot, angleToBeKnockedBack); + } } break; default: break; diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 949729d..3ef8aae 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -4,12 +4,15 @@ namespace Preparation.Utility { public static class GameData { - public const int NumOfStepPerSecond = 2500; // 姣忕琛岃蛋鍩虹姝ユ暟.鐢变簬绉婚焍uff鐨勫瓨鍦紝瑙掕壊鐨勫叿浣撶Щ鍔ㄩ熷害浼氬彂鐢熷彉鍖栵紝鐩稿簲浠g爜闇璋冩暣 + public const int NumOfStepPerSecond = 100; // 姣忕琛岃蛋姝ユ暟 + public const int BaseCharacterSpeed = 2500; // 瑙掕壊鍩虹绉诲姩閫熷害 public const int FrameDuration = 50; // 姣忓抚鏃堕暱 public const int CheckInterval = 10; // 妫鏌ラ棿闅 public const uint GameDurationInSecond = 60 * 10; // 娓告垙鏃堕暱 public const int LimitOfStopAndMove = 15; // 鍋滄鍜岀Щ鍔ㄧ殑鏈澶ч棿闅 public const int ProduceSpeedPerSecond = 200; // 姣忕鐢熶骇鍊 + public const int KnockedBackTime = 50; + public const int KnockedBackSpeed = 1500; // 鍑婚閫熷害(棰濆閫熷害锛岄渶鍔犱笂鍩虹绉婚燂級 public const int TolerancesLength = 3; public const int AdjustLength = 3; @@ -192,6 +195,7 @@ namespace Preparation.Utility public const int ShoesCost = 1500; public const int ShoesSpeed = 500; + public const int ShoesTime = 60000; public const int PurificationCost = 2000; public const int PurificationTime = 30000; @@ -203,6 +207,7 @@ namespace Preparation.Utility public const int CrazyTime = 30000; public const double CrazyPower = 1.2; public const double CrazyATKFreq = 1.25; + public const double ATKFreq = 1.0; public const int CrazySpeed = 300; public const int ScoreFarmPerSecond = 100; public const int MaxCharacterNum = 1; diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index 9cd8969..b32524c 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -75,26 +75,31 @@ namespace Server CharacterType = Transformation.CharacterTypeToProto(player.CharacterType), - CharacterActiveState = Transformation.CharacterStateToProto(player.CharacterActiveState), + CharacterActiveState = Transformation.CharacterStateToProto(player.CharacterState1), - // 寰呬慨鏀癸紝琚姩鐘舵佺敤CharacterStateType杩樻槸bool - BlindState = (player.blind) ? Protobuf.CharacterState.BLIND : Protobuf.CharacterState.NULL_CHARACTER_STATE, - BlindTime = (double)player.BlindTime, // 寰呬慨鏀癸紝鏃堕棿鏄惁搴旇鐢╠ouble + BlindState = (player.blind) ? Protobuf.CharacterState.Blind : Protobuf.CharacterState.NullCharacterState, + BlindTime = player.BlindTime, // 寰呬慨鏀癸紝Character.cs涓病鏈塳nockedback - KnockbackState = (player.knockedback) ? Protobuf.CharacterState.KNOCKED_BACK : Protobuf.CharacterState.NULL_CHARACTER_STATE, - KnockbackTime = (double)player.KnockedBackTime, - StunnedState = (player.stunned) ? Protobuf.CharacterState.STUNNED : Protobuf.CharacterState.NULL_CHARACTER_STATE, - StunnedTime = (double)player.StunnedTime, - InvisibleState = (player.visible) ? Protobuf.CharacterState.NULL_CHARACTER_STATE : Protobuf.CharacterState.INVISIBLE, + // KnockbackState = (player.knockedback) ? Protobuf.CharacterState.KnockedBack : Protobuf.CharacterState.NullCharacterState, + // KnockbackTime = player.KnockedBackTime, + StunnedState = (player.stunned) ? Protobuf.CharacterState.Stunned : Protobuf.CharacterState.NullCharacterState, + StunnedTime = player.StunnedTime, + InvisibleState = (player.visible) ? Protobuf.CharacterState.NullCharacterState : Protobuf.CharacterState.Invisible, // 寰呬慨鏀癸紝Character.cs涓病鏈塈nvisibleTime - InvisibleTime = (double)player.InvisibleTime, - HealingState = (player.healing) ? Protobuf.CharacterState.HEALING : Protobuf.CharacterState.NULL_CHARACTER_STATE, - HealingTime = (double)player.HealingTime, - BerserkState = (player.crazyman) ? Protobuf.CharacterState.BERSERK : Protobuf.CharacterState.NULL_CHARACTER_STATE, - BerserkTime = (double)CrazyManTime, - BurnedState = (player.burned) ? Protobuf.CharacterState.BURNED : Protobuf.CharacterState.NULL_CHARACTER_STATE, - BurnedTime = (double)BurnedTime, - DeceasedState = (player.deceased) ? Protobuf.CharacterState.DECEASED : Protobuf.CharacterState.NULL_CHARACTER_STATE, + // InvisibleTime = (double)player.InvisibleTime, + // 璨屼技涓嶉渶瑕佹不鐤楁椂闂 + // HealingState = (player.healing) ? Protobuf.CharacterState.Healing : Protobuf.CharacterState.NullCharacterState, + // HealingTime = (double)player.HealingTime, + // 寰呬慨鏀癸紝crazyman涓嶇煡閬撴槸buff杩樻槸鑽按 + // BerserkState = (player.CrazyManNum == 1) ? Protobuf.CharacterState.Berserk : Protobuf.CharacterState.NullCharacterState, + // BerserkTime = CrazyManTime, + BurnedState = (player.burned) ? Protobuf.CharacterState.Burned : Protobuf.CharacterState.NullCharacterState, + BurnedTime = player.BurnedTime, + HarmCut = player.HarmCut, + HarmCutTime = player.HarmCutTime, + DeceasedState = (player.CharacterState2 == Preparation.Utility.CharacterState.DECEASED) ? Protobuf.CharacterState.Deceased : Protobuf.CharacterState.NullCharacterState, + + CharacterPassiveState = Transformation.CharacterStateToProto(player.CharacterState2), X = player.Position.x, Y = player.Position.y, @@ -105,22 +110,36 @@ namespace Server CommonAttack = (int)player.AttackPower, // 寰呬慨鏀癸紝Character.cs涓病鏈塁ommonAttackCD - CommonAttackCD = (double)player.AttackCD, + CommonAttackCd = (int)(1 / player.ATKFrequency), CommonAttackRange = (int)player.AttackSize, - SkillAttackCD = (double)player.skillCD, + SkillAttackCd = player.skillCD, EconomyDepletion = player.EconomyDepletion, KillScore = (int)player.GetCost(), - HP = (int)player.HP, + Hp = (int)player.HP, - // 寰呬慨鏀癸紝Character.cs涓病鏈夊尯鍒哠hieldEquipment\ShoesEquipment绫诲瀷 - Shield = player.Shield, - Shoes = player.Shoes, + // 寰呬慨鏀癸紝Shield瑕佸垎涓ょ被 + ShieldEquipment = (int)player.Shield, // 鍔犳垚鍊硷紝鍙寘鍚姢鐩捐澶 + ShoesEquipment = (int)player.Shoes, // 鍔犳垚鍊 + ShoesEquipmentTime = player.QuickStepTime, // 鍖呭惈鎵鏈夐熷害鍔犳垚鐨勬椂闂 + // 寰呬慨鏀癸紝Transformation缂轰笢瑗 + // PurificationEquipment = (player.Purified) ? Protobuf.EquipmentType.PurificationPotion : Protobuf.PurificationEquipmentType.NullEquipmentType, + PurificationEquipmentTime = player.PurifiedTime, + // 寰呬慨鏀癸紝Character.cs娌℃湁闅愯韩鏃堕棿锛屾病鏈夌媯鏆磋嵂姘 + // InvisibilityEquipment = player.Invisibility, + // InvisibilityEquipmentTime = player.InsvisibilityTime, + // Berserk = player.CrazyManNum, // 鏁板硷紝1~3琛ㄧず绛夌骇锛0琛ㄧず娌℃湁 + // BerserkTime = player.CrazyManTime, - // - //AttackBuff = + // 寰呬慨鏀癸紝Transformation缂轰笢瑗 + // AttackBuff = (player.CrazyManNum == 1) ? Protobuf.CharacterBuffType.AttackBuff1 : (player.CrazyManNum == 2) ? Protobuf.CharacterBuffType.AttackBuff2 : (player.CrazyManNum == 3) ? Protobuf.CharacterBuffType.AttackBuff3 : Protobuf.CharacterBuffType.NullAttackBuff, + AttackBuffTime = player.CrazyManTime, + // 寰呬慨鏀 + SpeedBuffTime = player.QuickStepTime, + // VisionBuff = (player.CanSeeAll) ? Protobuf.CharacterBuffType.VisionBuff : Protobuf.CharacterBuffType.NullCharacterBuffType, + VisionBuffTime = player.WideViewTime, } }; return msg; diff --git a/logic/Server/PlaybackServer.cs b/logic/Server/PlaybackServer.cs index 918bd48..ee2b1dd 100644 --- a/logic/Server/PlaybackServer.cs +++ b/logic/Server/PlaybackServer.cs @@ -20,6 +20,7 @@ namespace Server private readonly object spectatorJoinLock = new(); protected object spectatorLock = new(); protected bool isSpectatorJoin = false; + int a_b_c_d = 1; protected bool IsSpectatorJoin { get diff --git a/logic/Server/Properties/launchSettings.json b/logic/Server/Properties/launchSettings.json new file mode 100644 index 0000000..1be99b0 --- /dev/null +++ b/logic/Server/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Server": { + "commandName": "Project", + "commandLineArgs": "--port 8888" + } + } +} \ No newline at end of file diff --git a/logic/Server/RpcServices.cs b/logic/Server/RpcServices.cs index f061116..88bb6c1 100644 --- a/logic/Server/RpcServices.cs +++ b/logic/Server/RpcServices.cs @@ -136,7 +136,7 @@ namespace Server lock (addPlayerLock) { Game.PlayerInitInfo playerInitInfo = new(request.TeamId, request.CharacterId, Transformation.CharacterTypeFromProto(request.CharacterType), request.SideFlag); - long newPlayerID = game.AddPlayer(playerInitInfo); + long newPlayerID = game.AddCharacter(playerInitInfo); if (newPlayerID == GameObj.invalidID) { GameServerLogging.logger.ConsoleLogDebug("FAIL AddPlayer"); @@ -385,7 +385,7 @@ namespace Server // var gameID = communicationToGameID[request.TeamId][request.PlayerId]; boolRes.ActSuccess = game.Attack( request.TeamId, request.CharacterId, - request.AttackRange, request.AttackedCharacterId, request.AttackedTeam); + request.AttackedCharacterId, request.AttackedTeam); GameServerLogging.logger.ConsoleLogDebug("END Attack"); return Task.FromResult(boolRes); } diff --git a/logic/Server/Server.csproj b/logic/Server/Server.csproj index d73aecf..1432b24 100644 --- a/logic/Server/Server.csproj +++ b/logic/Server/Server.csproj @@ -1,7 +1,7 @@ 锘 - Library + Exe net8.0 enable enable diff --git a/logic/logic.sln b/logic/logic.sln index 58f37f6..73d329e 100644 --- a/logic/logic.sln +++ b/logic/logic.sln @@ -17,6 +17,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Playback", "PlayBack\Playba EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Proto", "..\dependency\proto\Proto.csproj", "{E8E71849-1F1C-422E-B5F2-38483D23F6BD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientTest", "ClientTest\ClientTest.csproj", "{240D57BD-671E-4A84-9A26-82150229B98E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "瑙e喅鏂规椤", "瑙e喅鏂规椤", "{11DF0425-CEB7-43A8-8626-B42A61BDF972}" + ProjectSection(SolutionItems) = preProject + ..\.editorconfig = ..\.editorconfig + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -51,6 +58,10 @@ Global {E8E71849-1F1C-422E-B5F2-38483D23F6BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {E8E71849-1F1C-422E-B5F2-38483D23F6BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {E8E71849-1F1C-422E-B5F2-38483D23F6BD}.Release|Any CPU.Build.0 = Release|Any CPU + {240D57BD-671E-4A84-9A26-82150229B98E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {240D57BD-671E-4A84-9A26-82150229B98E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {240D57BD-671E-4A84-9A26-82150229B98E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {240D57BD-671E-4A84-9A26-82150229B98E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE