diff --git a/logic/GameClass/GameObj/Character/Skill.cs b/logic/GameClass/GameObj/Character/Skill.cs index 94a182e..df0c1dd 100644 --- a/logic/GameClass/GameObj/Character/Skill.cs +++ b/logic/GameClass/GameObj/Character/Skill.cs @@ -96,7 +96,7 @@ namespace GameClass.GameObj case CanBeginToCharge: return ActiveSkillType.CanBeginToCharge; case Punish: - return ActiveSkillType.Publish; + return ActiveSkillType.Punish; default: return ActiveSkillType.Null; } diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index a851a3f..353e50d 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -299,7 +299,7 @@ namespace Gaming if (!player.Commandable()) return false; - XY res = new XY // 子弹紧贴人物生成。 + XY res = player.Position + new XY // 子弹紧贴人物生成。 ( (int)((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Cos(angle)), (int)((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Sin(angle)) diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 92e65cd..ff95c6d 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -49,9 +49,9 @@ namespace Gaming { if (character.IsGhost() != player.IsGhost() && XY.Distance(player.Position + new XY(player.FacingDirection, player.Radius), character.Position) <= character.Radius) { - AttackManager.BeStunned(character, GameData.TimeOfGhostFainting); - player.AddScore(GameData.StudentScoreTrickerBeStunned); - AttackManager.BeStunned(player, GameData.TimeOfStudentFainting); + AttackManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenCharge); + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenCharge)); + AttackManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge); break; } } @@ -115,15 +115,31 @@ namespace Gaming { player.BulletOfPlayer = player.OriBulletOfPlayer; }); } - public bool Publish(Character player) + public bool Punish(Character player) { - return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.Publish), player, () => + return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.Punish), player, () => { - player.BulletOfPlayer = BulletType.FlyingKnife; - Debugger.Output(player, "uses flyingknife!"); + gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); + try + { + foreach (Character character in gameMap.GameObjDict[GameObjType.Character]) + { + if (player.IsGhost() && XY.Distance(player.Position, character.Position) <= player.ViewRange) + { + AttackManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.TimeFactorOfGhostFainting); + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.TimeFactorOfGhostFainting)); + break; + } + } + } + finally + { + gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); + } + Debugger.Output(player, "uses punishing!"); }, () => - { player.BulletOfPlayer = player.OriBulletOfPlayer; }); + { }); } public bool SuperFast(Character player) diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs index 5eb88f7..e8278c6 100644 --- a/logic/Preparation/Interface/IOccupation.cs +++ b/logic/Preparation/Interface/IOccupation.cs @@ -76,7 +76,7 @@ namespace Preparation.Interface public BulletType InitBullet => BulletType.Null; - public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Publish }); + public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Punish }); public List ListOfIPassiveSkill => new(new PassiveSkillType[] { }); public const int fixSpeed = 0; diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index c2ccce3..4c39f73 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -91,7 +91,7 @@ namespace Preparation.Utility SuperFast = 4, UseKnife = 5, CanBeginToCharge = 6, - Publish = 7, + Punish = 7, } public enum PassiveSkillType { diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index e504fdf..cbd6298 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -117,7 +117,10 @@ namespace Preparation.Utility { return 0; } - public const int StudentScoreTrickerBeStunned = 25; + public static int StudentScoreTrickerBeStunned(int time) + { + return time; + } public const int StudentScoreRescue = 100; public static int StudentScoreTreat(int degree) { @@ -159,9 +162,14 @@ namespace Preparation.Utility /// /// BeginToCharge /// - public const int TimeOfGhostFainting = 7220;//=AP of Ram - public const int TimeOfStudentFainting = 2090; + public const int TimeOfGhostFaintingWhenCharge = 7220; + public const int TimeOfStudentFaintingWhenCharge = 2090; + /// + /// Punish + /// + public const int TimeOfGhostFaintingWhenPunish = 3070; + public const int TimeFactorOfGhostFainting = 1000; #endregion #region 道具相关 public const int MinPropTypeNum = 1; diff --git a/logic/Server/ArgumentOption.cs b/logic/Server/ArgumentOption.cs index b931917..7b4f96e 100644 --- a/logic/Server/ArgumentOption.cs +++ b/logic/Server/ArgumentOption.cs @@ -12,16 +12,19 @@ namespace Server public class ArgumentOptions { + [Option("ip", Required = true, HelpText = "Server listening port")] + public string ServerIP { get; set; } = "0.0.0.0"; + [Option('p', "port", Required = true, HelpText = "Server listening port")] - public ushort ServerPort { get; set; } = 10086; + public ushort ServerPort { get; set; } = 8888; [Option('n', "playerNum", Required = false, HelpText = "The number of players, 1 by defualt")] public ushort playerNum { get; set; } = 1; [Option('t', "teamCount", Required = false, HelpText = "The number of teams, 1 by defualt")] - public ushort TeamCount { get; set; } = 1; + public ushort TeamCount { get; set; } = 2; - [Option('c', "playerCount", Required = false, HelpText = "The number of players per team, 1 by default")] + [Option('c', "playerCount", Required = false, HelpText = "The number of players per team, 4 by default")] public ushort PlayerCountPerTeam { get; set; } = 4; [Option('g', "gameTimeInSecond", Required = false, HelpText = "The time of the game in second, 10 minutes by default")] diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs index 4fad72f..888519a 100644 --- a/logic/Server/GameServer.cs +++ b/logic/Server/GameServer.cs @@ -20,8 +20,12 @@ namespace Server protected readonly ArgumentOptions options; private HttpSender? httpSender; private object gameLock = new(); +<<<<<<< HEAD private int playerNum = 0; private int PlayerNum => playerNum; // 注意修改 +======= + public int PlayerNum => options.playerNum; // 注意修改 +>>>>>>> 9497283ae5076d61510347911d4d9ac16841cef3 private MessageToClient currentGameInfo = new(); private MessageOfObj currentMapMsg = new(); private object newsLock = new(); @@ -203,7 +207,7 @@ namespace Server } private bool ValidPlayerID(long playerID) { - if (0 <= playerID && playerID < options.PlayerCountPerTeam + 1) + if ((0 <= playerID && playerID < options.PlayerCountPerTeam) || playerID == 4) return true; return false; } @@ -277,7 +281,7 @@ namespace Server var onConnection = new BoolRes(); lock (gameLock) { - if (0 <= request.PlayerId && request.PlayerId < playerNum) // 注意修改 + if (0 <= request.PlayerId && request.PlayerId < PlayerNum) // 注意修改 { onConnection.ActSuccess = true; Console.WriteLine(onConnection.ActSuccess); @@ -332,7 +336,7 @@ namespace Server lock (semaDict) { semaDict.Add(request.PlayerId, temp); - start = semaDict.Count == playerNum; + start = semaDict.Count == PlayerNum; } if (start) StartGame(); } @@ -428,7 +432,8 @@ namespace Server #endif BoolRes boolRes = new(); var gameID = communicationToGameID[request.PlayerId]; - //boolRes.ActSuccess = game.UseProp(gameID, CopyInfo.ToPropType(request.PropType)); + game.UseProp(gameID, CopyInfo.ToPropType(request.PropType)); + boolRes.ActSuccess = true; return Task.FromResult(boolRes); } public override Task ThrowProp(PropMsg request, ServerCallContext context) @@ -438,7 +443,8 @@ namespace Server #endif BoolRes boolRes = new(); var gameID = communicationToGameID[request.PlayerId]; - //boolRes.ActSuccess = game.ThrowProp(gameID, CopyInfo.ToPropType(request.PropType)); + game.ThrowProp(gameID, CopyInfo.ToPropType(request.PropType)); + boolRes.ActSuccess = true; return Task.FromResult(boolRes); } public override Task UseSkill(SkillMsg request, ServerCallContext context) @@ -448,7 +454,7 @@ namespace Server #endif BoolRes boolRes = new(); var gameID = communicationToGameID[request.PlayerId]; - //boolRes.ActSuccess = game.UseActiveSkill(gameID, CopyInfo.ToPropType(request.PropType)); + boolRes.ActSuccess = game.UseActiveSkill(gameID, request.SkillId); return Task.FromResult(boolRes); } @@ -469,7 +475,8 @@ namespace Server #endif BoolRes boolRes = new(); var gameID = communicationToGameID[request.PlayerId]; - //boolRes.ActSuccess = game.Rescue(gameID); + var toGameID = communicationToGameID[request.ToPlayerId]; + boolRes.ActSuccess = game.Rescue(gameID, toGameID); return Task.FromResult(boolRes); } public override Task StartTreatMate(TreatAndRescueMsg request, ServerCallContext context) @@ -479,7 +486,8 @@ namespace Server #endif BoolRes boolRes = new(); var gameID = communicationToGameID[request.PlayerId]; - //boolRes.ActSuccess = game.Treat(gameID); + var toGameID = communicationToGameID[request.ToPlayerId]; + boolRes.ActSuccess = game.Treat(gameID, toGameID); return Task.FromResult(boolRes); } public override Task StartLearning(IDMsg request, ServerCallContext context) @@ -629,7 +637,7 @@ namespace Server if (options.Url != DefaultArgumentOptions.Url && options.Token != DefaultArgumentOptions.Token) { - //this.httpSender = new HttpSender(options.Url, options.Token, "PUT"); + this.httpSender = new HttpSender(options.Url, options.Token, "PUT"); } } } diff --git a/logic/Server/Program.cs b/logic/Server/Program.cs index 792147c..1c2aa5e 100644 --- a/logic/Server/Program.cs +++ b/logic/Server/Program.cs @@ -23,10 +23,10 @@ namespace Server if (options == null) { Console.WriteLine("Argument parsing failed!"); - // return 1; + return 1; } - // Console.WriteLine("Server begins to run: " + options.ServerPort.ToString()); + Console.WriteLine("Server begins to run: " + options.ServerPort.ToString()); try { @@ -34,7 +34,7 @@ namespace Server Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { AvailableService.BindService(gameServer) }, - Ports = { new ServerPort("0.0.0.0", 8888, ServerCredentials.Insecure) } + Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) } }; server.Start(); diff --git a/logic/Server/Properties/launchSettings.json b/logic/Server/Properties/launchSettings.json index bc93c16..f1ad4af 100644 --- a/logic/Server/Properties/launchSettings.json +++ b/logic/Server/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Server": { "commandName": "Project", - "commandLineArgs": "-p 8888 -t 2 -c 4" + "commandLineArgs": "--ip 0.0.0.0\r\n-p 8888\r\n-f playback\r\n-g 600\r\n-b true\r\n-c 4\r\n-t 2\r\n-n 1" } } } \ No newline at end of file diff --git a/logic/cmd/gameServer.cmd b/logic/cmd/gameServer.cmd index 2ba3de6..4116f85 100644 --- a/logic/cmd/gameServer.cmd +++ b/logic/cmd/gameServer.cmd @@ -1,6 +1,10 @@ @echo off +<<<<<<< HEAD start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --port 8888 --teamCount 2 --playerNum 2 --gameTimeInSecond 600 --fileName test +======= +start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --port 8888 --teamCount 2 --playerCount 4 --playerNum 1 --gameTimeInSecond 600 --fileName test +>>>>>>> 9497283ae5076d61510347911d4d9ac16841cef3 ping -n 2 127.0.0.1 > NUL diff --git a/logic/规则Logic.md b/logic/规则Logic.md index ff1f104..167175a 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -353,3 +353,173 @@ | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| | Key5 | 能开启5教的门 |不得分| 能开启3教的门 |不得分| | Key6 | 能开启6教的门 |不得分| 能开启3教的门 |不得分| + +## 游戏数据 + +### 基本常数 + ~~~csharp + public const int numOfStepPerSecond = 20; // 每秒行走的步数 + public const int frameDuration = 50; // 每帧时长 + public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长 + + public const long gameDuration = 600000; // 游戏时长600000ms = 10min + + public const int MinSpeed = 1; // 最小速度 + public const int MaxSpeed = int.MaxValue; // 最大速度 + #endregion + #region 地图相关 + public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 + public const int lengthOfMap = 50000; // 地图长度 + public const int rows = 50; // 行数 + public const int cols = 50; // 列数 + + public const int numOfBirthPoint = 5; + public const int numOfGenerator = 9; + public const int numOfChest = 8; + + public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 + { + XY ret = new(x * numOfPosGridPerCell + numOfPosGridPerCell / 2, y * numOfPosGridPerCell + numOfPosGridPerCell / 2); + return ret; + } + public static int PosGridToCellX(XY pos) // 求坐标所在的格子的x坐标 + { + return pos.x / numOfPosGridPerCell; + } + public static int PosGridToCellY(XY pos) // 求坐标所在的格子的y坐标 + { + return pos.y / numOfPosGridPerCell; + } + public static XY PosGridToCellXY(XY pos) // 求坐标所在的格子的y坐标 + { + return new XY(pos.x / numOfPosGridPerCell, pos.y / numOfPosGridPerCell); + } + public static bool IsInTheSameCell(XY pos1, XY pos2) + { + return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2); + } + public static bool ApproachToInteract(XY pos1, XY pos2) + { + return Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) <= 1 && Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2)) <= 1; + } + public static bool ApproachToInteractInACross(XY pos1, XY pos2) + { + return (Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) + Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2))) <= 1; + } + ~~~ + +### 角色相关 + ~~~csharp + public const int numOfStudent = 4; + public const int characterRadius = numOfPosGridPerCell / 2 / 5 * 4; // 人物半径 + + public const int basicTreatSpeed = 100; + public const int basicFixSpeed = 100; + public const int basicSpeedOfOpeningOrLocking = 3280; + public const int basicStudentSpeedOfClimbingThroughWindows = 611; + public const int basicGhostSpeedOfClimbingThroughWindows = 1270; + public const int basicSpeedOfOpenChest = 1000; + + public const int basicHp = 3000000; // 初始血量 + public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间 + public const int BeginGamingAddiction = 10003; + public const int MidGamingAddiction = 30000; + public const int basicTreatmentDegree = 1500000; + public const int basicTimeOfRescue = 1000; + + public const int basicMoveSpeed = 1270; // 基本移动速度,单位:s-1 + public const int characterMaxSpeed = 12000; // 最大速度 + public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1 + + public const double basicConcealment = 1.0; + public const int basicAlertnessRadius = 30700; + public const int basicViewRange = 5 * numOfPosGridPerCell; + public const int maxNumOfPropInPropInventory = 3; +~~~ + +### 得分相关 + ~~~csharp + public static int TrickerScoreAttackStudent(int damage) + { + return damage * 100 / basicApOfGhost; + } + public const int TrickerScoreStudentBeAddicted = 50; + public const int TrickerScoreStudentBeStunned = 25; + public const int TrickerScoreStudentDie = 1000; + + public static int StudentScoreFix(int degreeOfFix) + { + return degreeOfFix; + } + public const int StudentScoreFixed = 25; + public static int StudentScorePinDown(int timeOfPiningDown) + { + return 0; + } + public const int StudentScoreTrickerBeStunned = 25; + public const int StudentScoreRescue = 100; + public static int StudentScoreTreat(int degree) + { + return degree; + } + public const int StudentScoreEscape = 1000; + public const int ScorePropRemainHp = 20; + public const int ScorePropUseShield = 20; + public const int ScorePropUseSpear = 20; + public const int ScorePropAddAp = 10; + public const int ScorePropAddHp = 50; + + ~~~ +### 攻击与子弹相关 + ~~~csharp + public const int basicApOfGhost = 1500000; // 捣蛋鬼攻击力 + public const int MinAP = 0; // 最小攻击力 + public const int MaxAP = int.MaxValue; // 最大攻击力 + + public const int basicCD = 3000; // 初始子弹冷却 + public const int basicCastTime = 500;//基本前摇时间 + public const int basicBackswing = 818;//基本后摇时间 + public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 + public const int basicStunnedTimeOfStudent = 4130; + + public const int bulletRadius = 200; // 默认子弹半径 + public const int basicBulletNum = 3; // 基本初始子弹量 + public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围 + public const double basicAttackShortRange = 2700; // 基本近程攻击范围 + public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围 +~~~ + +### 技能相关 + ~~~csharp + public const int maxNumOfSkill = 3; + public const int commonSkillCD = 30000; // 普通技能标准冷却时间 + public const int commonSkillTime = 10000; // 普通技能标准持续时间 + ~~~ +### 道具相关 + ~~~csharp + public const int MinPropTypeNum = 1; + public const int MaxPropTypeNum = 10; + public const int PropRadius = numOfPosGridPerCell / 2; + public const int PropMoveSpeed = 3000; + public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell; + public const long PropProduceTime = 10000; + public const int PropDuration = 10000; + + public const int ApPropAdd = basicApOfGhost * 12 / 10; + public const int ApSpearAdd = basicApOfGhost * 6 / 10; + public const int RemainHpWhenAddLife = 100; + + public const int numOfKeyEachArea = 2; + public const int numOfPropTypeNotKey = 4; + public const int numOfTeachingBuilding = 3; + ~~~ +### 物体相关 + ~~~csharp + public const int degreeOfFixedGenerator = 10300000; + public const int degreeOfLockingOrOpeningTheDoor = 10000; + public const int degreeOfOpeningChest = 10000; + public const int degreeOfOpenedDoorway = 18000; + public const int maxNumOfPropInChest = 2; + public const int numOfGeneratorRequiredForRepair = 7; + public const int numOfGeneratorRequiredForEmergencyExit = 3; + ~~~ \ No newline at end of file