From e106f82ed3e0123c02c96d18d5042ac383b64ada Mon Sep 17 00:00:00 2001 From: OctaAcid Date: Sun, 9 Apr 2023 01:17:56 +0800 Subject: [PATCH 01/37] chore: Using PasswordBox for password now --- installer/Installer/Common.cs | 56 +++++++++++++++++++++++ installer/Installer/MainWindow.xaml | 2 +- installer/Installer/Model.cs | 71 ++++++++++++++++------------- installer/Installer/ViewModel.cs | 20 ++++---- 4 files changed, 108 insertions(+), 41 deletions(-) diff --git a/installer/Installer/Common.cs b/installer/Installer/Common.cs index fc3a554..0f3697d 100644 --- a/installer/Installer/Common.cs +++ b/installer/Installer/Common.cs @@ -3,6 +3,8 @@ using System; using System.Windows.Input; using System.Globalization; using System.Windows.Data; +using System.Windows.Controls; +using System.Windows; namespace starter.viewmodel.common { @@ -98,4 +100,58 @@ namespace starter.viewmodel.common } } + /// + /// Password 附加属性,来自https://blog.csdn.net/qq_43562262/article/details/121786337 + /// + public class PasswordHelper + { + public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PasswordHelper), + new PropertyMetadata(new PropertyChangedCallback(OnPropertyChanged))); + + public static string GetPassword(DependencyObject d) + { + return (string)d.GetValue(PasswordProperty); + } + public static void SetPassword(DependencyObject d, string value) + { + d.SetValue(PasswordProperty, value); + } + + public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached("Attach", typeof(string), typeof(PasswordHelper), + new PropertyMetadata(new PropertyChangedCallback(OnAttachChanged))); + + public static string GetAttach(DependencyObject d) + { + return (string)d.GetValue(AttachProperty); + } + public static void SetAttach(DependencyObject d, string value) + { + d.SetValue(AttachProperty, value); + } + + static bool _isUpdating = false; + private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + PasswordBox pb = d as PasswordBox; + pb.PasswordChanged -= Pb_PasswordChanged; + if (!_isUpdating) + (d as PasswordBox).Password = e.NewValue.ToString(); + pb.PasswordChanged += Pb_PasswordChanged; + } + + private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + PasswordBox pb = d as PasswordBox; + pb.PasswordChanged += Pb_PasswordChanged; + } + + private static void Pb_PasswordChanged(object sender, RoutedEventArgs e) + { + PasswordBox pb = sender as PasswordBox; + _isUpdating = true; + SetPassword(pb, pb.Password); + _isUpdating = false; + } + } + } diff --git a/installer/Installer/MainWindow.xaml b/installer/Installer/MainWindow.xaml index 993efaa..48625cc 100644 --- a/installer/Installer/MainWindow.xaml +++ b/installer/Installer/MainWindow.xaml @@ -71,7 +71,7 @@ - + diff --git a/installer/Installer/Model.cs b/installer/Installer/Model.cs index 371bd97..a6ee504 100644 --- a/installer/Installer/Model.cs +++ b/installer/Installer/Model.cs @@ -124,7 +124,7 @@ namespace starter.viewmodel.settings } } - public async Task Login() + public async Task Login() { return await web.LoginToEEsast(client, Username, Password); } @@ -1057,43 +1057,50 @@ namespace WebConnect { public enum language { cpp, py }; public static string logintoken = ""; - async public Task LoginToEEsast(HttpClient client, string useremail, string password) + async public Task LoginToEEsast(HttpClient client, string useremail, string password) { string token = ""; - using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new - { - email = useremail, - password = password, - }))) + try { - switch (response.StatusCode) + using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new { - case System.Net.HttpStatusCode.OK: - Console.WriteLine("Success login"); - token = (System.Text.Json.JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), typeof(LoginResponse), new JsonSerializerOptions() - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - }) as LoginResponse) - ?.Token ?? - throw new Exception("no token!"); - logintoken = token; - SaveToken(); - var info = JsonConvert.DeserializeObject>(await response.Content.ReadAsStringAsync()); - Downloader.UserInfo._id = info["_id"]; - Downloader.UserInfo.email = info["email"]; - break; + email = useremail, + password = password, + }))) + { + switch (response.StatusCode) + { + case System.Net.HttpStatusCode.OK: + Console.WriteLine("Success login"); + token = (System.Text.Json.JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), typeof(LoginResponse), new JsonSerializerOptions() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }) as LoginResponse) + ?.Token ?? + throw new Exception("no token!"); + logintoken = token; + SaveToken(); + var info = JsonConvert.DeserializeObject>(await response.Content.ReadAsStringAsync()); + Downloader.UserInfo._id = info["_id"]; + Downloader.UserInfo.email = info["email"]; + break; - default: - int code = ((int)response.StatusCode); - Console.WriteLine(code); - if (code == 401) - { - //Console.WriteLine("邮箱或密码错误!"); - return false; - } - break; + default: + int code = ((int)response.StatusCode); + Console.WriteLine(code); + if (code == 401) + { + //Console.WriteLine("邮箱或密码错误!"); + return -1; + } + break; + } + return 0; } - return true; + } + catch + { + return -2; } } /// diff --git a/installer/Installer/ViewModel.cs b/installer/Installer/ViewModel.cs index b776fa8..8461acd 100644 --- a/installer/Installer/ViewModel.cs +++ b/installer/Installer/ViewModel.cs @@ -481,15 +481,19 @@ namespace starter.viewmodel.settings { clickLoginCommand = new BaseCommand(new Action(async o => { - if (!(await obj.Login())) + switch(await obj.Login()) { - obj.LoginFailed = true; - } - else - { - obj.LoginFailed = false; - Status = SettingsModel.Status.web; - this.RaisePropertyChanged("CoverVis"); + case -1: + obj.LoginFailed = true; + break; + case 0: + obj.LoginFailed = false; + Status = SettingsModel.Status.web; + this.RaisePropertyChanged("CoverVis"); + break; + case -2: + MessageBox.Show("无法连接服务器,请检查网络情况", "网络错误", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); + break; } this.RaisePropertyChanged("LoginFailVis"); })); From 3cdd82ae60d1f24880328664f1fa3136c700f32c Mon Sep 17 00:00:00 2001 From: OctaAcid Date: Sun, 9 Apr 2023 01:20:09 +0800 Subject: [PATCH 02/37] chore: reformat last commit --- installer/Installer/ViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/Installer/ViewModel.cs b/installer/Installer/ViewModel.cs index 8461acd..2920207 100644 --- a/installer/Installer/ViewModel.cs +++ b/installer/Installer/ViewModel.cs @@ -481,7 +481,7 @@ namespace starter.viewmodel.settings { clickLoginCommand = new BaseCommand(new Action(async o => { - switch(await obj.Login()) + switch (await obj.Login()) { case -1: obj.LoginFailed = true; From f88e147db5ff7285f8ce14fe7896dd6a0ff888fe Mon Sep 17 00:00:00 2001 From: Shawqeem <1004837646@qq.com> Date: Sun, 9 Apr 2023 01:59:30 +0800 Subject: [PATCH 03/37] fix: :bug: fix the bug due to 1024 * 1024 fix the bug due to 1024 * 1024 --- logic/Client/CommandLineArgs.cs | 2 +- logic/Client/MainWindow.xaml.cs | 167 ++++++---- logic/Client/PlaybackClient.cs | 334 ++++++++++--------- logic/Client/Properties/launchSettings.json | 2 +- logic/Client/StatusBarOfCircumstance.xaml.cs | 11 +- logic/Client/StatusBarOfHunter.xaml.cs | 3 +- logic/Client/StatusBarOfSurvivor.xaml.cs | 3 +- logic/Server/GameServer.cs | 3 +- logic/cmd/gameServer.cmd | 6 +- logic/cmd/playback.cmd | 2 +- playback/Playback/MessageReader.cs | 21 +- playback/Playback/MessageWriter.cs | 2 +- 12 files changed, 303 insertions(+), 253 deletions(-) diff --git a/logic/Client/CommandLineArgs.cs b/logic/Client/CommandLineArgs.cs index fe08801..c79edd2 100644 --- a/logic/Client/CommandLineArgs.cs +++ b/logic/Client/CommandLineArgs.cs @@ -36,7 +36,7 @@ namespace Client public string PlaybackFile { get; set; } = DefaultArgumentOptions.FileName; [Option("playbackSpeed", Required = false, HelpText = "The speed of the playback, between 0.25 and 4.0")] - public double PlaybackSpeed { get; set; } = 1.0; + public double PlaybackSpeed { get; set; } = 2.0; } } diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 073eabc..0768a1f 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -413,19 +413,6 @@ namespace Client { human = obj.StudentMessage; } - if (obj.StudentMessage.PlayerId < GameData.numOfStudent) - { - IStudentType occupation = (IStudentType)OccupationFactory.FindIOccupation(Transformation.ToStudentType(obj.StudentMessage.StudentType)); - totalLife[obj.StudentMessage.PlayerId] = occupation.MaxHp; - totalDeath[obj.StudentMessage.PlayerId] = occupation.MaxGamingAddiction; - int i = 0; - foreach (var skill in occupation.ListOfIActiveSkill) - { - var iActiveSkill = SkillFactory.FindIActiveSkill(skill); - coolTime[i, obj.StudentMessage.PlayerId] = iActiveSkill.SkillCD; - ++i; - } - } listOfHuman.Add(obj.StudentMessage); break; case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: @@ -433,14 +420,6 @@ namespace Client { butcher = obj.TrickerMessage; } - IGhostType occupation1 = (IGhostType)OccupationFactory.FindIOccupation(Transformation.ToTrickerType(obj.TrickerMessage.TrickerType)); - int j = 0; - foreach (var skill in occupation1.ListOfIActiveSkill) - { - var iActiveSkill = SkillFactory.FindIActiveSkill(skill); - coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; - ++j; - } listOfButcher.Add(obj.TrickerMessage); break; case MessageOfObj.MessageOfObjOneofCase.PropMessage: @@ -519,6 +498,7 @@ namespace Client listOfAll.Add(content.AllMessage); break; case GameState.GameEnd: + MessageBox.Show("Game Over!"); foreach (var obj in content.ObjMessage) { switch (obj.MessageOfObjCase) @@ -667,53 +647,81 @@ namespace Client private void Refresh(object? sender, EventArgs e) //log未更新 { - // Bonus(); - if (WindowState == WindowState.Maximized) - MaxButton.Content = "❐"; - else - MaxButton.Content = "🗖"; - if (StatusBarsOfSurvivor != null) + lock (drawPicLock) // 加锁是必要的,画图操作和接收信息操作不能同时进行 { - for (int i = 0; i < GameData.numOfStudent; i++) + // Bonus(); + if (WindowState == WindowState.Maximized) + MaxButton.Content = "❐"; + else + MaxButton.Content = "🗖"; + foreach (var obj in listOfHuman) { - StatusBarsOfSurvivor[i].SetFontSize(12 * UpperLayerOfMap.ActualHeight / 650); - StatusBarsOfSurvivor[i].NewData(totalLife, totalDeath, coolTime); + if (obj.PlayerId < GameData.numOfStudent) + { + IStudentType occupation = (IStudentType)OccupationFactory.FindIOccupation(Transformation.ToStudentType(obj.StudentType)); + totalLife[obj.PlayerId] = occupation.MaxHp; + totalDeath[obj.PlayerId] = occupation.MaxGamingAddiction; + int i = 0; + foreach (var skill in occupation.ListOfIActiveSkill) + { + var iActiveSkill = SkillFactory.FindIActiveSkill(skill); + coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD; + ++i; + } + } } - } - if (StatusBarsOfHunter != null) - { - StatusBarsOfHunter.SetFontSize(12 * UpperLayerOfMap.ActualHeight / 650); - StatusBarsOfHunter.NewData(totalLife, totalDeath, coolTime); - } - if (StatusBarsOfCircumstance != null) - StatusBarsOfCircumstance.SetFontSize(12 * UpperLayerOfMap.ActualHeight / 650); - // 完成窗口信息更新 - if (!isClientStocked) - { - unit = Math.Sqrt(UpperLayerOfMap.ActualHeight * UpperLayerOfMap.ActualWidth) / 50; - unitHeight = UpperLayerOfMap.ActualHeight / 50; - unitWidth = UpperLayerOfMap.ActualWidth / 50; - try + foreach (var obj in listOfButcher) { - // if (log != null) - //{ - // string temp = ""; - // for (int i = 0; i < dataDict[GameObjType.Character].Count; i++) - // { - // temp += Convert.ToString(dataDict[GameObjType.Character][i].MessageOfCharacter.TeamID) + "\n"; - // } - // log.Content = temp; - // } - UpperLayerOfMap.Children.Clear(); - // if ((communicator == null || !communicator.Client.IsConnected) && !isPlaybackMode) - //{ - // UnderLayerOfMap.Children.Clear(); - // throw new Exception("Client is unconnected."); - // } - // else - //{ - lock (drawPicLock) // 加锁是必要的,画图操作和接收信息操作不能同时进行 + IGhostType occupation1 = (IGhostType)OccupationFactory.FindIOccupation(Transformation.ToTrickerType(obj.TrickerType)); + int j = 0; + foreach (var skill in occupation1.ListOfIActiveSkill) { + var iActiveSkill = SkillFactory.FindIActiveSkill(skill); + coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; + ++j; + } + } + if (StatusBarsOfSurvivor != null) + { + for (int i = 0; i < GameData.numOfStudent; i++) + { + StatusBarsOfSurvivor[i].SetFontSize(12 * UpperLayerOfMap.ActualHeight / 650); + StatusBarsOfSurvivor[i].NewData(totalLife, totalDeath, coolTime); + } + } + if (StatusBarsOfHunter != null) + { + StatusBarsOfHunter.SetFontSize(12 * UpperLayerOfMap.ActualHeight / 650); + StatusBarsOfHunter.NewData(totalLife, totalDeath, coolTime); + } + if (StatusBarsOfCircumstance != null) + StatusBarsOfCircumstance.SetFontSize(12 * UpperLayerOfMap.ActualHeight / 650); + // 完成窗口信息更新 + if (!isClientStocked) + { + unit = Math.Sqrt(UpperLayerOfMap.ActualHeight * UpperLayerOfMap.ActualWidth) / 50; + unitHeight = UpperLayerOfMap.ActualHeight / 50; + unitWidth = UpperLayerOfMap.ActualWidth / 50; + try + { + // if (log != null) + //{ + // string temp = ""; + // for (int i = 0; i < dataDict[GameObjType.Character].Count; i++) + // { + // temp += Convert.ToString(dataDict[GameObjType.Character][i].MessageOfCharacter.TeamID) + "\n"; + // } + // log.Content = temp; + // } + UpperLayerOfMap.Children.Clear(); + // if ((communicator == null || !communicator.Client.IsConnected) && !isPlaybackMode) + //{ + // UnderLayerOfMap.Children.Clear(); + // throw new Exception("Client is unconnected."); + // } + // else + //{ + foreach (var data in listOfAll) { StatusBarsOfCircumstance.SetValue(data, gateOpened, isEmergencyDrawed, isEmergencyOpened, playerID); @@ -978,17 +986,18 @@ namespace Client } //} ZoomMap(); + + } + catch (Exception exc) + { + ErrorDisplayer error = new("Error: " + exc.ToString()); + error.Show(); + isClientStocked = true; + PorC.Content = "▶"; } } - catch (Exception exc) - { - ErrorDisplayer error = new("Error: " + exc.ToString()); - error.Show(); - isClientStocked = true; - PorC.Content = "▶"; - } + counter++; } - counter++; } // 键盘控制,未完善 @@ -1210,10 +1219,18 @@ namespace Client isClientStocked = true; PorC.Content = "▶"; } - else + else if (!isPlaybackMode) { - isClientStocked = false; - PorC.Content = "⏸"; + try + { + isClientStocked = false; + PorC.Content = "⏸"; + } + catch (Exception ex) + { + ErrorDisplayer error = new("发生错误。以下是系统报告:\n" + ex.ToString()); + error.Show(); + } } } // 未复现 @@ -1341,6 +1358,7 @@ namespace Client private List listOfGate; private List listOfHiddenGate; private object drawPicLock = new object(); + private object recvLock = new object(); private MessageOfStudent? human = null; private MessageOfTricker? butcher = null; private bool humanOrButcher;//true for human @@ -1407,6 +1425,7 @@ namespace Client bool isSpectatorMode = false; bool isEmergencyOpened = false; bool isEmergencyDrawed = false; + bool isDataFixed = false; const double radiusTimes = 1.0 * Preparation.Utility.GameData.characterRadius / Preparation.Utility.GameData.numOfPosGridPerCell; private int[] totalLife = new int[4] { 100, 100, 100, 100 }, totalDeath = new int[4] { 100, 100, 100, 100 }; private int[,] coolTime = new int[3, 5] { { 100, 100, 100, 100, 100 }, { 100, 100, 100, 100, 100 }, { 100, 100, 100, 100, 100 } }; diff --git a/logic/Client/PlaybackClient.cs b/logic/Client/PlaybackClient.cs index af923ca..5290b37 100644 --- a/logic/Client/PlaybackClient.cs +++ b/logic/Client/PlaybackClient.cs @@ -7,6 +7,7 @@ using Protobuf; using Playback; using System.Threading; using Timothy.FrameRateTask; +using System.Windows; namespace Client { @@ -79,183 +80,194 @@ namespace Client } } }; - new Thread(() => { - new FrameRateTaskExecutor - ( - () => !endFile, - () => - { - var content = Reader.ReadOne(); - if (content == null) - endFile = true; - else + int i = 0; + try + { + new FrameRateTaskExecutor + ( + () => !endFile, + () => { - lock (dataLock) + var content = Reader.ReadOne(); + i++; + if (content == null) + { + MessageBox.Show($"End! {i}"); + endFile = true; + } + else { - listOfHuman.Clear(); - listOfButcher.Clear(); - listOfProp.Clear(); - listOfBombedBullet.Clear(); - listOfBullet.Clear(); - listOfAll.Clear(); - listOfChest.Clear(); - listOfClassroom.Clear(); - listOfDoor.Clear(); - listOfHiddenGate.Clear(); - listOfGate.Clear(); - switch (content.GameState) + lock (dataLock) { - case GameState.GameStart: - foreach (var obj in content.ObjMessage) - { - switch (obj.MessageOfObjCase) + listOfHuman.Clear(); + listOfButcher.Clear(); + listOfProp.Clear(); + listOfBombedBullet.Clear(); + listOfBullet.Clear(); + listOfAll.Clear(); + listOfChest.Clear(); + listOfClassroom.Clear(); + listOfDoor.Clear(); + listOfHiddenGate.Clear(); + listOfGate.Clear(); + switch (content.GameState) + { + case GameState.GameStart: + foreach (var obj in content.ObjMessage) { - case MessageOfObj.MessageOfObjOneofCase.StudentMessage: - //if (humanOrButcher && obj.StudentMessage.PlayerId == playerID) - //{ - // human = obj.StudentMessage; - //} - listOfHuman.Add(obj.StudentMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: - //if (!humanOrButcher && obj.TrickerMessage.PlayerId == playerID) - //{ - // butcher = obj.TrickerMessage; - //} - listOfButcher.Add(obj.TrickerMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.PropMessage: - listOfProp.Add(obj.PropMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.BombedBulletMessage: - listOfBombedBullet.Add(obj.BombedBulletMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.BulletMessage: - listOfBullet.Add(obj.BulletMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.ChestMessage: - listOfChest.Add(obj.ChestMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: - listOfClassroom.Add(obj.ClassroomMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.DoorMessage: - listOfDoor.Add(obj.DoorMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.GateMessage: - listOfGate.Add(obj.GateMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: - listOfHiddenGate.Add(obj.HiddenGateMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.MapMessage: - break; + switch (obj.MessageOfObjCase) + { + case MessageOfObj.MessageOfObjOneofCase.StudentMessage: + //if (humanOrButcher && obj.StudentMessage.PlayerId == playerID) + //{ + // human = obj.StudentMessage; + //} + listOfHuman.Add(obj.StudentMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: + //if (!humanOrButcher && obj.TrickerMessage.PlayerId == playerID) + //{ + // butcher = obj.TrickerMessage; + //} + listOfButcher.Add(obj.TrickerMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.PropMessage: + listOfProp.Add(obj.PropMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.BombedBulletMessage: + listOfBombedBullet.Add(obj.BombedBulletMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.BulletMessage: + listOfBullet.Add(obj.BulletMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.ChestMessage: + listOfChest.Add(obj.ChestMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: + listOfClassroom.Add(obj.ClassroomMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.DoorMessage: + listOfDoor.Add(obj.DoorMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.GateMessage: + listOfGate.Add(obj.GateMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: + listOfHiddenGate.Add(obj.HiddenGateMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.MapMessage: + break; + } } - } - listOfAll.Add(content.AllMessage); - break; - case GameState.GameRunning: - foreach (var obj in content.ObjMessage) - { - switch (obj.MessageOfObjCase) + listOfAll.Add(content.AllMessage); + break; + case GameState.GameRunning: + foreach (var obj in content.ObjMessage) { - case MessageOfObj.MessageOfObjOneofCase.StudentMessage: - //if (humanOrButcher && obj.StudentMessage.PlayerId == playerID) - //{ - // human = obj.StudentMessage; - //} - listOfHuman.Add(obj.StudentMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: - //if (!humanOrButcher && obj.TrickerMessage.PlayerId == playerID) - //{ - // butcher = obj.TrickerMessage; - //} - listOfButcher.Add(obj.TrickerMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.PropMessage: - listOfProp.Add(obj.PropMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.BombedBulletMessage: - listOfBombedBullet.Add(obj.BombedBulletMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.BulletMessage: - listOfBullet.Add(obj.BulletMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.ChestMessage: - listOfChest.Add(obj.ChestMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: - listOfClassroom.Add(obj.ClassroomMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.DoorMessage: - listOfDoor.Add(obj.DoorMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: - listOfHiddenGate.Add(obj.HiddenGateMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.GateMessage: - listOfGate.Add(obj.GateMessage); - break; + switch (obj.MessageOfObjCase) + { + case MessageOfObj.MessageOfObjOneofCase.StudentMessage: + //if (humanOrButcher && obj.StudentMessage.PlayerId == playerID) + //{ + // human = obj.StudentMessage; + //} + listOfHuman.Add(obj.StudentMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: + //if (!humanOrButcher && obj.TrickerMessage.PlayerId == playerID) + //{ + // butcher = obj.TrickerMessage; + //} + listOfButcher.Add(obj.TrickerMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.PropMessage: + listOfProp.Add(obj.PropMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.BombedBulletMessage: + listOfBombedBullet.Add(obj.BombedBulletMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.BulletMessage: + listOfBullet.Add(obj.BulletMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.ChestMessage: + listOfChest.Add(obj.ChestMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: + listOfClassroom.Add(obj.ClassroomMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.DoorMessage: + listOfDoor.Add(obj.DoorMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: + listOfHiddenGate.Add(obj.HiddenGateMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.GateMessage: + listOfGate.Add(obj.GateMessage); + break; + } } - } - listOfAll.Add(content.AllMessage); - break; + listOfAll.Add(content.AllMessage); + break; - case GameState.GameEnd: - foreach (var obj in content.ObjMessage) - { - switch (obj.MessageOfObjCase) + case GameState.GameEnd: + MessageBox.Show("Game Over!"); + foreach (var obj in content.ObjMessage) { - case MessageOfObj.MessageOfObjOneofCase.StudentMessage: - listOfHuman.Add(obj.StudentMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: - listOfButcher.Add(obj.TrickerMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.PropMessage: - listOfProp.Add(obj.PropMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.BombedBulletMessage: - listOfBombedBullet.Add(obj.BombedBulletMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.BulletMessage: - listOfBullet.Add(obj.BulletMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.ChestMessage: - listOfChest.Add(obj.ChestMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: - listOfClassroom.Add(obj.ClassroomMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.DoorMessage: - listOfDoor.Add(obj.DoorMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: - listOfHiddenGate.Add(obj.HiddenGateMessage); - break; - case MessageOfObj.MessageOfObjOneofCase.GateMessage: - listOfGate.Add(obj.GateMessage); - break; + switch (obj.MessageOfObjCase) + { + case MessageOfObj.MessageOfObjOneofCase.StudentMessage: + listOfHuman.Add(obj.StudentMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: + listOfButcher.Add(obj.TrickerMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.PropMessage: + listOfProp.Add(obj.PropMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.BombedBulletMessage: + listOfBombedBullet.Add(obj.BombedBulletMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.BulletMessage: + listOfBullet.Add(obj.BulletMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.ChestMessage: + listOfChest.Add(obj.ChestMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: + listOfClassroom.Add(obj.ClassroomMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.DoorMessage: + listOfDoor.Add(obj.DoorMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: + listOfHiddenGate.Add(obj.HiddenGateMessage); + break; + case MessageOfObj.MessageOfObjOneofCase.GateMessage: + listOfGate.Add(obj.GateMessage); + break; + } } - } - listOfAll.Add(content.AllMessage); - break; + listOfAll.Add(content.AllMessage); + break; + } } } - } - }, - frame, - () => + }, + frame, + () => + { + Sema.Release(); + return 1; + } + ) + { AllowTimeExceed = true }.Start(); + } + catch (Exception ex) { - Sema.Release(); - //MessageBox.Show("Game Over!"); - return 1; + MessageBox.Show(ex.Message); } - ) - { AllowTimeExceed = true }.Start(); }) { IsBackground = true }.Start(); return map; diff --git a/logic/Client/Properties/launchSettings.json b/logic/Client/Properties/launchSettings.json index 5e50d0d..fb94197 100644 --- a/logic/Client/Properties/launchSettings.json +++ b/logic/Client/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Client": { "commandName": "Project", - "commandLineArgs": "--ip 127.0.0.1 --cl --port 8888 --characterID 4 --type 2 --occupation 2" + "commandLineArgs": "--cl --playbackFile D:\\2_autumn\\thuai6\\THUAI6\\logic\\cmd\\test.thuaipb --playbackSpeed 2 " } } } \ No newline at end of file diff --git a/logic/Client/StatusBarOfCircumstance.xaml.cs b/logic/Client/StatusBarOfCircumstance.xaml.cs index 9e51039..5d4616c 100644 --- a/logic/Client/StatusBarOfCircumstance.xaml.cs +++ b/logic/Client/StatusBarOfCircumstance.xaml.cs @@ -31,10 +31,13 @@ namespace Client } public void SetFontSize(double fontsize) { - status.FontSize = 13 * fontsize / 12; - time.FontSize = 14 * fontsize / 12; - name.FontSize = 14 * fontsize / 12; - scoresOfStudents.FontSize = scoresOfTrickers.FontSize = fontsize; + if (fontsize != 0) + { + status.FontSize = 13 * fontsize / 12; + time.FontSize = 14 * fontsize / 12; + name.FontSize = 14 * fontsize / 12; + scoresOfStudents.FontSize = scoresOfTrickers.FontSize = fontsize; + } } public void SetValue(MessageOfAll obj, bool gateOpened, bool hiddenGateRefreshed, bool hiddenGateOpened, long playerId) diff --git a/logic/Client/StatusBarOfHunter.xaml.cs b/logic/Client/StatusBarOfHunter.xaml.cs index b9b3fb9..b4c4add 100644 --- a/logic/Client/StatusBarOfHunter.xaml.cs +++ b/logic/Client/StatusBarOfHunter.xaml.cs @@ -32,7 +32,8 @@ namespace Client } public void SetFontSize(double fontsize) { - serial.FontSize = scores.FontSize = state.FontSize = status.FontSize = activeSkill0.FontSize = activeSkill1.FontSize = activeSkill2.FontSize = prop0.FontSize = prop1.FontSize = prop2.FontSize = fontsize; + if (fontsize != 0) + serial.FontSize = scores.FontSize = state.FontSize = status.FontSize = activeSkill0.FontSize = activeSkill1.FontSize = activeSkill2.FontSize = prop0.FontSize = prop1.FontSize = prop2.FontSize = fontsize; } private void SetStaticValue(MessageOfTricker obj) diff --git a/logic/Client/StatusBarOfSurvivor.xaml.cs b/logic/Client/StatusBarOfSurvivor.xaml.cs index 5304479..fa7ca3e 100644 --- a/logic/Client/StatusBarOfSurvivor.xaml.cs +++ b/logic/Client/StatusBarOfSurvivor.xaml.cs @@ -31,7 +31,8 @@ namespace Client } public void SetFontSize(double fontsize) { - serial.FontSize = scores.FontSize = status.FontSize = activeSkill0.FontSize = activeSkill1.FontSize = activeSkill2.FontSize = prop0.FontSize = prop1.FontSize = prop2.FontSize = fontsize; + if (fontsize != 0) + serial.FontSize = scores.FontSize = status.FontSize = activeSkill0.FontSize = activeSkill1.FontSize = activeSkill2.FontSize = prop0.FontSize = prop1.FontSize = prop2.FontSize = fontsize; } private void SetStaticValue(MessageOfStudent obj) { diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs index 5ecc5f7..2a80249 100644 --- a/logic/Server/GameServer.cs +++ b/logic/Server/GameServer.cs @@ -130,7 +130,7 @@ namespace Server case GameState.GameRunning: case GameState.GameEnd: case GameState.GameStart: - currentGameInfo.ObjMessage.Add(currentMapMsg); + if (gameState == GameState.GameStart) currentGameInfo.ObjMessage.Add(currentMapMsg); foreach (GameObj gameObj in gameObjList) { MessageOfObj? msg = CopyInfo.Auto(gameObj); @@ -153,7 +153,6 @@ namespace Server break; } } - foreach (var kvp in semaDict) { kvp.Value.Item1.Release(); diff --git a/logic/cmd/gameServer.cmd b/logic/cmd/gameServer.cmd index d4d54f2..f91b10b 100644 --- a/logic/cmd/gameServer.cmd +++ b/logic/cmd/gameServer.cmd @@ -1,6 +1,6 @@ @echo off -start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 600 --fileName test +start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 60 --fileName test ping -n 2 127.0.0.1 > NUL @@ -12,4 +12,6 @@ start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --ch start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 2 --type 1 --occupation 3 -start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 3 --type 1 --occupation 3 \ No newline at end of file +start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 3 --type 1 --occupation 3 + +::start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --ip 0.0.0.0 --port 8888 --characterID 2030 diff --git a/logic/cmd/playback.cmd b/logic/cmd/playback.cmd index 8bb70ea..32156c7 100644 --- a/logic/cmd/playback.cmd +++ b/logic/cmd/playback.cmd @@ -1,5 +1,5 @@ @echo off -start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --playbackFile .\test.thuaipb --playbackSpeed 3 +start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --playbackFile .\test.thuaipb --playbackSpeed 1 ping -n 2 127.0.0.1 > NUL \ No newline at end of file diff --git a/playback/Playback/MessageReader.cs b/playback/Playback/MessageReader.cs index e9c24b2..71f6616 100644 --- a/playback/Playback/MessageReader.cs +++ b/playback/Playback/MessageReader.cs @@ -27,7 +27,7 @@ namespace Playback public readonly uint teamCount; public readonly uint playerCount; - const int bufferMaxSize = 1024 * 1024; // 1M + const int bufferMaxSize = 10 * 1024 * 1024; // 10M public MessageReader(string fileName) { @@ -83,7 +83,8 @@ namespace Playback public MessageToClient? ReadOne() { beginRead: - if (Finished) return null; + if (Finished) + return null; var pos = cos.Position; try { @@ -94,9 +95,21 @@ namespace Playback catch (InvalidProtocolBufferException) { var leftByte = buffer.Length - pos; // 上次读取剩余的字节 - for (int i = 0; i < leftByte; ++i) + if (buffer.Length < bufferMaxSize / 2) { - buffer[i] = buffer[pos + i]; + var newBuffer = new byte[bufferMaxSize]; + for (int i = 0; i < leftByte; i++) + { + newBuffer[i] = buffer[pos + i]; + } + buffer = newBuffer; + } + else + { + for (int i = 0; i < leftByte; ++i) + { + buffer[i] = buffer[pos + i]; + } } var bufferSize = gzs.Read(buffer, (int)leftByte, (int)(buffer.Length - leftByte)) + leftByte; if (bufferSize == leftByte) diff --git a/playback/Playback/MessageWriter.cs b/playback/Playback/MessageWriter.cs index a23d701..abda3c2 100644 --- a/playback/Playback/MessageWriter.cs +++ b/playback/Playback/MessageWriter.cs @@ -12,7 +12,7 @@ namespace Playback private CodedOutputStream cos; private MemoryStream ms; private GZipStream gzs; - private const int memoryCapacity = 1024 * 1024; // 1M + private const int memoryCapacity = 10 * 1024 * 1024; // 10M private static void ClearMemoryStream(MemoryStream msToClear) { From 1a1cd8e957f7a5d684b147bc587f40864f93832b Mon Sep 17 00:00:00 2001 From: Shawqeem <1004837646@qq.com> Date: Sun, 9 Apr 2023 02:17:02 +0800 Subject: [PATCH 04/37] style: :art: change the name of spectator change the name of spectator --- logic/Client/MainWindow.xaml.cs | 1 - logic/Client/StatusBarOfCircumstance.xaml.cs | 9 +++++++-- logic/cmd/gameServer.cmd | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 0768a1f..e870848 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -1358,7 +1358,6 @@ namespace Client private List listOfGate; private List listOfHiddenGate; private object drawPicLock = new object(); - private object recvLock = new object(); private MessageOfStudent? human = null; private MessageOfTricker? butcher = null; private bool humanOrButcher;//true for human diff --git a/logic/Client/StatusBarOfCircumstance.xaml.cs b/logic/Client/StatusBarOfCircumstance.xaml.cs index 5d4616c..47d95b0 100644 --- a/logic/Client/StatusBarOfCircumstance.xaml.cs +++ b/logic/Client/StatusBarOfCircumstance.xaml.cs @@ -12,6 +12,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using Protobuf; +using Preparation.Utility; namespace Client { @@ -56,14 +57,18 @@ namespace Client { time.Text += Convert.ToString(sec); } - if (playerId == 4) + if (playerId == GameData.numOfStudent) { name.Text = "🚀 Tricker's"; } - else + else if(playerId< GameData.numOfStudent) { name.Text = "🚀 Student" + Convert.ToString(playerId) + "'s"; } + else + { + name.Text = "🚀 Spectator's"; + } if (obj.SubjectFinished < Preparation.Utility.GameData.numOfGeneratorRequiredForRepair) { status.Text = "📱: " + Convert.ToString(obj.SubjectFinished) + "\n🚪: "; diff --git a/logic/cmd/gameServer.cmd b/logic/cmd/gameServer.cmd index f91b10b..6c4c56b 100644 --- a/logic/cmd/gameServer.cmd +++ b/logic/cmd/gameServer.cmd @@ -14,4 +14,4 @@ start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --ch start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 3 --type 1 --occupation 3 -::start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --ip 0.0.0.0 --port 8888 --characterID 2030 +start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 2030 \ No newline at end of file From c670fda87e2c29dca62cac7299b84fdfe411e69a Mon Sep 17 00:00:00 2001 From: Shawqeem <1004837646@qq.com> Date: Sun, 9 Apr 2023 02:37:57 +0800 Subject: [PATCH 05/37] feat: :sparkles: (clgg) help server add the map message when a spectator joins a started game (clgg) help server add the map message when a spectator joins a started game --- logic/Client/MainWindow.xaml.cs | 3 +++ logic/Client/Properties/launchSettings.json | 2 +- logic/Client/StatusBarOfCircumstance.xaml.cs | 2 +- logic/Gaming/Game.cs | 7 +++--- logic/Server/GameServer.cs | 6 ++++- logic/Server/RpcServices.cs | 23 ++++++++++++++++---- 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index e870848..c115e6e 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -493,6 +493,9 @@ namespace Client case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: listOfHiddenGate.Add(obj.HiddenGateMessage); break; + case MessageOfObj.MessageOfObjOneofCase.MapMessage: + GetMap(obj.MapMessage); + break; } } listOfAll.Add(content.AllMessage); diff --git a/logic/Client/Properties/launchSettings.json b/logic/Client/Properties/launchSettings.json index fb94197..a671030 100644 --- a/logic/Client/Properties/launchSettings.json +++ b/logic/Client/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Client": { "commandName": "Project", - "commandLineArgs": "--cl --playbackFile D:\\2_autumn\\thuai6\\THUAI6\\logic\\cmd\\test.thuaipb --playbackSpeed 2 " + "commandLineArgs": "--cl --port 8888 --characterID 2031" } } } \ No newline at end of file diff --git a/logic/Client/StatusBarOfCircumstance.xaml.cs b/logic/Client/StatusBarOfCircumstance.xaml.cs index 47d95b0..1e3b863 100644 --- a/logic/Client/StatusBarOfCircumstance.xaml.cs +++ b/logic/Client/StatusBarOfCircumstance.xaml.cs @@ -61,7 +61,7 @@ namespace Client { name.Text = "🚀 Tricker's"; } - else if(playerId< GameData.numOfStudent) + else if (playerId < GameData.numOfStudent) { name.Text = "🚀 Student" + Convert.ToString(playerId) + "'s"; } diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index edbdb3c..65d0d6d 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -215,15 +215,16 @@ namespace Gaming } return false; } - public void Attack(long playerID, double angle) + public bool Attack(long playerID, double angle) { if (!gameMap.Timer.IsGaming) - return; + return false; Character? player = gameMap.FindPlayerToAction(playerID); if (player != null) { - _ = attackManager.Attack(player, angle); + return attackManager.Attack(player, angle); } + return false; } public void UseProp(long playerID, PropType propType = PropType.Null) { diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs index 2a80249..c0a1abf 100644 --- a/logic/Server/GameServer.cs +++ b/logic/Server/GameServer.cs @@ -130,7 +130,11 @@ namespace Server case GameState.GameRunning: case GameState.GameEnd: case GameState.GameStart: - if (gameState == GameState.GameStart) currentGameInfo.ObjMessage.Add(currentMapMsg); + if (gameState == GameState.GameStart || IsSpectatorJoin) + { + currentGameInfo.ObjMessage.Add(currentMapMsg); + IsSpectatorJoin = false; + } foreach (GameObj gameObj in gameObjList) { MessageOfObj? msg = CopyInfo.Auto(gameObj); diff --git a/logic/Server/RpcServices.cs b/logic/Server/RpcServices.cs index d775697..fccb653 100644 --- a/logic/Server/RpcServices.cs +++ b/logic/Server/RpcServices.cs @@ -16,6 +16,22 @@ namespace Server { public partial class GameServer : AvailableService.AvailableServiceBase { + protected object spectatorLock = new object(); + protected bool isSpectatorJoin = false; + protected bool IsSpectatorJoin + { + get + { + lock (spectatorLock) + return isSpectatorJoin; + } + + set + { + lock (spectatorLock) + isSpectatorJoin = value; + } + } public override Task TryConnection(IDMsg request, ServerCallContext context) { #if DEBUG @@ -53,6 +69,7 @@ namespace Server { semaDict.Add(request.PlayerId, temp); } + IsSpectatorJoin = true; } do { @@ -147,8 +164,7 @@ namespace Server return Task.FromResult(boolRes); } var gameID = communicationToGameID[request.PlayerId]; - game.Attack(gameID, request.Angle); - boolRes.ActSuccess = true; + boolRes.ActSuccess = game.Attack(gameID, request.Angle); return Task.FromResult(boolRes); } @@ -170,8 +186,7 @@ namespace Server return Task.FromResult(moveRes); } var gameID = communicationToGameID[request.PlayerId]; - game.MovePlayer(gameID, (int)request.TimeInMilliseconds, request.Angle); - moveRes.ActSuccess = true; + moveRes.ActSuccess = game.MovePlayer(gameID, (int)request.TimeInMilliseconds, request.Angle); if (!game.GameMap.Timer.IsGaming) moveRes.ActSuccess = false; return Task.FromResult(moveRes); } From e91906053b3b742fc0f5931b2af50069ba24e2a4 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sun, 9 Apr 2023 03:40:33 +0800 Subject: [PATCH 06/37] =?UTF-8?q?build:=20:construction:=20edit=20?= =?UTF-8?q?=E8=A7=84=E5=88=99Logic.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAPI/cpp/API/include/API.h | 2 +- .../GameClass/GameObj/Bullet/Bullet.Ghost.cs | 2 - logic/Preparation/Utility/GameData.cs | 2 +- logic/规则Logic.md | 307 +++++++++++++----- 4 files changed, 230 insertions(+), 83 deletions(-) diff --git a/CAPI/cpp/API/include/API.h b/CAPI/cpp/API/include/API.h index 42a8cc3..bb61b0b 100644 --- a/CAPI/cpp/API/include/API.h +++ b/CAPI/cpp/API/include/API.h @@ -99,6 +99,7 @@ public: // 捡道具、使用技能 virtual std::future PickProp(THUAI6::PropType prop) = 0; virtual std::future UseProp(THUAI6::PropType prop) = 0; + virtual std::future ThrowProp(THUAI6::PropType prop) = 0; virtual std::future UseSkill(int32_t skillID) = 0; virtual std::future Attack(double angleInRadian) = 0; @@ -124,7 +125,6 @@ public: // 获取视野内可见的道具信息 [[nodiscard]] virtual std::vector> GetProps() const = 0; - // 获取地图信息,视野外的地图统一为Land [[nodiscard]] virtual std::vector> GetFullMap() const = 0; [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; diff --git a/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs index 85c3c34..8760d02 100644 --- a/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs +++ b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs @@ -137,7 +137,6 @@ namespace GameClass.GameObj switch (gameObjType) { case GameObjType.Character: - case GameObjType.Generator: return true; default: return false; @@ -184,7 +183,6 @@ namespace GameClass.GameObj switch (gameObjType) { case GameObjType.Character: - case GameObjType.Generator: return true; default: return false; diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 037c7e4..123c81a 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -185,7 +185,7 @@ namespace Preparation.Utility public const int MinAP = 0; // 最小攻击力 public const int MaxAP = int.MaxValue; // 最大攻击力 - public const int factorDamageGenerator = 2;//子弹对电机的破坏=factorDamageGenerator*AP; + public const int factorDamageGenerator = 1;//子弹对电机的破坏=factorDamageGenerator*AP; public const int bulletRadius = 200; // 默认子弹半径 public const int basicBulletNum = 3; // 基本初始子弹量 diff --git a/logic/规则Logic.md b/logic/规则Logic.md index 96eb5a4..61fbdee 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -1,10 +1,6 @@ # 规则Logic -## 说明 -- *斜体表示Logic底层尚未(完全)实现* -- []表示待决定 - -## 简要规则 +## 通过接口了解规则喵 ### 地图 - 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。 @@ -12,19 +8,25 @@ - **极坐标以x坐标轴为极轴,角度逆时针为正方向**。 - 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到: - 略 -- 地图上的每个格子有自己的区域类型:陆地、墙、草地、电机、出口、紧急出口、门、窗、箱子 +- 地图上的每个格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 + +### 移动 +- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动的方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴** + +### 使用技能 +- `std::future UseSkill(int32_t skillID)`:使用对应序号的主动技能 ### 人物 - 人物半径为800 -- 游戏人物共有17种不可叠加的状态:(加^为学生独有) -1. 普通状态 +- 人物共有17种不可叠加的状态:(加^为学生独有) +1. (可)移动状态 2. 学习^ -3. 被治疗^ -4. 在治疗^ +3. 被勉励^ +4. 在勉励^ 5. 开或锁门 6. 翻箱 7. 使用技能 -8. 正在毕业^ +8. 开启校门^ 9. 唤醒他人中^ 10. 被唤醒中(从沉迷状态中^ @@ -37,64 +39,91 @@ 17. 翻窗 - 其中后8项为不可行动状态 - - 不加声明,不可行动状态中的玩家各项指令是无效的 +- `std::future EndAllAction()`:可以使处在2-9状态的玩家终止对应交互,对于后8项状态无效 + +### 攻击 +- `std::future Attack(double angleInRadian)`:`angleInRadian`为攻击方向,无论近战远程均产生bullet表示攻击 +- 攻击类型CommonAttackOfGhost攻击未写完的作业,会造成对应攻击力的损坏 +- 捣蛋鬼攻击交互状态或前后摇的学生,将使学生眩晕4.3s + +| 攻击类型 |搞蛋鬼的一般攻击CommonAttackOfGhost| 飞刀FlyingKnife | 蹦蹦炸弹BombBomb | JumpyDumpty | +| :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | +| 子弹爆炸范围 | 0 | 0 | 1000 | 500 | +| 子弹攻击距离 | 1100 | 39000 | 1100 | 2200 | +| 攻击力 | 1500000 | 1,200,000 | 1,800,000 | 900000 | +| 移动速度/s | 3700 | 7,400 | 3000 | 4300 | +| 前摇(ms) | 297 | 500 | 366 | 0 | +|未攻击至目标时的后摇(ms)| 800 | 0 | 3700 | 0 | +|攻击至目标时的后摇(ms)| 3700 | 0 | 3700 | 0 | +| CD(ms) | 800 | 400 | 3000 | - | +| 最大子弹容量 | 1 | 1 | 1 | - | ### 交互 -- 除了翻窗,交互目标与交互者在一个九宫格内则为可交互 - - 翻窗时玩家应当在目标前后左右一个格子内 +- 除了翻窗,交互目标与交互者在一个九宫格方可交互 +- 交互进度每毫秒增加对应交互速度的值 +- 作业,门,箱子完成/开启进度达到10000000为完成 #### 破译与逃脱 -- 每张地图都有10台电机,学生需要破译其中的**7台**,并开启任意大门(总所需时间为18秒)后从开启的大门逃脱,亦或在只剩1名学生的情况下从紧急出口逃脱; -- 紧急出口会在电机破译完成3台的情况下在地图的3-5个固定紧急出口刷新点之一随机刷新显示。 -- 当学生只剩1名时,紧急出口将会自动打开,该学生可从紧急出口逃脱。 -- 大门开启的进度不清空 - -#### 攻击 -- 无论近战远程均产生bullet以表示攻击所至距离 -- 如果有前摇,前摇最大时间一般为攻击最远距离/bullet移动速度。前摇期间攻击被打断时,子弹消失。 -- 无论搞蛋鬼或学生,攻击后,通常会出现一段无伤害判定的攻击动作后置时间,称为后摇。击中物体时后摇更长 -- 搞蛋鬼可以攻击未修完的作业,造成(攻击力*2/100000)%的 -- 捣蛋鬼攻击或一些特定技能击中以下状态的学生,将使学生眩晕4.3s -1. 处于前摇或后摇 -2. 治疗或解救他人 -3. 修理电机 -4. 开锁门 -5. 翻窗 -6. 开启箱子 - -#### 治疗 -- 治疗时每毫秒增加相当于治疗者治疗速度的被治疗程度 -- 当达到被治疗程度达到1500000或者最大血量与当前血量的差值时,治疗结束。 -- 治疗中断时,被治疗程度保留;被治疗者遭到攻击时被治疗程度清空 +- 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。 +- `std::future StartLearning()`:在教室(旁)做作业 +- `std::future StartOpenGate()`:开启校门,所需时间为18秒,开启的进度不清空 +- 隐藏校门会在**3间**教室的作业完成的情况下在3-5个隐藏校门刷新点之一随机显现,当学生只剩1名时,隐藏校门将会自动打开。 +- `std::future Graduate()`:从开启的校门或隐藏校门毕业。 + +#### 勉励(Treat) +- `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大血量与当前血量的差值时,勉励结束。 +- 勉励中断时,被勉励程度保留;被勉励者遭到攻击时被勉励程度清空 #### 沉迷与唤醒 -- 当学生血量归零时,学生自动原地进入沉迷状态,每毫秒增加1沉迷度 -- 该学生可由其他的学生唤醒,唤醒后,血量恢复至1/2并可以重新行动。沉迷程度不清空。 -- 一般情况下,唤醒时间为1秒。 -- 进入沉迷状态时。如果学生原本沉迷程度在(0,其最大沉迷度/3)中,学生沉迷程度直接变为其最大沉迷度/3;如果学生原本沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,学生沉迷程度直接变为其最大沉迷度x2/3;如果学生原本沉迷程度大于其最大沉迷度x2/3,从游戏中出局; -- 当学生沉迷程度达到该玩家最大沉迷程度时,从游戏中出局 +- 当学生血量归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 +- `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后血量恢复至1/2。沉迷程度不清空。 +- 进入沉迷状态时。如果学生原沉迷程度在(0,其最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; + - 当学生沉迷程度达到该玩家最大沉迷程度时,从游戏中出局 #### 门 - 门分别属于三个教学区:三教,五教,六教 -- 需要拿到对应教学区的钥匙才能打开或锁住对应的门 -- 钥匙只会出现在箱子中,每个教学区都有2把钥匙 -- 当门所在格子内有人时,无法锁门 - - 锁门时其他人可以进入门所在格子,锁门过程中断 +- 拥有对应教学区的钥匙才能开锁对应的门 + - 锁门过程中,门所在格子内有人会使锁门过程中断 +- `std::future OpenDoor()`:开门 +- `std::future CloseDoor()`:关门 #### 窗 -- 通常情况下捣蛋鬼翻越窗户的速度高于学生。 -- 有人正在翻越窗户时,其他玩家均不可以翻越该窗户。 +- `std::future SkipWindow()`:翻窗时玩家应当在窗前后左右一个格子内 #### 箱子 -- 开启箱子后将有2个随机道具掉落在玩家位置。 -- 开启箱子的基础持续时间为10秒。 -- 箱子道具不刷新 +- `std::future StartOpenChest()`:开箱后将有2个随机道具掉落在玩家位置。 -#### Bgm +### Bgm 1. 不详的感觉:捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) 2. 期待搞事的感觉:学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) 3. 学习的声音: 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 +### 队内信息 +- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。`toPlayerID`指定发送的对象,`message`指定发送的内容。`message`的长度不能超过 64,否则将发送失败! +- `bool HaveMessage()`:有队友发来的尚未接收的信息,则返回 true 。 + +### 信息受限 +- 以上主动行为每 50ms 最多总共可以调用 50 次;主动返回 bool 值代表本次操作是否成功。 +- `bool Wait()`:asynchronous 为 true 的情况下,选手可以调用此函数,阻塞当前线程,直到下一次消息更新时继续运行。 + +### 信息获取 +`std::vector> GetStudents() const` :返回所有可视学生的信息。 +`std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 +`std::vector> GetProps() const` :返回所有可视道具的信息。 +`std::vector> GetFullMap() const`:返回整张地图的地形信息。 +注意下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 +`THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 +`bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 +`int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 +`int32_t GetGateProgress(int32_t cellX, int32_t cellY) const`:查询特定位置校门开启进度 +`int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 +`THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 +`int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 +`std::shared_ptr GetGameInfo() const`:查询当前游戏状态 +`std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID +`int GetFrameCount() const`:获取目前所进行的帧数 +`std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 + ### 得分 #### 屠夫 @@ -117,17 +146,22 @@ - 不同道具/技能有不同得分 - 使屠夫进入特殊状态得分(如使之眩晕) - 救人 -- 治疗 +- 勉励 - 逃脱 - 解除眩晕 - 开锁门 -## 道具 +### 道具 +- 玩家最多同时拥有三个道具 +- 道具对于捣蛋鬼与学生可能有不同效果 +- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 +- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 +- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 | 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| -| Key5 | 能开启5教的门 |不得分| 能开启3教的门 |不得分| -| Key6 | 能开启6教的门 |不得分| 能开启3教的门 |不得分| +| Key5 | 能开启5教的门 |不得分| 能开启5教的门 |不得分| +| Key6 | 能开启6教的门 |不得分| 能开启6教的门 |不得分| | AddSpeed | 提高移动速度,持续10s |得分?| 提高移动速度,持续10s |得分?| | AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | | AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | @@ -189,7 +223,7 @@ | 最大毅力值 | 3000000 | 10 | 1 | 1.1 | 32/30 | | 最大沉迷度 | 60000 | 10 | 0.9 | 1.3 | 1.1 | | 学习一科速度/s | 1.23% | 0 | 0.6 | 1.1 | 1 | -| 治疗速度 | 100 | 0.7 | 0.8 | 0.8 | 2 | +| 勉励速度 | 100 | 0.7 | 0.8 | 0.8 | 2 | | 隐蔽度 | 1.0 | 0.5 | 0.9 | 0.9 | 1 | | 警戒范围 | 15000 | 0.5 | 1 | 0.9 | 1 | | 视野范围 | 10000 | 0.9 | 1.1 | 0.9 | 1 | @@ -232,48 +266,156 @@ - 通过唤醒获得对应得分 - 勉励 - CD:60s - - 使用瞬间,治疗完成可视范围内一个毅力不足的人 - - 通过治疗获得对应得分 + - 使用瞬间,勉励完成可视范围内一个毅力不足的人 + - 通过勉励获得对应得分 - 鼓舞 - CD:60s - 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff - 每鼓舞一个学生得分10 -### 攻击类型 -| 攻击类型 |搞蛋鬼的一般攻击CommonAttackOfGhost| 飞刀FlyingKnife | 蹦蹦炸弹BombBomb | JumpyDumpty | -| :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | -| 子弹爆炸范围 | 0 | 0 | 1000 | 500 | -| 子弹攻击距离 | 1100 | 39000 | 1100 | 2200 | -| 攻击力 | 1500000 | 1,200,000 | 1,800,000 | 900000 | -| 移动速度/s | 3700 | 7,400 | 3000 | 4300 | -| 有无前摇(ms) | 297 | 500 | 366 | 0 | -|未攻击至目标时的后摇(ms)| 800 | 0 | 3700 | 0 | -|攻击至目标时的后摇(ms)| 3700 | 0 | 3700 | 0 | -| CD(ms) | 800 | 400 | 3000 | - | -| 最大子弹容量 | 1 | 1 | 1 | - | - -## 游戏数据 -请自行查看Logic/Preparation/Utility/GameData.cs - +## 辅助函数 +`static inline int CellToGrid(int cell) noexcept`:将地图格数 cell 转换为绝对坐标grid。 +`static inline int GridToCell(int grid) noexcept`:将绝对坐标 grid 转换为地图格数cell。 +下面为用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 +~~~csharp + void Print(std::string str) const; + void PrintStudent() const; + void PrintTricker() const; + void PrintProp() const; + void PrintSelfInfo() const; +~~~ + +## 接口一览 +~~~csharp + // 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 + virtual std::future Move(int64_t timeInMilliseconds, double angleInRadian) = 0; + + // 向特定方向移动 + virtual std::future MoveRight(int64_t timeInMilliseconds) = 0; + virtual std::future MoveUp(int64_t timeInMilliseconds) = 0; + virtual std::future MoveLeft(int64_t timeInMilliseconds) = 0; + virtual std::future MoveDown(int64_t timeInMilliseconds) = 0; + + // 捡道具、使用技能 + virtual std::future PickProp(THUAI6::PropType prop) = 0; + virtual std::future UseProp(THUAI6::PropType prop) = 0; + virtual std::future UseSkill(int32_t skillID) = 0; + virtual std::future Attack(double angleInRadian) = 0; + + virtual std::future OpenDoor() = 0; + virtual std::future CloseDoor() = 0; + virtual std::future SkipWindow() = 0; + virtual std::future StartOpenGate() = 0; + virtual std::future StartOpenChest() = 0; + virtual std::future EndAllAction() = 0; + + // 发送信息、接受信息,注意收消息时无消息则返回nullopt + virtual std::future SendMessage(int64_t, std::string) = 0; + [[nodiscard]] virtual bool HaveMessage() = 0; + [[nodiscard]] virtual std::pair GetMessage() = 0; + + // 等待下一帧 + virtual std::future Wait() = 0; + + // 获取视野内可见的学生/捣蛋鬼的信息 + [[nodiscard]] virtual std::vector> GetStudents() const = 0; + [[nodiscard]] virtual std::vector> GetTrickers() const = 0; + + // 获取视野内可见的道具信息 + [[nodiscard]] virtual std::vector> GetProps() const = 0; + + // 获取地图信息,视野外的地图统一为Land + [[nodiscard]] virtual std::vector> GetFullMap() const = 0; + [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; + + [[nodiscard]] virtual bool IsDoorOpen(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetChestProgress(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetGateProgress(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const = 0; + + [[nodiscard]] virtual std::shared_ptr GetGameInfo() const = 0; + + // 获取所有玩家的GUID + [[nodiscard]] virtual std::vector GetPlayerGUIDs() const = 0; + + // 获取游戏目前所进行的帧数 + [[nodiscard]] virtual int GetFrameCount() const = 0; + + /*****选手可能用的辅助函数*****/ + + // 获取指定格子中心的坐标 + [[nodiscard]] static inline int CellToGrid(int cell) noexcept + { + return cell * numOfGridPerCell + numOfGridPerCell / 2; + } + + // 获取指定坐标点所位于的格子的 X 序号 + [[nodiscard]] static inline int GridToCell(int grid) noexcept + { + return grid / numOfGridPerCell; + } + + // 用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 + + virtual void Print(std::string str) const = 0; + virtual void PrintStudent() const = 0; + virtual void PrintTricker() const = 0; + virtual void PrintProp() const = 0; + virtual void PrintSelfInfo() const = 0; +}; + +class IStudentAPI : public IAPI +{ +public: + /*****学生阵营的特定函数*****/ + + virtual std::future StartLearning() = 0; + virtual std::future StartTreatMate(int64_t mateID) = 0; + virtual std::future StartRescueMate(int64_t mateID) = 0; + virtual std::future Graduate() = 0; + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; +}; + +class ITrickerAPI : public IAPI +{ +public: + /*****捣蛋鬼阵营的特定函数*****/ + + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; +}; +~~~ ## 细则 ### 特殊说明 - 不加说明,这里“学生”往往包括职业“教师” +### 移动 +- 不鼓励选手面向地图编程,因为移动过程中你可以受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。 +- `bool MoveRight(uint32_t timeInMilliseconds)`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理 + +### 人物 +- 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 + ### 初始状态 - 玩家出生点固定且一定为空地 +### 道具 +- 使用钥匙相当于销毁 + ### 交互 - 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 - - 实际上救援或治疗不同的人是有效的 + - 实际上救援或勉励不同的人是有效的 ### 破译与逃脱 -- 紧急出口与大门对于人有碰撞体积 -- 一个大门同时最多可以由一人开启 +- 隐藏校门与校门对于人有碰撞体积 +- 一个校门同时最多可以由一人开启 ### 攻击 - 每次学生受到攻击后会损失对应子弹的攻击力的血量 +- 前摇期间攻击被打断时,子弹消失。 - 此处,前摇指 从播放攻击动作开始 攻击者不能交互 的时间 ### 沉迷与唤醒 @@ -281,6 +423,7 @@ - 不能两人同时唤醒一个人 ### 门 +- 每个教学区都有2把钥匙 - 一扇门只允许同时一个人开锁门 - 开锁门未完成前,门状态表现为原来的状态 - 开锁门进度中断后清空 @@ -290,12 +433,18 @@ - 翻越窗户是一种交互行为,翻窗一共有两个过程 - 跳上窗:从当前位置到窗边缘中点,位置瞬移,时间=距离/爬窗速度。中断时,停留在原位置 - 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度。中断时,停留在另一侧格子中心 +- 通常情况下捣蛋鬼翻越窗户的速度高于学生。 +- 有人正在翻越窗户时,其他玩家均不可以翻越该窗户。 ### 箱子 - 地图上有8个箱子 - 同一时刻只允许一人进行开启 - 未开启完成的箱子在下一次需要重新开始开启。 - 箱子开启后其中道具才可以被观测和拿取 +- 箱子道具不刷新 + +### 信息获取 +- 查询对应物体状态时物体不存在则返回false ## 键鼠控制 @@ -309,9 +458,9 @@ | 鼠标双击某点 | (Tri)攻击,方向与从Tricker指向该点的向量相同 | | K | (Stu)开始学习 | | R | (Stu)开始营救(陷入沉迷状态的同伴) | -| T | (Stu)开始治疗(学习毅力下降的同伴) | +| T | (Stu)开始勉励(学习毅力下降的同伴) | | G | (Stu)发出毕业请求 | -| H | (Stu)申请毕业(或称为开大门) | +| H | (Stu)申请毕业(或称为开校门) | | O | (Both)开(教学楼)门 | | P | (Both)关(教学楼)门 | | U | (Both)翻窗 | From b8f7fa257fb64f21c72e79404f1e9cfcaade7f0f Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sun, 9 Apr 2023 03:59:21 +0800 Subject: [PATCH 07/37] =?UTF-8?q?build:=20:construction:=20edit=20?= =?UTF-8?q?=E8=A7=84=E5=88=99Logic.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logic/Preparation/Utility/GameData.cs | 2 +- logic/规则Logic.md | 84 ++++++++++++++------------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 123c81a..c37c7f5 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -90,7 +90,7 @@ namespace Preparation.Utility public const int basicTreatSpeed = 100; public const int basicFixSpeed = 123; - public const int basicSpeedOfOpeningOrLocking = 4130; + public const int basicSpeedOfOpeningOrLocking = 4000; public const int basicStudentSpeedOfClimbingThroughWindows = 611; public const int basicGhostSpeedOfClimbingThroughWindows = 1270; public const int basicSpeedOfOpenChest = 1000; diff --git a/logic/规则Logic.md b/logic/规则Logic.md index 61fbdee..edf39c2 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -18,21 +18,21 @@ ### 人物 - 人物半径为800 -- 人物共有17种不可叠加的状态:(加^为学生独有) +- 人物共有17种不可叠加的状态: 1. (可)移动状态 -2. 学习^ -3. 被勉励^ -4. 在勉励^ +2. 学习 +3. 被勉励 +4. 在勉励 5. 开或锁门 6. 翻箱 7. 使用技能 -8. 开启校门^ -9. 唤醒他人中^ +8. 开启校门 +9. 唤醒他人中 -10. 被唤醒中(从沉迷状态中^ -11. 沉迷^ -12. 退学^ -13. 毕业^ +10. 被唤醒中 +11. 沉迷 +12. 退学 +13. 毕业 14. 被眩晕 15. 前摇 16. 后摇 @@ -72,13 +72,13 @@ #### 勉励(Treat) - `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大血量与当前血量的差值时,勉励结束。 -- 勉励中断时,被勉励程度保留;被勉励者遭到攻击时被勉励程度清空 +- 勉励中断时,被勉励程度保留;遭到攻击时被勉励程度清空 #### 沉迷与唤醒 - 当学生血量归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 - `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后血量恢复至1/2。沉迷程度不清空。 -- 进入沉迷状态时。如果学生原沉迷程度在(0,其最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; - - 当学生沉迷程度达到该玩家最大沉迷程度时,从游戏中出局 +- 进入沉迷状态时。如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; + - 当学生沉迷程度达到其最大沉迷程度时,从游戏中出局 #### 门 - 门分别属于三个教学区:三教,五教,六教 @@ -100,10 +100,10 @@ ### 队内信息 - `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。`toPlayerID`指定发送的对象,`message`指定发送的内容。`message`的长度不能超过 64,否则将发送失败! -- `bool HaveMessage()`:有队友发来的尚未接收的信息,则返回 true 。 +- `bool HaveMessage()`:是否有队友发来的尚未接收的信息。 ### 信息受限 -- 以上主动行为每 50ms 最多总共可以调用 50 次;主动返回 bool 值代表本次操作是否成功。 +- 主动行为每 50ms 最多总共可以调用 50 次; - `bool Wait()`:asynchronous 为 true 的情况下,选手可以调用此函数,阻塞当前线程,直到下一次消息更新时继续运行。 ### 信息获取 @@ -111,7 +111,8 @@ `std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 `std::vector> GetProps() const` :返回所有可视道具的信息。 `std::vector> GetFullMap() const`:返回整张地图的地形信息。 -注意下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 + +- 下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 `THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 `bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 `int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 @@ -119,14 +120,32 @@ `int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 `THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 `int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 + `std::shared_ptr GetGameInfo() const`:查询当前游戏状态 `std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID `int GetFrameCount() const`:获取目前所进行的帧数 `std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 -### 得分 +### 道具 +- 玩家最多同时拥有三个道具 +- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 +- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 +- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 + +| 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | +| :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| +| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| +| Key5 | 能开启5教的门 |不得分| 能开启5教的门 |不得分| +| Key6 | 能开启6教的门 |不得分| 能开启6教的门 |不得分| +| AddSpeed | 提高移动速度,持续10s |得分?| 提高移动速度,持续10s |得分?| +| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | +| AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | +| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生| +| RecoveryFromDizziness | 使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分?|使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分?| + +## 得分 -#### 屠夫 +### 屠夫 - [Tricker对Student造成伤害时,得伤害*100/基本伤害(1500000)分。] - *[使用道具/技能得分]* @@ -137,7 +156,7 @@ - 主动解除眩晕,得15分 - 开锁门 -#### 人类 +### 人类 - 修机得分 - 人类每修n%的电机,得n分 - 修完一台电机,额外得?分 @@ -151,23 +170,6 @@ - 解除眩晕 - 开锁门 -### 道具 -- 玩家最多同时拥有三个道具 -- 道具对于捣蛋鬼与学生可能有不同效果 -- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 -- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 -- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 -| 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | -| :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| -| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| -| Key5 | 能开启5教的门 |不得分| 能开启5教的门 |不得分| -| Key6 | 能开启6教的门 |不得分| 能开启6教的门 |不得分| -| AddSpeed | 提高移动速度,持续10s |得分?| 提高移动速度,持续10s |得分?| -| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | -| AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | -| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生| -| RecoveryFromDizziness | 使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分?|使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分?| - ## 职业与技能 ### 捣蛋鬼 @@ -178,9 +180,9 @@ | 隐蔽度 | 1.0 | 1.5 | 1 | 0.8 | | 警戒范围 | 17000 | 1.3 | 1 | 0.9 | | 视野范围 | 15000 | 1.2 | 1 | 1 | -| 开锁门时间/s | 41.3% | 1 | 1 | 1 | +| 开锁门速度 | 4000 | 1 | 1 | 1 | | 翻窗速度 | 1270 | 1 | 1 | 1.1 | -| 翻箱时间/s | 10% | 1 | 1.1 | 1 | +| 翻箱速度 | 1000 | 1 | 1.1 | 1 | #### 刺客 - 普通攻击为 搞蛋鬼的一般攻击 @@ -227,9 +229,9 @@ | 隐蔽度 | 1.0 | 0.5 | 0.9 | 0.9 | 1 | | 警戒范围 | 15000 | 0.5 | 1 | 0.9 | 1 | | 视野范围 | 10000 | 0.9 | 1.1 | 0.9 | 1 | -| 开锁门时间/s | 4.13% | 1 | 1 | 1 | 1 | +| 开锁门速度 | 4000 | 1 | 1 | 1 | 1 | | 翻窗速度 | 1270 | 0.5 | 1.2 | 10/12 | 1 | -| 翻箱时间/s | 10% | 1 | 1 | 1 | 1 | +| 翻箱速度 | 1000 | 1 | 1 | 1 | 1 | #### 运动员 - 主动技能 @@ -277,7 +279,7 @@ `static inline int CellToGrid(int cell) noexcept`:将地图格数 cell 转换为绝对坐标grid。 `static inline int GridToCell(int grid) noexcept`:将绝对坐标 grid 转换为地图格数cell。 下面为用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 -~~~csharp +~~~c void Print(std::string str) const; void PrintStudent() const; void PrintTricker() const; From 87ed4aafc420f5bb2340272a3cf755f70635b158 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Sun, 9 Apr 2023 13:47:39 +0800 Subject: [PATCH 08/37] feat(CAPI): :sparkles: add some missing interfaces --- CAPI/cpp/API/include/API.h | 19 ++- CAPI/cpp/API/include/Communication.h | 1 + CAPI/cpp/API/include/logic.h | 2 + CAPI/cpp/API/src/API.cpp | 22 ++++ CAPI/cpp/API/src/Communication.cpp | 12 ++ CAPI/cpp/API/src/DebugAPI.cpp | 30 +++++ CAPI/cpp/API/src/logic.cpp | 15 +++ CAPI/python/PyAPI/AI.py | 177 +++++++++++++++++++++------ CAPI/python/PyAPI/API.py | 12 ++ CAPI/python/PyAPI/Communication.py | 11 +- CAPI/python/PyAPI/DebugAPI.py | 32 +++++ CAPI/python/PyAPI/Interface.py | 16 +++ CAPI/python/PyAPI/logic.py | 40 +++--- CAPI/python/PyAPI/main.py | 1 - CAPI/python/run.sh | 4 +- 15 files changed, 335 insertions(+), 59 deletions(-) diff --git a/CAPI/cpp/API/include/API.h b/CAPI/cpp/API/include/API.h index 42a8cc3..c4516df 100644 --- a/CAPI/cpp/API/include/API.h +++ b/CAPI/cpp/API/include/API.h @@ -35,6 +35,7 @@ public: [[nodiscard]] virtual std::vector> GetTrickers() const = 0; [[nodiscard]] virtual std::vector> GetStudents() const = 0; [[nodiscard]] virtual std::vector> GetProps() const = 0; + [[nodiscard]] virtual std::vector> GetBullets() const = 0; [[nodiscard]] virtual std::shared_ptr StudentGetSelfInfo() const = 0; [[nodiscard]] virtual std::shared_ptr TrickerGetSelfInfo() const = 0; @@ -54,6 +55,7 @@ public: virtual bool Move(int64_t time, double angle) = 0; virtual bool PickProp(THUAI6::PropType prop) = 0; virtual bool UseProp(THUAI6::PropType prop) = 0; + virtual bool ThrowProp(THUAI6::PropType prop) = 0; virtual bool UseSkill(int32_t skillID) = 0; virtual bool SendMessage(int64_t toID, std::string message) = 0; virtual bool HaveMessage() = 0; @@ -99,6 +101,7 @@ public: // 捡道具、使用技能 virtual std::future PickProp(THUAI6::PropType prop) = 0; virtual std::future UseProp(THUAI6::PropType prop) = 0; + virtual std::future ThrowProp(THUAI6::PropType prop) = 0; virtual std::future UseSkill(int32_t skillID) = 0; virtual std::future Attack(double angleInRadian) = 0; @@ -124,7 +127,9 @@ public: // 获取视野内可见的道具信息 [[nodiscard]] virtual std::vector> GetProps() const = 0; - // 获取地图信息,视野外的地图统一为Land + // 获取视野内可见的子弹信息 + [[nodiscard]] virtual std::vector> GetBullets() const = 0; + [[nodiscard]] virtual std::vector> GetFullMap() const = 0; [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; @@ -221,6 +226,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future Attack(double angleInRadian) override; @@ -243,6 +249,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; @@ -308,6 +316,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future OpenDoor() override; @@ -328,6 +337,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; @@ -383,6 +394,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future Attack(double angleInRadian) override; @@ -405,6 +417,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; @@ -455,6 +469,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future OpenDoor() override; @@ -475,6 +490,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; diff --git a/CAPI/cpp/API/include/Communication.h b/CAPI/cpp/API/include/Communication.h index 7aa2d96..3490b75 100644 --- a/CAPI/cpp/API/include/Communication.h +++ b/CAPI/cpp/API/include/Communication.h @@ -26,6 +26,7 @@ public: bool Move(int64_t time, double angle, int64_t playerID); bool PickProp(THUAI6::PropType prop, int64_t playerID); bool UseProp(THUAI6::PropType prop, int64_t playerID); + bool ThrowProp(THUAI6::PropType prop, int64_t playerID); bool UseSkill(int32_t skillID, int64_t playerID); bool SendMessage(int64_t toID, std::string message, int64_t playerID); bool OpenDoor(int64_t playerID); diff --git a/CAPI/cpp/API/include/logic.h b/CAPI/cpp/API/include/logic.h index 3002938..2db779b 100644 --- a/CAPI/cpp/API/include/logic.h +++ b/CAPI/cpp/API/include/logic.h @@ -94,6 +94,7 @@ private: [[nodiscard]] std::vector> GetTrickers() const override; [[nodiscard]] std::vector> GetStudents() const override; [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; [[nodiscard]] std::shared_ptr StudentGetSelfInfo() const override; [[nodiscard]] std::shared_ptr TrickerGetSelfInfo() const override; [[nodiscard]] THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const override; @@ -113,6 +114,7 @@ private: bool Move(int64_t time, double angle) override; bool PickProp(THUAI6::PropType prop) override; bool UseProp(THUAI6::PropType prop) override; + bool ThrowProp(THUAI6::PropType prop) override; bool UseSkill(int32_t skillID) override; bool SendMessage(int64_t toID, std::string message) override; diff --git a/CAPI/cpp/API/src/API.cpp b/CAPI/cpp/API/src/API.cpp index b65bec2..03e08c7 100644 --- a/CAPI/cpp/API/src/API.cpp +++ b/CAPI/cpp/API/src/API.cpp @@ -89,6 +89,18 @@ std::future TrickerAPI::UseProp(THUAI6::PropType prop) { return logic.UseProp(prop); }); } +std::future StudentAPI::ThrowProp(THUAI6::PropType prop) +{ + return std::async(std::launch::async, [=]() + { return logic.ThrowProp(prop); }); +} + +std::future TrickerAPI::ThrowProp(THUAI6::PropType prop) +{ + return std::async(std::launch::async, [=]() + { return logic.ThrowProp(prop); }); +} + std::future StudentAPI::UseSkill(int32_t skillID) { return std::async(std::launch::async, [=]() @@ -255,6 +267,16 @@ std::vector> TrickerAPI::GetProps() const return logic.GetProps(); } +std::vector> StudentAPI::GetBullets() const +{ + return logic.GetBullets(); +} + +std::vector> TrickerAPI::GetBullets() const +{ + return logic.GetBullets(); +} + std::vector> StudentAPI::GetFullMap() const { return logic.GetFullMap(); diff --git a/CAPI/cpp/API/src/Communication.cpp b/CAPI/cpp/API/src/Communication.cpp index 7d75de5..41a8590 100644 --- a/CAPI/cpp/API/src/Communication.cpp +++ b/CAPI/cpp/API/src/Communication.cpp @@ -51,6 +51,18 @@ bool Communication::UseProp(THUAI6::PropType prop, int64_t playerID) return false; } +bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID) +{ + protobuf::BoolRes throwPropResult; + ClientContext context; + auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID); + auto status = THUAI6Stub->ThrowProp(&context, request, &throwPropResult); + if (status.ok()) + return throwPropResult.act_success(); + else + return false; +} + bool Communication::UseSkill(int32_t skillID, int64_t playerID) { protobuf::BoolRes useSkillResult; diff --git a/CAPI/cpp/API/src/DebugAPI.cpp b/CAPI/cpp/API/src/DebugAPI.cpp index 2d91be6..f307148 100644 --- a/CAPI/cpp/API/src/DebugAPI.cpp +++ b/CAPI/cpp/API/src/DebugAPI.cpp @@ -187,6 +187,26 @@ std::future TrickerDebugAPI::UseProp(THUAI6::PropType prop) return result; }); } +std::future StudentDebugAPI::ThrowProp(THUAI6::PropType prop) +{ + logger->info("ThrowProp: prop={}, called at {}ms", THUAI6::propTypeDict[prop], Time::TimeSinceStart(startPoint)); + return std::async(std::launch::async, [=]() + { auto result = logic.ThrowProp(prop); + if (!result) + logger->warn("ThrowProp: failed at {}ms", Time::TimeSinceStart(startPoint)); + return result; }); +} + +std::future TrickerDebugAPI::ThrowProp(THUAI6::PropType prop) +{ + logger->info("ThrowProp: prop={}, called at {}ms", THUAI6::propTypeDict[prop], Time::TimeSinceStart(startPoint)); + return std::async(std::launch::async, [=]() + { auto result = logic.ThrowProp(prop); + if (!result) + logger->warn("ThrowProp: failed at {}ms", Time::TimeSinceStart(startPoint)); + return result; }); +} + std::future StudentDebugAPI::UseSkill(int32_t skillID) { logger->info("UseSkill: skillID={}, called at {}ms", skillID, Time::TimeSinceStart(startPoint)); @@ -435,6 +455,16 @@ std::vector> TrickerDebugAPI::GetProps() con return logic.GetProps(); } +std::vector> StudentDebugAPI::GetBullets() const +{ + return logic.GetBullets(); +} + +std::vector> TrickerDebugAPI::GetBullets() const +{ + return logic.GetBullets(); +} + std::vector> StudentDebugAPI::GetFullMap() const { return logic.GetFullMap(); diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index b6a85b4..8d01502 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -51,6 +51,15 @@ std::vector> Logic::GetProps() const return temp; } +std::vector> Logic::GetBullets() const +{ + std::unique_lock lock(mtxState); + std::vector> temp; + temp.assign(currentState->bullets.begin(), currentState->bullets.end()); + logger->debug("Called GetBullets"); + return temp; +} + std::shared_ptr Logic::StudentGetSelfInfo() const { std::unique_lock lock(mtxState); @@ -193,6 +202,12 @@ bool Logic::UseProp(THUAI6::PropType prop) return pComm->UseProp(prop, playerID); } +bool Logic::ThrowProp(THUAI6::PropType prop) +{ + logger->debug("Called ThrowProp"); + return pComm->ThrowProp(prop, playerID); +} + bool Logic::UseSkill(int32_t skill) { logger->debug("Called UseSkill"); diff --git a/CAPI/python/PyAPI/AI.py b/CAPI/python/PyAPI/AI.py index 791ee7f..0cd06a9 100644 --- a/CAPI/python/PyAPI/AI.py +++ b/CAPI/python/PyAPI/AI.py @@ -1,6 +1,7 @@ import PyAPI.structures as THUAI6 from PyAPI.Interface import IStudentAPI, ITrickerAPI, IAI from typing import Union, Final, cast +import queue import time @@ -9,7 +10,7 @@ class Setting: # 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新 @staticmethod def asynchronous() -> bool: - return False + return True # 选手必须修改该函数的返回值来选择自己的阵营 @staticmethod @@ -41,50 +42,146 @@ class AssistFunction: return grid // numOfGridPerCell -arrive: bool = False +path = [] +cur = 0 +fixedclass = [] class AI(IAI): # 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致 def StudentPlay(self, api: IStudentAPI) -> None: - api.Attack(float('nan')) - time.sleep(0.5) - api.PrintSelfInfo() - # api.SendMessage(4, "Hello World!") - # api.PrintSelfInfo() - # global arrive - # if not arrive: - # if api.GetSelfInfo().x < 25500: - # api.MoveDown(50) - # return - # if api.GetSelfInfo().y > 10500: - # api.MoveLeft(50) - # return - # arrive = True - # else: - # api.SkipWindow() - # # time.sleep(1) - - # api.PrintSelfInfo() - - # if api.GetSelfInfo().y < 18500: - # api.MoveRight(50) - # return - # api.StartLearning() - - # if api.GetSelfInfo().y > 7000: - # api.MoveLeft(50) - # return - # if api.GetSelfInfo().x > 20500: - # api.MoveUp(50) - # return - # if api.GetSelfInfo().y > 4500: - # api.MoveLeft(50) - # return - - api.PrintTricker() - - return + global fixedclass + selfInfo = api.GetSelfInfo() + available = [THUAI6.PlaceType.Land, + THUAI6.PlaceType.Grass, THUAI6.PlaceType.Door3, THUAI6.PlaceType.Door6, THUAI6.PlaceType.Door5, THUAI6.PlaceType.Gate] + + def bfs(x, y): + if api.GetPlaceType(x, y) not in available: + return [] + + def GetSuccessors(x, y): + successors = [] + if x > 0 and api.GetPlaceType(x - 1, y) in available: + successors.append((x - 1, y)) + if x < 49 and api.GetPlaceType(x + 1, y) in available: + successors.append((x + 1, y)) + if y > 0 and api.GetPlaceType(x, y - 1) in available: + successors.append((x, y - 1)) + if y < 49 and api.GetPlaceType(x, y + 1) in available: + successors.append((x, y + 1)) + return successors + selfX = AssistFunction.GridToCell(api.GetSelfInfo().x) + selfY = AssistFunction.GridToCell(api.GetSelfInfo().y) + frontier = queue.Queue() + frontier.put((selfX, selfY, [])) + visited = [] + while not frontier.empty(): + currentX, currentY, path = frontier.get() + if currentX == x and currentY == y: + return path + for nextX, nextY in GetSuccessors(currentX, currentY): + if (nextX, nextY) not in visited: + visited.append((nextX, nextY)) + frontier.put((nextX, nextY, path + [(nextX, nextY)])) + return [] + + def GoTo(x, y): + global path, cur + if path != [] and cur < len(path): + selfX = api.GetSelfInfo().x + selfY = api.GetSelfInfo().y + nextX, nextY = path[cur] + nextX = AssistFunction.CellToGrid(nextX) + nextY = AssistFunction.CellToGrid(nextY) + if selfX < nextX - 100: + api.MoveDown(10) + time.sleep(0.01) + return + if selfX > nextX + 100: + api.MoveUp(10) + time.sleep(0.01) + return + if selfY < nextY - 100: + api.MoveRight(10) + time.sleep(0.01) + return + if selfY > nextY + 100: + api.MoveLeft(10) + time.sleep(0.01) + return + cur += 1 + return + else: + path = bfs(x, y) + cur = 0 + return + + if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) < 18000: + api.StartOpenGate() + return + + if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) >= 18000: + api.Graduate() + return + + if len(fixedclass) == 7: + GoTo(6, 6) + return + + if api.GetPlaceType(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) == THUAI6.PlaceType.ClassRoom: + if api.GetSelfInfo().playerID == 0: + api.Print("Trying to fix!") + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: + api.StartLearning() + return + else: + if (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) not in fixedclass: + fixedclass.append( + (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) + elif api.GetSelfInfo().playerID == 1: + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: + api.StartLearning() + return + else: + fixedclass.append((AssistFunction.GridToCell( + api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) + elif api.GetSelfInfo().playerID == 2: + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1) < 103000: + api.StartLearning() + return + else: + fixedclass.append((AssistFunction.GridToCell( + api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1)) + elif api.GetSelfInfo().playerID == 3: + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1) < 103000: + api.StartLearning() + return + else: + fixedclass.append((AssistFunction.GridToCell( + api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1)) + + for i in range(50): + for j in range(50): + if api.GetSelfInfo().playerID == 0: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i - 1, j) in available: + GoTo(i - 1, j) + return + elif api.GetSelfInfo().playerID == 1: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i + 1, j) in available: + GoTo(i + 1, j) + return + elif api.GetSelfInfo().playerID == 2: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i, j - 1) in available: + GoTo(i, j - 1) + return + elif api.GetSelfInfo().playerID == 3: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i, j + 1) in available: + GoTo(i, j + 1) + return def TrickerPlay(self, api: ITrickerAPI) -> None: return diff --git a/CAPI/python/PyAPI/API.py b/CAPI/python/PyAPI/API.py index d9cba6e..bb5522b 100644 --- a/CAPI/python/PyAPI/API.py +++ b/CAPI/python/PyAPI/API.py @@ -41,6 +41,9 @@ class StudentAPI(IStudentAPI, IGameTimer): def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: return self.__pool.submit(self.__logic.UseProp, propType) + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + return self.__pool.submit(self.__logic.ThrowProp, propType) + def UseSkill(self, skillID: int) -> Future[bool]: return self.__pool.submit(self.__logic.UseSkill, skillID) @@ -99,6 +102,9 @@ class StudentAPI(IStudentAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() @@ -208,6 +214,9 @@ class TrickerAPI(ITrickerAPI, IGameTimer): def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: return self.__pool.submit(self.__logic.UseProp, propType) + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + return self.__pool.submit(self.__logic.ThrowProp, propType) + def UseSkill(self, skillID: int) -> Future[bool]: return self.__pool.submit(self.__logic.UseSkill, skillID) @@ -266,6 +275,9 @@ class TrickerAPI(ITrickerAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() diff --git a/CAPI/python/PyAPI/Communication.py b/CAPI/python/PyAPI/Communication.py index c9abcbd..41c201f 100644 --- a/CAPI/python/PyAPI/Communication.py +++ b/CAPI/python/PyAPI/Communication.py @@ -48,7 +48,7 @@ class Communication: else: return pickResult.act_success - def UseProp(self, propType: THUAI6.PropType, playerID: int): + def UseProp(self, propType: THUAI6.PropType, playerID: int) -> bool: try: useResult = self.__THUAI6Stub.UseProp( THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) @@ -57,6 +57,15 @@ class Communication: else: return useResult.act_success + def ThrowProp(self, propType: THUAI6.PropType, playerID: int) -> bool: + try: + throwResult = self.__THUAI6Stub.ThrowProp( + THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) + except grpc.RpcError as e: + return False + else: + return throwResult.act_success + def UseSkill(self, skillID: int, playerID: int) -> bool: try: useResult = self.__THUAI6Stub.UseSkill( diff --git a/CAPI/python/PyAPI/DebugAPI.py b/CAPI/python/PyAPI/DebugAPI.py index 98c4710..5e18c5f 100644 --- a/CAPI/python/PyAPI/DebugAPI.py +++ b/CAPI/python/PyAPI/DebugAPI.py @@ -109,6 +109,19 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): return self.__pool.submit(logUse) + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + self.__logger.info( + f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms") + + def logThrow() -> bool: + result = self.__logic.ThrowProp(propType) + if not result: + self.__logger.warning( + f"ThrowProp: failed at {self.__GetTime()}ms") + return result + + return self.__pool.submit(logThrow) + def UseSkill(self, skillID: int) -> Future[bool]: self.__logger.info( f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms") @@ -261,6 +274,9 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() @@ -545,6 +561,19 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): return self.__pool.submit(logUse) + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + self.__logger.info( + f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms") + + def logThrow() -> bool: + result = self.__logic.ThrowProp(propType) + if not result: + self.__logger.warning( + f"ThrowProp: failed at {self.__GetTime()}ms") + return result + + return self.__pool.submit(logThrow) + def UseSkill(self, skillID: int) -> Future[bool]: self.__logger.info( f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms") @@ -697,6 +726,9 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() diff --git a/CAPI/python/PyAPI/Interface.py b/CAPI/python/PyAPI/Interface.py index 732d1de..9566363 100644 --- a/CAPI/python/PyAPI/Interface.py +++ b/CAPI/python/PyAPI/Interface.py @@ -20,6 +20,10 @@ class ILogic(metaclass=ABCMeta): def GetProps(self) -> List[THUAI6.Prop]: pass + @abstractmethod + def GetBullets(self) -> List[THUAI6.Bullet]: + pass + @abstractmethod def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: pass @@ -72,6 +76,10 @@ class ILogic(metaclass=ABCMeta): def UseProp(self, propType: THUAI6.PropType) -> bool: pass + @abstractmethod + def ThrowProp(self, propType: THUAI6.PropType) -> bool: + pass + @abstractmethod def UseSkill(self, skillID: int) -> bool: pass @@ -184,6 +192,10 @@ class IAPI(metaclass=ABCMeta): def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: pass + @abstractmethod + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + pass + @abstractmethod def UseSkill(self, skillID: int) -> Future[bool]: pass @@ -258,6 +270,10 @@ class IAPI(metaclass=ABCMeta): def GetProps(self) -> List[THUAI6.Prop]: pass + @abstractmethod + def GetBullets(self) -> List[THUAI6.Bullet]: + pass + @abstractmethod def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: pass diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index 42d9b3a..ec9d559 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -2,6 +2,7 @@ import os from typing import List, Union, Callable, Tuple import threading import logging +import copy import proto.MessageType_pb2 as MessageType import proto.Message2Server_pb2 as Message2Server import proto.Message2Clients_pb2 as Message2Clients @@ -71,27 +72,32 @@ class Logic(ILogic): def GetTrickers(self) -> List[THUAI6.Tricker]: with self.__mtxState: self.__logger.debug("Called GetTrickers") - return self.__currentState.trickers + return copy.deepcopy(self.__currentState.trickers) def GetStudents(self) -> List[THUAI6.Student]: with self.__mtxState: self.__logger.debug("Called GetStudents") - return self.__currentState.students + return copy.deepcopy(self.__currentState.students) def GetProps(self) -> List[THUAI6.Prop]: with self.__mtxState: self.__logger.debug("Called GetProps") - return self.__currentState.props + return copy.deepcopy(self.__currentState.props) + + def GetBullets(self) -> List[THUAI6.Bullet]: + with self.__mtxState: + self.__logger.debug("Called GetBullets") + return copy.deepcopy(self.__currentState.bullets) def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: with self.__mtxState: self.__logger.debug("Called GetSelfInfo") - return self.__currentState.self + return copy.deepcopy(self.__currentState.self) def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: with self.__mtxState: self.__logger.debug("Called GetFullMap") - return self.__currentState.gameMap + return copy.deepcopy(self.__currentState.gameMap) def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType: with self.__mtxState: @@ -99,13 +105,13 @@ class Logic(ILogic): self.__logger.warning("Invalid position") return THUAI6.PlaceType.NullPlaceType self.__logger.debug("Called GetPlaceType") - return self.__currentState.gameMap[x][y] + return copy.deepcopy(self.__currentState.gameMap[x][y]) def IsDoorOpen(self, x: int, y: int) -> bool: with self.__mtxState: self.__logger.debug("Called IsDoorOpen") if (x, y) in self.__currentState.mapInfo.doorState: - return self.__currentState.mapInfo.doorState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.doorState[(x, y)]) else: self.__logger.warning("Door not found") return False @@ -114,7 +120,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetClassroomProgress") if (x, y) in self.__currentState.mapInfo.classroomState: - return self.__currentState.mapInfo.classroomState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.classroomState[(x, y)]) else: self.__logger.warning("Classroom not found") return 0 @@ -123,7 +129,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetChestProgress") if (x, y) in self.__currentState.mapInfo.chestState: - return self.__currentState.mapInfo.chestState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.chestState[(x, y)]) else: self.__logger.warning("Chest not found") return 0 @@ -132,7 +138,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetGateProgress") if (x, y) in self.__currentState.mapInfo.gateState: - return self.__currentState.mapInfo.gateState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.gateState[(x, y)]) else: self.__logger.warning("Gate not found") return 0 @@ -141,7 +147,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetHiddenGateState") if (x, y) in self.__currentState.mapInfo.hiddenGateState: - return self.__currentState.mapInfo.hiddenGateState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.hiddenGateState[(x, y)]) else: self.__logger.warning("HiddenGate not found") return THUAI6.HiddenGateState.Null @@ -150,7 +156,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetDoorProgress") if (x, y) in self.__currentState.mapInfo.doorProgress: - return self.__currentState.mapInfo.doorProgress[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.doorProgress[(x, y)]) else: self.__logger.warning("Door not found") return 0 @@ -158,7 +164,7 @@ class Logic(ILogic): def GetGameInfo(self) -> THUAI6.GameInfo: with self.__mtxState: self.__logger.debug("Called GetGameInfo") - return self.__currentState.gameInfo + return copy.deepcopy(self.__currentState.gameInfo) def Move(self, time: int, angle: float) -> bool: self.__logger.debug("Called Move") @@ -172,6 +178,10 @@ class Logic(ILogic): self.__logger.debug("Called UseProp") return self.__comm.UseProp(propType, self.__playerID) + def ThrowProp(self, propType: THUAI6.PropType) -> bool: + self.__logger.debug("Called ThrowProp") + return self.__comm.ThrowProp(propType, self.__playerID) + def UseSkill(self, skillID: int) -> bool: self.__logger.debug("Called UseSkill") return self.__comm.UseSkill(skillID, self.__playerID) @@ -198,11 +208,11 @@ class Logic(ILogic): def GetCounter(self) -> int: with self.__mtxState: - return self.__counterState + return copy.deepcopy(self.__counterState) def GetPlayerGUIDs(self) -> List[int]: with self.__mtxState: - return self.__playerGUIDs + return copy.deepcopy(self.__playerGUIDs) # IStudentAPI使用的接口 diff --git a/CAPI/python/PyAPI/main.py b/CAPI/python/PyAPI/main.py index d717884..5622a3b 100644 --- a/CAPI/python/PyAPI/main.py +++ b/CAPI/python/PyAPI/main.py @@ -39,7 +39,6 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None: file = args.file screen = args.screen warnOnly = args.warnOnly - print(warnOnly) logic = Logic(pID) logic.Main(AIBuilder, sIP, sPort, file, screen, warnOnly) diff --git a/CAPI/python/run.sh b/CAPI/python/run.sh index 00de795..ec08c25 100755 --- a/CAPI/python/run.sh +++ b/CAPI/python/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 0 -d -o & -# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 1 -d -o & \ No newline at end of file +# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 1 -d & +# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 2 -d & +# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 3 -d & \ No newline at end of file From 02b939884831c9f869537bfb4680e7c88cd5f481 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Sun, 9 Apr 2023 14:02:53 +0800 Subject: [PATCH 09/37] feat(CAPI): :sparkles: add invisible judgement --- CAPI/cpp/API/src/logic.cpp | 18 +++ CAPI/python/PyAPI/AI.py | 227 ++++++++++++++++--------------------- CAPI/python/PyAPI/logic.py | 4 + 3 files changed, 117 insertions(+), 132 deletions(-) diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index 8d01502..4b8415c 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -543,6 +543,15 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) } case THUAI6::MessageOfObj::TrickerMessage: { + bool flag = false; + for (int i = 0; i < item.tricker_message().buff_size(); i++) + if (Proto2THUAI6::trickerBuffTypeDict[item.tricker_message().buff(i)] == THUAI6::TrickerBuffType::Invisible) + { + flag = true; + break; + } + if (flag) + break; if (AssistFunction::HaveView(bufferState->studentSelf->viewRange, bufferState->studentSelf->x, bufferState->studentSelf->y, item.tricker_message().x(), item.tricker_message().y(), bufferState->gameMap)) { bufferState->trickers.push_back(Proto2THUAI6::Protobuf2THUAI6Tricker(item.tricker_message())); @@ -689,6 +698,15 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) } case THUAI6::MessageOfObj::StudentMessage: { + bool flag = false; + for (int i = 0; i < item.student_message().buff_size(); i++) + if (Proto2THUAI6::studentBuffTypeDict[item.student_message().buff(i)] == THUAI6::StudentBuffType::Invisible) + { + flag = true; + break; + } + if (flag) + break; if (AssistFunction::HaveView(bufferState->trickerSelf->viewRange, bufferState->trickerSelf->x, bufferState->trickerSelf->y, item.student_message().x(), item.student_message().y(), bufferState->gameMap)) { bufferState->students.push_back(Proto2THUAI6::Protobuf2THUAI6Student(item.student_message())); diff --git a/CAPI/python/PyAPI/AI.py b/CAPI/python/PyAPI/AI.py index 0cd06a9..eb4abd0 100644 --- a/CAPI/python/PyAPI/AI.py +++ b/CAPI/python/PyAPI/AI.py @@ -50,138 +50,101 @@ fixedclass = [] class AI(IAI): # 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致 def StudentPlay(self, api: IStudentAPI) -> None: - global fixedclass - selfInfo = api.GetSelfInfo() - available = [THUAI6.PlaceType.Land, - THUAI6.PlaceType.Grass, THUAI6.PlaceType.Door3, THUAI6.PlaceType.Door6, THUAI6.PlaceType.Door5, THUAI6.PlaceType.Gate] - - def bfs(x, y): - if api.GetPlaceType(x, y) not in available: - return [] - - def GetSuccessors(x, y): - successors = [] - if x > 0 and api.GetPlaceType(x - 1, y) in available: - successors.append((x - 1, y)) - if x < 49 and api.GetPlaceType(x + 1, y) in available: - successors.append((x + 1, y)) - if y > 0 and api.GetPlaceType(x, y - 1) in available: - successors.append((x, y - 1)) - if y < 49 and api.GetPlaceType(x, y + 1) in available: - successors.append((x, y + 1)) - return successors - selfX = AssistFunction.GridToCell(api.GetSelfInfo().x) - selfY = AssistFunction.GridToCell(api.GetSelfInfo().y) - frontier = queue.Queue() - frontier.put((selfX, selfY, [])) - visited = [] - while not frontier.empty(): - currentX, currentY, path = frontier.get() - if currentX == x and currentY == y: - return path - for nextX, nextY in GetSuccessors(currentX, currentY): - if (nextX, nextY) not in visited: - visited.append((nextX, nextY)) - frontier.put((nextX, nextY, path + [(nextX, nextY)])) - return [] - - def GoTo(x, y): - global path, cur - if path != [] and cur < len(path): - selfX = api.GetSelfInfo().x - selfY = api.GetSelfInfo().y - nextX, nextY = path[cur] - nextX = AssistFunction.CellToGrid(nextX) - nextY = AssistFunction.CellToGrid(nextY) - if selfX < nextX - 100: - api.MoveDown(10) - time.sleep(0.01) - return - if selfX > nextX + 100: - api.MoveUp(10) - time.sleep(0.01) - return - if selfY < nextY - 100: - api.MoveRight(10) - time.sleep(0.01) - return - if selfY > nextY + 100: - api.MoveLeft(10) - time.sleep(0.01) - return - cur += 1 - return - else: - path = bfs(x, y) - cur = 0 - return - - if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) < 18000: - api.StartOpenGate() - return - - if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) >= 18000: - api.Graduate() - return - - if len(fixedclass) == 7: - GoTo(6, 6) - return - - if api.GetPlaceType(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) == THUAI6.PlaceType.ClassRoom: - if api.GetSelfInfo().playerID == 0: - api.Print("Trying to fix!") - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: - api.StartLearning() - return - else: - if (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) not in fixedclass: - fixedclass.append( - (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) - elif api.GetSelfInfo().playerID == 1: - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: - api.StartLearning() - return - else: - fixedclass.append((AssistFunction.GridToCell( - api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) - elif api.GetSelfInfo().playerID == 2: - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1) < 103000: - api.StartLearning() - return - else: - fixedclass.append((AssistFunction.GridToCell( - api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1)) - elif api.GetSelfInfo().playerID == 3: - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1) < 103000: - api.StartLearning() - return - else: - fixedclass.append((AssistFunction.GridToCell( - api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1)) - - for i in range(50): - for j in range(50): - if api.GetSelfInfo().playerID == 0: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i - 1, j) in available: - GoTo(i - 1, j) - return - elif api.GetSelfInfo().playerID == 1: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i + 1, j) in available: - GoTo(i + 1, j) - return - elif api.GetSelfInfo().playerID == 2: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i, j - 1) in available: - GoTo(i, j - 1) - return - elif api.GetSelfInfo().playerID == 3: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i, j + 1) in available: - GoTo(i, j + 1) - return + # global fixedclass + # selfInfo = api.GetSelfInfo() + # available = [THUAI6.PlaceType.Land, + # THUAI6.PlaceType.Grass, THUAI6.PlaceType.Door3, THUAI6.PlaceType.Door6, THUAI6.PlaceType.Door5, THUAI6.PlaceType.Gate] + + # def bfs(x, y): + # if api.GetPlaceType(x, y) not in available: + # return [] + + # def GetSuccessors(x, y): + # successors = [] + # if x > 0 and api.GetPlaceType(x - 1, y) in available: + # successors.append((x - 1, y)) + # if x < 49 and api.GetPlaceType(x + 1, y) in available: + # successors.append((x + 1, y)) + # if y > 0 and api.GetPlaceType(x, y - 1) in available: + # successors.append((x, y - 1)) + # if y < 49 and api.GetPlaceType(x, y + 1) in available: + # successors.append((x, y + 1)) + # return successors + # selfX = AssistFunction.GridToCell(api.GetSelfInfo().x) + # selfY = AssistFunction.GridToCell(api.GetSelfInfo().y) + # frontier = queue.Queue() + # frontier.put((selfX, selfY, [])) + # visited = [] + # while not frontier.empty(): + # currentX, currentY, path = frontier.get() + # if currentX == x and currentY == y: + # return path + # for nextX, nextY in GetSuccessors(currentX, currentY): + # if (nextX, nextY) not in visited: + # visited.append((nextX, nextY)) + # frontier.put((nextX, nextY, path + [(nextX, nextY)])) + # return [] + + # def GoTo(x, y): + # global path, cur + # if path != [] and cur < len(path): + # selfX = api.GetSelfInfo().x + # selfY = api.GetSelfInfo().y + # nextX, nextY = path[cur] + # nextX = AssistFunction.CellToGrid(nextX) + # nextY = AssistFunction.CellToGrid(nextY) + # if selfX < nextX - 100: + # api.MoveDown(10) + # time.sleep(0.01) + # return + # if selfX > nextX + 100: + # api.MoveUp(10) + # time.sleep(0.01) + # return + # if selfY < nextY - 100: + # api.MoveRight(10) + # time.sleep(0.01) + # return + # if selfY > nextY + 100: + # api.MoveLeft(10) + # time.sleep(0.01) + # return + # cur += 1 + # return + # else: + # path = bfs(x, y) + # cur = 0 + # return + + # if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) < 18000: + # api.StartOpenGate() + # return + + # if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) >= 18000: + # api.Graduate() + # return + + # if len(fixedclass) == 7: + # GoTo(6, 6) + # return + + # if api.GetPlaceType(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) == THUAI6.PlaceType.ClassRoom: + # api.Print("Trying to fix!") + # if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: + # api.StartLearning() + # return + # else: + # if (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) not in fixedclass: + # fixedclass.append( + # (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) + + # for i in range(50): + # for j in range(50): + # if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + # if api.GetPlaceType(i - 1, j) in available: + # GoTo(i - 1, j) + # return + api.PrintTricker() def TrickerPlay(self, api: ITrickerAPI) -> None: return diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index ec9d559..71f549e 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -358,6 +358,8 @@ class Logic(ILogic): self.__logger.debug("Add Student!") for item in message.obj_message: if item.WhichOneof("message_of_obj") == "tricker_message": + if MessageType.TRICKER_INVISIBLE in item.tricker_message.buff: + continue if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.tricker_message.x, item.tricker_message.y, self.__bufferState.gameMap): self.__bufferState.trickers.append( Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message)) @@ -450,6 +452,8 @@ class Logic(ILogic): self.__logger.debug("Add Tricker!") for item in message.obj_message: if item.WhichOneof("message_of_obj") == "student_message": + if MessageType.STUDENT_INVISIBLE in item.student_message.buff: + continue if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.student_message.x, item.student_message.y, self.__bufferState.gameMap): self.__bufferState.students.append( Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)) From 53c16d4f815b61106f694c55ac5b47de63ee64cd Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sun, 9 Apr 2023 14:44:19 +0800 Subject: [PATCH 10/37] fix: :bug: fix the addition of Buff --- CAPI/cpp/API/include/API.h | 3 --- logic/.gitignore | 2 ++ logic/GameClass/GameObj/Character/Character.cs | 6 ++++++ logic/Gaming/CharacterManager .cs | 2 +- logic/规则Logic.md | 3 +++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CAPI/cpp/API/include/API.h b/CAPI/cpp/API/include/API.h index d51092c..c4516df 100644 --- a/CAPI/cpp/API/include/API.h +++ b/CAPI/cpp/API/include/API.h @@ -127,12 +127,9 @@ public: // 获取视野内可见的道具信息 [[nodiscard]] virtual std::vector> GetProps() const = 0; -<<<<<<< HEAD -======= // 获取视野内可见的子弹信息 [[nodiscard]] virtual std::vector> GetBullets() const = 0; ->>>>>>> 413ef5584c0bd44e1399284a775da492adf98475 [[nodiscard]] virtual std::vector> GetFullMap() const = 0; [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; diff --git a/logic/.gitignore b/logic/.gitignore index a9bdd24..2694985 100644 --- a/logic/.gitignore +++ b/logic/.gitignore @@ -400,3 +400,5 @@ FodyWeavers.xsd #THUAI playback file *.thuaipb +#private cmd +cmd/gameServerOfSanford.cmd \ No newline at end of file diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index a91c30d..78e81a4 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -521,6 +521,12 @@ namespace GameClass.GameObj return this.HasShield; case BuffType.AddLife: return this.HasLIFE; + case BuffType.AddAp: + return this.HasAp; + case BuffType.Clairaudience: + return this.HasClairaudience; + case BuffType.Invisible: + return this.HasInvisible; default: return false; } diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index ce867fc..8ec3d2c 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -292,6 +292,7 @@ namespace Gaming { ((WriteAnswers)student.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0; } + student.SetDegreeOfTreatment0(); #if DEBUG Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString()); #endif @@ -328,7 +329,6 @@ namespace Gaming bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp)); bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); } - student.SetDegreeOfTreatment0(); if (student.HP <= 0) student.TryActivatingLIFE(); // 如果有复活甲 diff --git a/logic/规则Logic.md b/logic/规则Logic.md index edf39c2..7f9bbe0 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -113,6 +113,7 @@ `std::vector> GetFullMap() const`:返回整张地图的地形信息。 - 下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 + `THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 `bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 `int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 @@ -277,7 +278,9 @@ ## 辅助函数 `static inline int CellToGrid(int cell) noexcept`:将地图格数 cell 转换为绝对坐标grid。 + `static inline int GridToCell(int grid) noexcept`:将绝对坐标 grid 转换为地图格数cell。 + 下面为用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 ~~~c void Print(std::string str) const; From d9f152679a72030cd4a100124eccf8d977083a06 Mon Sep 17 00:00:00 2001 From: gsy1519 <614054460@qq.com> Date: Sun, 9 Apr 2023 17:22:37 +0800 Subject: [PATCH 11/37] fix: :zap: improve message writer --- playback/Playback/MessageWriter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/playback/Playback/MessageWriter.cs b/playback/Playback/MessageWriter.cs index a23d701..d38d65f 100644 --- a/playback/Playback/MessageWriter.cs +++ b/playback/Playback/MessageWriter.cs @@ -50,6 +50,7 @@ namespace Playback { cos.Flush(); gzs.Write(ms.GetBuffer(), 0, (int)ms.Length); + gzs.Flush(); ClearMemoryStream(ms); fs.Flush(); } From db9f11dc0bf0dd6c52dd04d126b498327783e45f Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Mon, 10 Apr 2023 15:39:31 +0800 Subject: [PATCH 12/37] perf: :zap: add whatInteractingWith to make a great optimization --- .../GameClass/GameObj/Character/Character.cs | 55 +++++++++------ logic/GameClass/GameObj/Map/Chest.cs | 27 ++++--- logic/Gaming/ActionManager.cs | 70 ++++++++----------- logic/Gaming/AttackManager.cs | 4 +- logic/Gaming/CharacterManager .cs | 10 +-- logic/Gaming/PropManager.cs | 2 +- .../SkillManager/SkillManager.ActiveSkill.cs | 27 ++++++- logic/Preparation/Interface/ICharacter.cs | 2 +- logic/Preparation/Interface/IOccupation.cs | 31 ++++++++ logic/Preparation/Interface/ISkill.cs | 19 ++++- logic/Preparation/Utility/EnumType.cs | 1 + logic/Server/CopyInfo.cs | 10 +-- logic/Server/GameServer.cs | 13 ++-- logic/规则Logic.md | 36 +++++----- 14 files changed, 191 insertions(+), 116 deletions(-) diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 78e81a4..7340b4f 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -300,14 +300,6 @@ namespace GameClass.GameObj if (playerState == PlayerStateType.Null && IsMoving) return PlayerStateType.Moving; return playerState; } - set - { - if (value != PlayerStateType.Moving) - lock (gameObjLock) - IsMoving = false; - - lock (gameObjLock) playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; - } } public bool NoHp() => (playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped @@ -323,6 +315,38 @@ namespace GameClass.GameObj || playerState == PlayerStateType.Treated || playerState == PlayerStateType.Stunned || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); + private GameObj? whatInteractingWith = null; + public GameObj? WhatInteractingWith => whatInteractingWith; + + public void SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + { + lock (gameObjLock) + { + switch (playerState) + { + case PlayerStateType.OpeningTheChest: + ((Chest)whatInteractingWith).StopOpen(); + break; + default: + break; + } + whatInteractingWith = gameObj; + if (value != PlayerStateType.Moving) + IsMoving = false; + playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; + //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); + } + } + + public void SetPlayerStateNaturally() + { + lock (gameObjLock) + { + whatInteractingWith = null; + playerState = PlayerStateType.Null; + } + } + private int score = 0; public int Score { @@ -382,21 +406,6 @@ namespace GameClass.GameObj } } } - /// - /// 角色携带的信息 - /// - private string message = "THUAI6"; - public string Message - { - get => message; - set - { - lock (gameObjLock) - { - message = value; - } - } - } #region 道具和buff相关属性、方法 private Prop[] propInventory = new Prop[GameData.maxNumOfPropInPropInventory] diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs index 23ee8d0..23d9571 100644 --- a/logic/GameClass/GameObj/Map/Chest.cs +++ b/logic/GameClass/GameObj/Map/Chest.cs @@ -20,20 +20,25 @@ namespace GameClass.GameObj private Prop[] propInChest = new Prop[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() }; public Prop[] PropInChest => propInChest; - private int openDegree = 0; - public int OpenDegree + private int openStartTime = 0; + public int OpenStartTime => openStartTime; + private Character? whoOpen = null; + public Character? WhoOpen => whoOpen; + public void Open(int startTime, Character character) { - get => openDegree; - set + lock (gameObjLock) { - if (value > 0) - lock (gameObjLock) - openDegree = (value > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : value; - else - lock (gameObjLock) - openDegree = 0; + openStartTime = startTime; + whoOpen = character; + } + } + public void StopOpen() + { + lock (gameObjLock) + { + openStartTime = 0; + whoOpen = null; } } - public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedChest); } } diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 875d1fd..a58efee 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -38,7 +38,7 @@ namespace Gaming public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { if (!playerToMove.Commandable()) return false; - playerToMove.PlayerState = PlayerStateType.Moving; + playerToMove.SetPlayerState(PlayerStateType.Moving); moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); return true; } @@ -47,7 +47,7 @@ namespace Gaming { if (player.Commandable()) { - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); return true; } return false; @@ -63,7 +63,7 @@ namespace Gaming return false; ++generatorForFix.NumOfFixing; - player.PlayerState = PlayerStateType.Fixing; + player.SetPlayerState(PlayerStateType.Fixing); new Thread ( () => @@ -74,7 +74,7 @@ namespace Gaming { if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) { - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); gameMap.NumOfRepairedGenerators++; } }, @@ -99,7 +99,7 @@ namespace Gaming if (doorwayToOpen == null || doorwayToOpen.IsOpening || !doorwayToOpen.PowerSupply) return false; - player.PlayerState = PlayerStateType.OpeningTheDoorway; + player.SetPlayerState(PlayerStateType.OpeningTheDoorway); doorwayToOpen.IsOpening = true; new Thread ( @@ -120,7 +120,7 @@ namespace Gaming if (doorwayToOpen.OpenDegree >= GameData.degreeOfOpenedDoorway) { if (player.PlayerState == PlayerStateType.OpeningTheDoorway) - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); } } @@ -163,7 +163,7 @@ namespace Gaming playerTreated = gameMap.StudentForInteract(player.Position); if (playerTreated == null) return false; } - if (player == playerTreated || (!player.Commandable()) || player.PlayerState == PlayerStateType.Treating || + if (player == playerTreated || (!player.Commandable()) || playerTreated.PlayerState == PlayerStateType.Treated || (!playerTreated.Commandable()) || playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position)) return false; @@ -172,22 +172,22 @@ namespace Gaming ( () => { - playerTreated.PlayerState = PlayerStateType.Treated; - player.PlayerState = PlayerStateType.Treating; + playerTreated.SetPlayerState(PlayerStateType.Treated); + player.SetPlayerState(PlayerStateType.Treating); new FrameRateTaskExecutor( loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming, loopToDo: () => { if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) - playerTreated.PlayerState = PlayerStateType.Null; + playerTreated.SetPlayerState(); }, timeInterval: GameData.frameDuration, finallyReturn: () => 0 ) .Start(); - if (player.PlayerState == PlayerStateType.Treating) player.PlayerState = PlayerStateType.Null; - else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.PlayerState = PlayerStateType.Null; + if (player.PlayerState == PlayerStateType.Treating) player.SetPlayerState(); + else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.SetPlayerState(); } ) { IsBackground = true }.Start(); @@ -200,11 +200,10 @@ namespace Gaming playerRescued = gameMap.StudentForInteract(player.Position); if (playerRescued == null) return false; } - if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || player == playerRescued - || !GameData.ApproachToInteract(playerRescued.Position, player.Position) || playerRescued.TimeOfRescue > 0) + if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) return false; - player.PlayerState = PlayerStateType.Rescuing; - playerRescued.PlayerState = PlayerStateType.Rescued; + player.SetPlayerState(PlayerStateType.Rescuing); + playerRescued.SetPlayerState(PlayerStateType.Rescued); new Thread ( @@ -226,14 +225,14 @@ namespace Gaming { if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue) { - playerRescued.PlayerState = PlayerStateType.Null; + playerRescued.SetPlayerState(); playerRescued.HP = playerRescued.MaxHp / 2; player.AddScore(GameData.StudentScoreRescue); } else - playerRescued.PlayerState = PlayerStateType.Addicted; + playerRescued.SetPlayerState(PlayerStateType.Addicted); } - if (player.PlayerState == PlayerStateType.Rescuing) player.PlayerState = PlayerStateType.Null; + if (player.PlayerState == PlayerStateType.Rescuing) player.SetPlayerState(); playerRescued.TimeOfRescue = 0; } ) @@ -247,30 +246,21 @@ namespace Gaming return false; Chest? chestToOpen = (Chest?)gameMap.OneForInteract(player.Position, GameObjType.Chest); - if (chestToOpen == null || chestToOpen.OpenDegree > 0) + if (chestToOpen == null || chestToOpen.OpenStartTime > 0) return false; - player.PlayerState = PlayerStateType.OpeningTheChest; + player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen); + int startTime = gameMap.Timer.nowTime(); + chestToOpen.Open(startTime, player); new Thread ( () => { - new FrameRateTaskExecutor( - loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheChest && gameMap.Timer.IsGaming && (!chestToOpen.IsOpen()), - loopToDo: () => - { - chestToOpen.OpenDegree += GameData.frameDuration * player.SpeedOfOpenChest; - }, - timeInterval: GameData.frameDuration, - finallyReturn: () => 0 - ) + Thread.Sleep(GameData.degreeOfOpenedChest / player.SpeedOfOpenChest); - .Start(); - - if (chestToOpen.IsOpen()) + if (chestToOpen.OpenStartTime == startTime) { - if (player.PlayerState == PlayerStateType.OpeningTheChest) - player.PlayerState = PlayerStateType.Null; + player.SetPlayerStateNaturally(); for (int i = 0; i < GameData.maxNumOfPropInChest; ++i) { Prop prop = chestToOpen.PropInChest[i]; @@ -279,8 +269,6 @@ namespace Gaming gameMap.Add(prop); } } - else chestToOpen.OpenDegree = 0; - } ) @@ -312,7 +300,7 @@ namespace Gaming //Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer); // gameMap.Add(addWall); - player.PlayerState = PlayerStateType.ClimbingThroughWindows; + player.SetPlayerState(PlayerStateType.ClimbingThroughWindows); windowForClimb.WhoIsClimbing = player; new Thread ( @@ -354,7 +342,7 @@ namespace Gaming // gameMap.Remove(addWall); if (player.PlayerState == PlayerStateType.ClimbingThroughWindows) { - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); } } @@ -394,7 +382,7 @@ namespace Gaming } if (!flag) return false; - player.PlayerState = PlayerStateType.LockingOrOpeningTheDoor; + player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor); new Thread ( () => @@ -417,7 +405,7 @@ namespace Gaming doorToLock.IsOpen = (!doorToLock.IsOpen); } if (player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor) - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); doorToLock.OpenOrLockDegree = 0; } diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 1d77685..842d53a 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -174,7 +174,7 @@ namespace Gaming if (bullet.CastTime > 0) { - player.PlayerState = PlayerStateType.TryingToAttack; + player.SetPlayerState(PlayerStateType.TryingToAttack); new Thread (() => @@ -195,7 +195,7 @@ namespace Gaming { if (player.PlayerState == PlayerStateType.TryingToAttack) { - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); } else bullet.IsMoving = false; diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index 8ec3d2c..5d0d062 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -216,7 +216,7 @@ namespace Gaming return; } } - player.PlayerState = PlayerStateType.Addicted; + player.SetPlayerState(PlayerStateType.Addicted); new Thread (() => { @@ -252,10 +252,10 @@ namespace Gaming new Thread (() => { - player.PlayerState = PlayerStateType.Stunned; + player.SetPlayerState(PlayerStateType.Stunned); Thread.Sleep(time); if (player.PlayerState == PlayerStateType.Stunned) - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); } ) { IsBackground = true }.Start(); @@ -341,7 +341,7 @@ namespace Gaming { if (player == null || time <= 0) return false; if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false; - player.PlayerState = PlayerStateType.Swinging; + player.SetPlayerState(PlayerStateType.Swinging); new Thread (() => @@ -350,7 +350,7 @@ namespace Gaming if (player.PlayerState == PlayerStateType.Swinging) { - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); } } ) diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs index ac14bb1..3914b87 100644 --- a/logic/Gaming/PropManager.cs +++ b/logic/Gaming/PropManager.cs @@ -57,7 +57,7 @@ namespace Gaming if (player.PlayerState == PlayerStateType.Stunned) { player.AddScore(GameData.ScorePropRecoverFromDizziness); - player.PlayerState = PlayerStateType.Null; + player.SetPlayerState(); } break; default: diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 2f2f72e..5496e79 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -28,6 +28,31 @@ namespace Gaming { }); } + public static bool ShowTime(Character player) + { + if ((!player.Commandable())) return false; + IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime); + Debugger.Output(player, ": It's show time!"); + + return ActiveSkillEffect(skill, player, () => + { + /* Thread + * new FrameRateTaskExecutor( + loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheChest && gameMap.Timer.IsGaming && (!chestToOpen.IsOpen()), + loopToDo: () => + { + chestToOpen.OpenStartTime += GameData.frameDuration * player.SpeedOfOpenChest; + }, + timeInterval: GameData.frameDuration, + finallyReturn: () => 0 + ) + + .Start();*/ + }, + () => + { }); + } + public static bool BecomeInvisible(Character player) { if ((!player.Commandable())) return false; @@ -180,7 +205,7 @@ namespace Gaming { if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character)) { - character.PlayerState = PlayerStateType.Null; + character.SetPlayerState(); character.HP = GameData.RemainHpWhenAddLife; ((Student)character).TimeOfRescue = 0; player.AddScore(GameData.StudentScoreRescue); diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs index c4b175c..5975b8c 100644 --- a/logic/Preparation/Interface/ICharacter.cs +++ b/logic/Preparation/Interface/ICharacter.cs @@ -10,7 +10,7 @@ namespace Preparation.Interface public int Score { get; } public void AddScore(int add); public double Vampire { get; } - public PlayerStateType PlayerState { get; set; } + public PlayerStateType PlayerState { get; } public BulletType BulletOfPlayer { get; set; } public bool IsGhost(); diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs index 3e3eb70..b37bda6 100644 --- a/logic/Preparation/Interface/IOccupation.cs +++ b/logic/Preparation/Interface/IOccupation.cs @@ -91,6 +91,37 @@ namespace Preparation.Interface public int speedOfOpenChest = (int)(GameData.basicSpeedOfOpenChest * 1.1); public int SpeedOfOpenChest => speedOfOpenChest; } + public class Idol : IGhostType + { + private const int moveSpeed = GameData.basicGhostMoveSpeed; + public int MoveSpeed => moveSpeed; + + private const int maxHp = GameData.basicHp; + public int MaxHp => maxHp; + + public BulletType InitBullet => BulletType.CommonAttackOfGhost; + + public List ListOfIActiveSkill => new(new ActiveSkillType[] { }); + public List ListOfIPassiveSkill => new(new PassiveSkillType[] { }); + + public double concealment = GameData.basicConcealment; + public double Concealment => concealment; + + public int alertnessRadius = GameData.basicGhostAlertnessRadius; + public int AlertnessRadius => alertnessRadius; + + public int viewRange = GameData.basicGhostViewRange * 11 / 10; + public int ViewRange => viewRange; + + public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; + public int SpeedOfOpeningOrLocking => speedOfOpeningOrLocking; + + public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows; + public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; + + public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; + public int SpeedOfOpenChest => speedOfOpenChest; + } public class ANoisyPerson : IGhostType { private const int moveSpeed = (int)(GameData.basicGhostMoveSpeed * 1.07); diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index f0a16f6..04950e8 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -33,7 +33,7 @@ namespace Preparation.Interface public class BecomeInvisible : IActiveSkill { - public int SkillCD => GameData.commonSkillCD; + public int SkillCD => GameData.commonSkillCD * 2; public int DurationTime => GameData.commonSkillTime * 6 / 10; private readonly object commonSkillLock = new object(); @@ -121,6 +121,21 @@ namespace Preparation.Interface } } + public class ShowTime : IActiveSkill + { + public int SkillCD => GameData.commonSkillCD * 3; + public int DurationTime => GameData.commonSkillTime; + + private readonly object commonSkillLock = new object(); + public object ActiveSkillLock => commonSkillLock; + + public bool isBeingUsed = false; + public bool IsBeingUsed + { + get => isBeingUsed; set => isBeingUsed = value; + } + } + public class JumpyBomb : IActiveSkill { public int SkillCD => GameData.commonSkillCD / 2; @@ -137,7 +152,7 @@ namespace Preparation.Interface public class UseKnife : IActiveSkill { - public int SkillCD => GameData.commonSkillCD * 2 / 3; + public int SkillCD => GameData.commonSkillCD; public int DurationTime => GameData.commonSkillTime / 10; private readonly object commonSkillLock = new object(); public object ActiveSkillLock => commonSkillLock; diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index cbc4028..fc9b4d7 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -100,6 +100,7 @@ namespace Preparation.Utility Rouse = 11, Encourage = 12, Inspire = 13, + ShowTime = 14, } public enum PassiveSkillType { diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index 8cf0a76..a192063 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using GameClass.GameObj; using System.Numerics; using Preparation.Utility; +using Gaming; namespace Server { public static class CopyInfo { - public static MessageOfObj? Auto(GameObj gameObj) + public static MessageOfObj? Auto(GameObj gameObj, int time) { switch (gameObj.Type) { @@ -29,7 +30,7 @@ namespace Server case Preparation.Utility.GameObjType.Generator: return Classroom((Generator)gameObj); case Preparation.Utility.GameObjType.Chest: - return Chest((Chest)gameObj); + return Chest((Chest)gameObj, time); case Preparation.Utility.GameObjType.Doorway: return Gate((Doorway)gameObj); case Preparation.Utility.GameObjType.EmergencyExit: @@ -223,13 +224,14 @@ namespace Server msg.DoorMessage.IsOpen = door.IsOpen; return msg; } - private static MessageOfObj Chest(Chest chest) + private static MessageOfObj Chest(Chest chest, int time) { MessageOfObj msg = new MessageOfObj(); msg.ChestMessage = new(); msg.ChestMessage.X = chest.Position.x; msg.ChestMessage.Y = chest.Position.y; - msg.ChestMessage.Progress = chest.OpenDegree; + int progress = (chest.OpenStartTime > 0) ? ((time - chest.OpenStartTime) * chest.WhoOpen.SpeedOfOpenChest) : 0; + msg.ChestMessage.Progress = (progress > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : progress; return msg; } } diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs index c0a1abf..b997885 100644 --- a/logic/Server/GameServer.cs +++ b/logic/Server/GameServer.cs @@ -135,22 +135,23 @@ namespace Server currentGameInfo.ObjMessage.Add(currentMapMsg); IsSpectatorJoin = false; } + int time = game.GameMap.Timer.nowTime(); foreach (GameObj gameObj in gameObjList) { - MessageOfObj? msg = CopyInfo.Auto(gameObj); - if (msg != null) currentGameInfo.ObjMessage.Add(CopyInfo.Auto(gameObj)); + MessageOfObj? msg = CopyInfo.Auto(gameObj, time); + if (msg != null) currentGameInfo.ObjMessage.Add(msg); } lock (newsLock) { foreach (var news in currentNews) { MessageOfObj? msg = CopyInfo.Auto(news); - if (msg != null) currentGameInfo.ObjMessage.Add(CopyInfo.Auto(news)); + if (msg != null) currentGameInfo.ObjMessage.Add(msg); } currentNews.Clear(); } currentGameInfo.GameState = gameState; - currentGameInfo.AllMessage = GetMessageOfAll(); + currentGameInfo.AllMessage = GetMessageOfAll(time); mwr?.WriteOne(currentGameInfo); break; default: @@ -211,10 +212,10 @@ namespace Server return false; } - private MessageOfAll GetMessageOfAll() + private MessageOfAll GetMessageOfAll(int time) { MessageOfAll msg = new MessageOfAll(); - msg.GameTime = game.GameMap.Timer.nowTime(); + msg.GameTime = time; msg.SubjectFinished = (int)game.GameMap.NumOfRepairedGenerators; msg.StudentGraduated = (int)game.GameMap.NumOfEscapedStudent; msg.StudentQuited = (int)game.GameMap.NumOfDeceasedStudent; diff --git a/logic/规则Logic.md b/logic/规则Logic.md index 7f9bbe0..af2fc86 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -8,10 +8,10 @@ - **极坐标以x坐标轴为极轴,角度逆时针为正方向**。 - 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到: - 略 -- 地图上的每个格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 +- 地图上格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 ### 移动 -- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动的方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴** +- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴** ### 使用技能 - `std::future UseSkill(int32_t skillID)`:使用对应序号的主动技能 @@ -20,6 +20,7 @@ - 人物半径为800 - 人物共有17种不可叠加的状态: 1. (可)移动状态 +- `std::future EndAllAction()`:可以使处在下者八项状态中的玩家终止交互 2. 学习 3. 被勉励 4. 在勉励 @@ -28,7 +29,7 @@ 7. 使用技能 8. 开启校门 9. 唤醒他人中 - +- 之后八项为不可行动状态 10. 被唤醒中 11. 沉迷 12. 退学 @@ -38,9 +39,6 @@ 16. 后摇 17. 翻窗 -- 其中后8项为不可行动状态 -- `std::future EndAllAction()`:可以使处在2-9状态的玩家终止对应交互,对于后8项状态无效 - ### 攻击 - `std::future Attack(double angleInRadian)`:`angleInRadian`为攻击方向,无论近战远程均产生bullet表示攻击 - 攻击类型CommonAttackOfGhost攻击未写完的作业,会造成对应攻击力的损坏 @@ -67,17 +65,17 @@ - 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。 - `std::future StartLearning()`:在教室(旁)做作业 - `std::future StartOpenGate()`:开启校门,所需时间为18秒,开启的进度不清空 -- 隐藏校门会在**3间**教室的作业完成的情况下在3-5个隐藏校门刷新点之一随机显现,当学生只剩1名时,隐藏校门将会自动打开。 +- 当**3间**教室的作业完成时,隐藏校门在3-5个刷新点之一随机显现;当只剩1名学生时,隐藏校门自动打开。 - `std::future Graduate()`:从开启的校门或隐藏校门毕业。 #### 勉励(Treat) -- `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大血量与当前血量的差值时,勉励结束。 +- `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。 - 勉励中断时,被勉励程度保留;遭到攻击时被勉励程度清空 #### 沉迷与唤醒 -- 当学生血量归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 -- `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后血量恢复至1/2。沉迷程度不清空。 -- 进入沉迷状态时。如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; +- 当学生学习毅力归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 +- `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。 +- 进入沉迷状态时,如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; - 当学生沉迷程度达到其最大沉迷程度时,从游戏中出局 #### 门 @@ -99,12 +97,12 @@ 3. 学习的声音: 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 ### 队内信息 -- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。`toPlayerID`指定发送的对象,`message`指定发送的内容。`message`的长度不能超过 64,否则将发送失败! +- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。第一个参数指定发送的对象,第二个参数指定发送的内容。 - `bool HaveMessage()`:是否有队友发来的尚未接收的信息。 +- `std::pair GetMessage()`:从玩家ID为第一个参数的队友获取信息。 -### 信息受限 -- 主动行为每 50ms 最多总共可以调用 50 次; -- `bool Wait()`:asynchronous 为 true 的情况下,选手可以调用此函数,阻塞当前线程,直到下一次消息更新时继续运行。 +### 线程控制 +- `bool Wait()`:阻塞当前线程,直到下一次消息更新时继续运行。 ### 信息获取 `std::vector> GetStudents() const` :返回所有可视学生的信息。 @@ -189,11 +187,11 @@ - 普通攻击为 搞蛋鬼的一般攻击 - 主动技能 - 隐身 - - CD:30s 持续时间:6s + - CD:60s 持续时间:6s - 在持续时间内玩家隐身 - 使用瞬间得分 - 使用飞刀 - - CD:20s 持续时间:1s + - CD:30s 持续时间:1s - 在持续时间内,攻击类型变为飞刀 - 不直接得分 @@ -412,14 +410,14 @@ public: ### 交互 - 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 - - 实际上救援或勉励不同的人是有效的 + - 实际上唤醒或勉励不同的人是有效的 ### 破译与逃脱 - 隐藏校门与校门对于人有碰撞体积 - 一个校门同时最多可以由一人开启 ### 攻击 -- 每次学生受到攻击后会损失对应子弹的攻击力的血量 +- 每次学生受到攻击后会损失对应子弹的攻击力的学习毅力 - 前摇期间攻击被打断时,子弹消失。 - 此处,前摇指 从播放攻击动作开始 攻击者不能交互 的时间 From 6ba64b08fe69b249b37fcbe6e4870104622a0ded Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Tue, 11 Apr 2023 00:42:31 +0800 Subject: [PATCH 13/37] perf: :lock: add a limit of call the Stop or Move fuction --- logic/Gaming/ActionManager.cs | 33 ++++++++++++++++++++++++--- logic/Gaming/Game.cs | 2 +- logic/Preparation/Utility/GameData.cs | 2 ++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index a58efee..5fe6ed0 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -37,15 +37,15 @@ namespace Gaming } public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { - if (!playerToMove.Commandable()) return false; + if (!playerToMove.Commandable() || !TryToStop()) return false; playerToMove.SetPlayerState(PlayerStateType.Moving); moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); return true; } - public static bool Stop(Character player) + public bool Stop(Character player) { - if (player.Commandable()) + if (player.Commandable() || !TryToStop()) { player.SetPlayerState(); return true; @@ -437,6 +437,33 @@ namespace Gaming } } */ + private object numLock = new object(); + private int lastTime = 0; + private int numStop = 0; + private int NumStop => numStop; + private bool TryToStop() + { + lock (numLock) + { + int time = gameMap.Timer.nowTime(); + if (time / GameData.frameDuration > lastTime) + { + lastTime = time / GameData.frameDuration; + numStop = 1; + return true; + } + else + { + if (numStop == GameData.LimitOfStopAndMove) + return false; + else + { + ++numStop; + return true; + } + } + } + } private readonly Map gameMap; private readonly CharacterManager characterManager; diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 65d0d6d..6575102 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -167,7 +167,7 @@ namespace Gaming Character? player = gameMap.FindPlayerToAction(playerID); if (player != null) { - return ActionManager.Stop(player); + return actionManager.Stop(player); } return false; } diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index c37c7f5..70d634a 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -15,6 +15,8 @@ namespace Preparation.Utility public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长 public const long gameDuration = 600000; // 游戏时长600000ms = 10min + public const int LimitOfStopAndMove = 15; + public const int MinSpeed = 1; // 最小速度 public const int MaxSpeed = int.MaxValue; // 最大速度 From c29ede31309a86711d7430b272db5656b4e63319 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Tue, 11 Apr 2023 10:47:56 +0800 Subject: [PATCH 14/37] perf: :zap: adjust the structure --- .../GameClass/GameObj/Character/Character.cs | 10 +-- logic/GameClass/GameObj/Map/Doorway.cs | 10 +-- logic/Gaming/ActionManager.cs | 68 ++++++++----------- logic/Gaming/AttackManager.cs | 12 ++-- logic/Gaming/CharacterManager .cs | 32 ++++++--- logic/Gaming/Game.cs | 4 +- logic/Gaming/PropManager.cs | 9 +-- .../SkillManager/SkillManager.ActiveSkill.cs | 8 +-- logic/Server/CopyInfo.cs | 7 +- logic/规则Logic.md | 3 +- 10 files changed, 82 insertions(+), 81 deletions(-) diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 7340b4f..dae9be8 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -318,18 +318,10 @@ namespace GameClass.GameObj private GameObj? whatInteractingWith = null; public GameObj? WhatInteractingWith => whatInteractingWith; - public void SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + public void ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) { lock (gameObjLock) { - switch (playerState) - { - case PlayerStateType.OpeningTheChest: - ((Chest)whatInteractingWith).StopOpen(); - break; - default: - break; - } whatInteractingWith = gameObj; if (value != PlayerStateType.Moving) IsMoving = false; diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs index 6bb2f00..cff420b 100644 --- a/logic/GameClass/GameObj/Map/Doorway.cs +++ b/logic/GameClass/GameObj/Map/Doorway.cs @@ -35,14 +35,14 @@ namespace GameClass.GameObj } } - private bool isOpening = false; - public bool IsOpening + private int openStartTime = 0; + public int OpenStartTime { - get => isOpening; + get => openStartTime; set { lock (gameObjLock) - isOpening = value; + openStartTime = value; } } @@ -61,6 +61,6 @@ namespace GameClass.GameObj } } - public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway); + public bool IsOpen() => (openDegree == GameData.degreeOfOpenedDoorway); } } diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 5fe6ed0..6c162a7 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -23,22 +23,22 @@ namespace Gaming { if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) { - if (CharacterManager.BeStunned((Character)player, GameData.TimeOfStunnedWhenJumpyDumpty)) + if (characterManager.BeStunned((Character)player, GameData.TimeOfStunnedWhenJumpyDumpty)) player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStunnedWhenJumpyDumpty)); gameMap.Remove((GameObj)collisionObj); } } if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) { - if (CharacterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) + if (characterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenCharge)); - CharacterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge); + characterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge); } } public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { if (!playerToMove.Commandable() || !TryToStop()) return false; - playerToMove.SetPlayerState(PlayerStateType.Moving); + characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving); moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); return true; } @@ -47,7 +47,7 @@ namespace Gaming { if (player.Commandable() || !TryToStop()) { - player.SetPlayerState(); + characterManager.SetPlayerState(player); return true; } return false; @@ -63,7 +63,7 @@ namespace Gaming return false; ++generatorForFix.NumOfFixing; - player.SetPlayerState(PlayerStateType.Fixing); + characterManager.SetPlayerState(player, PlayerStateType.Fixing); new Thread ( () => @@ -74,7 +74,7 @@ namespace Gaming { if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) { - player.SetPlayerState(); + characterManager.SetPlayerState(player); gameMap.NumOfRepairedGenerators++; } }, @@ -96,31 +96,21 @@ namespace Gaming if (!(player.Commandable()) || player.PlayerState == PlayerStateType.OpeningTheDoorway) return false; Doorway? doorwayToOpen = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); - if (doorwayToOpen == null || doorwayToOpen.IsOpening || !doorwayToOpen.PowerSupply) + if (doorwayToOpen == null || doorwayToOpen.OpenStartTime > 0 || !doorwayToOpen.PowerSupply) return false; - player.SetPlayerState(PlayerStateType.OpeningTheDoorway); - doorwayToOpen.IsOpening = true; + characterManager.SetPlayerState(player, PlayerStateType.OpeningTheDoorway, doorwayToOpen); + int startTime = doorwayToOpen.OpenStartTime = gameMap.Timer.nowTime(); new Thread ( () => { - new FrameRateTaskExecutor( - loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheDoorway && gameMap.Timer.IsGaming && doorwayToOpen.OpenDegree < GameData.degreeOfOpenedDoorway, - loopToDo: () => - { - doorwayToOpen.OpenDegree += GameData.frameDuration; - }, - timeInterval: GameData.frameDuration, - finallyReturn: () => 0 - ) + Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree); - .Start(); - doorwayToOpen.IsOpening = false; - if (doorwayToOpen.OpenDegree >= GameData.degreeOfOpenedDoorway) + if (doorwayToOpen.OpenStartTime == startTime) { - if (player.PlayerState == PlayerStateType.OpeningTheDoorway) - player.SetPlayerState(); + doorwayToOpen.OpenDegree = GameData.degreeOfOpenedDoorway; + player.SetPlayerStateNaturally(); } } @@ -172,22 +162,22 @@ namespace Gaming ( () => { - playerTreated.SetPlayerState(PlayerStateType.Treated); - player.SetPlayerState(PlayerStateType.Treating); + characterManager.SetPlayerState(player, PlayerStateType.Treated); + characterManager.SetPlayerState(player, PlayerStateType.Treating); new FrameRateTaskExecutor( loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming, loopToDo: () => { if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) - playerTreated.SetPlayerState(); + characterManager.SetPlayerState(playerTreated); }, timeInterval: GameData.frameDuration, finallyReturn: () => 0 ) .Start(); - if (player.PlayerState == PlayerStateType.Treating) player.SetPlayerState(); - else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.SetPlayerState(); + if (player.PlayerState == PlayerStateType.Treating) characterManager.SetPlayerState(player); + else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated); } ) { IsBackground = true }.Start(); @@ -202,8 +192,8 @@ namespace Gaming } if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) return false; - player.SetPlayerState(PlayerStateType.Rescuing); - playerRescued.SetPlayerState(PlayerStateType.Rescued); + characterManager.SetPlayerState(player, PlayerStateType.Rescuing); + characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued); new Thread ( @@ -225,14 +215,14 @@ namespace Gaming { if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue) { - playerRescued.SetPlayerState(); + characterManager.SetPlayerState(playerRescued); playerRescued.HP = playerRescued.MaxHp / 2; player.AddScore(GameData.StudentScoreRescue); } else - playerRescued.SetPlayerState(PlayerStateType.Addicted); + characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted); } - if (player.PlayerState == PlayerStateType.Rescuing) player.SetPlayerState(); + if (player.PlayerState == PlayerStateType.Rescuing) characterManager.SetPlayerState(player); playerRescued.TimeOfRescue = 0; } ) @@ -249,7 +239,7 @@ namespace Gaming if (chestToOpen == null || chestToOpen.OpenStartTime > 0) return false; - player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen); + characterManager.SetPlayerState(player, PlayerStateType.OpeningTheChest, chestToOpen); int startTime = gameMap.Timer.nowTime(); chestToOpen.Open(startTime, player); new Thread @@ -300,7 +290,7 @@ namespace Gaming //Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer); // gameMap.Add(addWall); - player.SetPlayerState(PlayerStateType.ClimbingThroughWindows); + characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows); windowForClimb.WhoIsClimbing = player; new Thread ( @@ -342,7 +332,7 @@ namespace Gaming // gameMap.Remove(addWall); if (player.PlayerState == PlayerStateType.ClimbingThroughWindows) { - player.SetPlayerState(); + characterManager.SetPlayerState(player); } } @@ -382,7 +372,7 @@ namespace Gaming } if (!flag) return false; - player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor); + characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor); new Thread ( () => @@ -405,7 +395,7 @@ namespace Gaming doorToLock.IsOpen = (!doorToLock.IsOpen); } if (player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor) - player.SetPlayerState(); + characterManager.SetPlayerState(player); doorToLock.OpenOrLockDegree = 0; } diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 842d53a..40995b2 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -81,14 +81,14 @@ namespace Gaming { if (objBeingShot == null) { - CharacterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); + characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); return; } Debugger.Output(bullet, bullet.TypeOfBullet.ToString()); BombObj(bullet, objBeingShot); - CharacterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); + characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); return; } @@ -140,10 +140,10 @@ namespace Gaming if (objBeingShot == null) { - CharacterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); + characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); } else - CharacterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); + characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); } public bool Attack(Character? player, double angle) @@ -174,7 +174,7 @@ namespace Gaming if (bullet.CastTime > 0) { - player.SetPlayerState(PlayerStateType.TryingToAttack); + characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); new Thread (() => @@ -195,7 +195,7 @@ namespace Gaming { if (player.PlayerState == PlayerStateType.TryingToAttack) { - player.SetPlayerState(); + characterManager.SetPlayerState(player); } else bullet.IsMoving = false; diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index 5d0d062..14d84b8 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -7,6 +7,7 @@ using GameEngine; using Preparation.Interface; using Timothy.FrameRateTask; using System.Numerics; +using System.Timers; namespace Gaming { @@ -21,6 +22,21 @@ namespace Gaming this.gameMap = gameMap; } + public void SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + { + switch (player.PlayerState) + { + case PlayerStateType.OpeningTheChest: + ((Chest)player.WhatInteractingWith).StopOpen(); + break; + case PlayerStateType.OpeningTheDoorway: + ((Doorway)player.WhatInteractingWith).OpenDegree += gameMap.Timer.nowTime() - ((Doorway)player.WhatInteractingWith).OpenStartTime; + break; + default: + break; + } + player.ChangePlayerState(value, gameObj); + } public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null) { @@ -216,7 +232,7 @@ namespace Gaming return; } } - player.SetPlayerState(PlayerStateType.Addicted); + SetPlayerState(player, PlayerStateType.Addicted); new Thread (() => { @@ -246,23 +262,23 @@ namespace Gaming { IsBackground = true }.Start(); } - public static bool BeStunned(Character player, int time) + public bool BeStunned(Character player, int time) { if (player.PlayerState == PlayerStateType.Stunned || player.NoHp() || player.CharacterType == CharacterType.Robot) return false; new Thread (() => { - player.SetPlayerState(PlayerStateType.Stunned); + SetPlayerState(player, PlayerStateType.Stunned); Thread.Sleep(time); if (player.PlayerState == PlayerStateType.Stunned) - player.SetPlayerState(); + SetPlayerState(player); } ) { IsBackground = true }.Start(); return true; } - public static bool TryBeAwed(Student character, Bullet bullet) + public bool TryBeAwed(Student character, Bullet bullet) { if (character.CanBeAwed()) { @@ -337,11 +353,11 @@ namespace Gaming else TryBeAwed(student, bullet); } - public static bool BackSwing(Character? player, int time) + public bool BackSwing(Character? player, int time) { if (player == null || time <= 0) return false; if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false; - player.SetPlayerState(PlayerStateType.Swinging); + SetPlayerState(player, PlayerStateType.Swinging); new Thread (() => @@ -350,7 +366,7 @@ namespace Gaming if (player.PlayerState == PlayerStateType.Swinging) { - player.SetPlayerState(); + SetPlayerState(player); } } ) diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 6575102..914fd6d 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -233,7 +233,7 @@ namespace Gaming Character? player = gameMap.FindPlayerToAction(playerID); if (player != null) { - PropManager.UseProp(player, propType); + propManager.UseProp(player, propType); } } public void ThrowProp(long playerID, PropType propType = PropType.Null) @@ -375,7 +375,7 @@ namespace Gaming characterManager = new CharacterManager(gameMap); attackManager = new AttackManager(gameMap, characterManager); actionManager = new ActionManager(gameMap, characterManager); - propManager = new PropManager(gameMap); + propManager = new PropManager(gameMap, characterManager); skillManager = new SkillManager(gameMap, actionManager, attackManager, propManager, characterManager); } } diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs index 3914b87..457ed44 100644 --- a/logic/Gaming/PropManager.cs +++ b/logic/Gaming/PropManager.cs @@ -16,10 +16,10 @@ namespace Gaming private class PropManager { private readonly Map gameMap; - + private readonly CharacterManager characterManager; private readonly List availableCellForGenerateProp; - public static void UseProp(Character player, PropType propType) + public void UseProp(Character player, PropType propType) { if (player.IsResetting || player.CharacterType == CharacterType.Robot) return; @@ -57,7 +57,7 @@ namespace Gaming if (player.PlayerState == PlayerStateType.Stunned) { player.AddScore(GameData.ScorePropRecoverFromDizziness); - player.SetPlayerState(); + player.SetPlayerStateNaturally(); } break; default: @@ -210,8 +210,9 @@ namespace Gaming { IsBackground = true }.Start(); */ } - public PropManager(Map gameMap) // 道具不能扔过墙 + public PropManager(Map gameMap, CharacterManager characterManager) // 道具不能扔过墙 { + this.characterManager = characterManager; this.gameMap = gameMap; /* this.moveEngine = new MoveEngine( gameMap: gameMap, diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 5496e79..afebbd6 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -145,7 +145,7 @@ namespace Gaming { if (!character.IsGhost() && XY.Distance(character.Position, player.Position) <= player.ViewRange) { - if (CharacterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl)) + if (characterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl)) player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStudentFaintingWhenHowl)); break; } @@ -155,7 +155,7 @@ namespace Gaming { gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); } - CharacterManager.BackSwing(player, GameData.TimeOfGhostSwingingAfterHowl); + characterManager.BackSwing(player, GameData.TimeOfGhostSwingingAfterHowl); Debugger.Output(player, "howled!"); }, () => @@ -177,7 +177,7 @@ namespace Gaming || character.PlayerState == PlayerStateType.UsingSkill) && gameMap.CanSee(player, character)) { - if (CharacterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish)) + if (characterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish)) player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish)); break; } @@ -205,7 +205,7 @@ namespace Gaming { if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character)) { - character.SetPlayerState(); + characterManager.SetPlayerState(character); character.HP = GameData.RemainHpWhenAddLife; ((Student)character).TimeOfRescue = 0; player.AddScore(GameData.StudentScoreRescue); diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index a192063..a3409ce 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -32,7 +32,7 @@ namespace Server case Preparation.Utility.GameObjType.Chest: return Chest((Chest)gameObj, time); case Preparation.Utility.GameObjType.Doorway: - return Gate((Doorway)gameObj); + return Gate((Doorway)gameObj, time); case Preparation.Utility.GameObjType.EmergencyExit: if (((EmergencyExit)gameObj).CanOpen) return HiddenGate((EmergencyExit)gameObj); @@ -195,13 +195,14 @@ namespace Server msg.ClassroomMessage.Progress = generator.DegreeOfRepair; return msg; } - private static MessageOfObj Gate(Doorway doorway) + private static MessageOfObj Gate(Doorway doorway, int time) { MessageOfObj msg = new MessageOfObj(); msg.GateMessage = new(); msg.GateMessage.X = doorway.Position.x; msg.GateMessage.Y = doorway.Position.y; - msg.GateMessage.Progress = doorway.OpenDegree; + int progress = ((doorway.OpenStartTime > 0) ? (time - doorway.OpenStartTime) : 0) + doorway.OpenDegree; + msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress; return msg; } private static MessageOfObj HiddenGate(EmergencyExit Exit) diff --git a/logic/规则Logic.md b/logic/规则Logic.md index af2fc86..55456a2 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -252,7 +252,7 @@ - 特性 - 冥想 - 当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为0.3%/ms - - 受到攻击(并非伤害)或眩晕或翻窗(或攻击他人)学习进度清零 + - 受到攻击(并非伤害)或学习或进入不可接受治疗状态(包括翻窗)学习进度清零 - 主动技能5 - 写答案 - CD:30s @@ -401,6 +401,7 @@ public: ### 人物 - 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 +- EndAllAction()及Move指令调用数总和一帧内不超过10次 ### 初始状态 - 玩家出生点固定且一定为空地 From 9f8e93b875cf6c43abc4431f8377087b8347fe42 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Tue, 11 Apr 2023 13:52:39 +0800 Subject: [PATCH 15/37] feat: :sparkles: add a new CharacterType Idol --- dependency/proto/MessageType.proto | 2 +- logic/Client/MainWindow.xaml.cs | 2 +- logic/Client/StatusBarOfHunter.xaml.cs | 4 +- logic/Gaming/ActionManager.cs | 2 +- logic/Gaming/CharacterManager .cs | 4 +- .../SkillManager/SkillManager.ActiveSkill.cs | 51 ++-- logic/Gaming/SkillManager/SkillManager.cs | 3 + logic/Preparation/Interface/IOccupation.cs | 6 +- logic/Preparation/Interface/ISkill.cs | 6 +- logic/Preparation/Utility/EnumType.cs | 1 + logic/Preparation/Utility/GameData.cs | 1 + logic/Preparation/Utility/Transformation.cs | 4 + logic/Preparation/Utility/XY.cs | 5 +- logic/Server/CopyInfo.cs | 232 ++++++++++-------- 14 files changed, 200 insertions(+), 123 deletions(-) diff --git a/dependency/proto/MessageType.proto b/dependency/proto/MessageType.proto index 28d3be8..5cc801e 100755 --- a/dependency/proto/MessageType.proto +++ b/dependency/proto/MessageType.proto @@ -118,7 +118,7 @@ enum TrickerType ASSASSIN = 1; KLEE = 2; A_NOISY_PERSON = 3; - TRICKERTYPE4 = 4; + IDOL = 4; } // 游戏进行状态 diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index c115e6e..3c437a8 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -241,7 +241,7 @@ namespace Client playerMsg.TrickerType = TrickerType.ANoisyPerson; break; case 4: - playerMsg.TrickerType = TrickerType._4; + playerMsg.TrickerType = TrickerType.Idol; break; case 0: default: diff --git a/logic/Client/StatusBarOfHunter.xaml.cs b/logic/Client/StatusBarOfHunter.xaml.cs index b4c4add..358db47 100644 --- a/logic/Client/StatusBarOfHunter.xaml.cs +++ b/logic/Client/StatusBarOfHunter.xaml.cs @@ -49,8 +49,8 @@ namespace Client case TrickerType.ANoisyPerson: serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nANoisyPerson"; break; - case TrickerType._4: - serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nTrickerType4"; + case TrickerType.Idol: + serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nIdol"; break; case TrickerType.NullTrickerType: serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nNullTrickerType"; diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 6c162a7..a4fcbd4 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -162,7 +162,7 @@ namespace Gaming ( () => { - characterManager.SetPlayerState(player, PlayerStateType.Treated); + characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated); characterManager.SetPlayerState(player, PlayerStateType.Treating); new FrameRateTaskExecutor( loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming, diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index 14d84b8..0626679 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -30,7 +30,9 @@ namespace Gaming ((Chest)player.WhatInteractingWith).StopOpen(); break; case PlayerStateType.OpeningTheDoorway: - ((Doorway)player.WhatInteractingWith).OpenDegree += gameMap.Timer.nowTime() - ((Doorway)player.WhatInteractingWith).OpenStartTime; + Doorway doorway = (Doorway)player.WhatInteractingWith; + doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; + doorway.OpenStartTime = 0; break; default: break; diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index afebbd6..20bb373 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -4,6 +4,7 @@ using Preparation.Interface; using Preparation.Utility; using System; using Timothy.FrameRateTask; +using Google.Protobuf.Compiler; namespace Gaming { @@ -28,29 +29,51 @@ namespace Gaming { }); } - public static bool ShowTime(Character player) + public bool ShowTime(Character player) { if ((!player.Commandable())) return false; IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime); - Debugger.Output(player, ": It's show time!"); + characterManager.SetPlayerState(player, PlayerStateType.UsingSkill); return ActiveSkillEffect(skill, player, () => { - /* Thread - * new FrameRateTaskExecutor( - loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheChest && gameMap.Timer.IsGaming && (!chestToOpen.IsOpen()), - loopToDo: () => - { - chestToOpen.OpenStartTime += GameData.frameDuration * player.SpeedOfOpenChest; - }, - timeInterval: GameData.frameDuration, - finallyReturn: () => 0 - ) + new Thread + ( + () => + { + new FrameRateTaskExecutor( + loopCondition: () => player.PlayerState == PlayerStateType.UsingSkill && gameMap.Timer.IsGaming, + loopToDo: () => + { + gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); + try + { + foreach (Character person in gameMap.GameObjDict[GameObjType.Character]) + { + if (!person.IsGhost()) + actionManager.MovePlayer(person, GameData.frameDuration, (player.Position - person.Position).Angle()); + } + } + finally + { + gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); + } + }, + timeInterval: GameData.frameDuration, + finallyReturn: () => 0 + ) - .Start();*/ + .Start(); + } + ) + { IsBackground = true }.Start(); }, () => - { }); + { + if (player.PlayerState == PlayerStateType.UsingSkill) + player.SetPlayerStateNaturally(); + } + ); } public static bool BecomeInvisible(Character player) diff --git a/logic/Gaming/SkillManager/SkillManager.cs b/logic/Gaming/SkillManager/SkillManager.cs index 0d2edf4..9cf6f09 100644 --- a/logic/Gaming/SkillManager/SkillManager.cs +++ b/logic/Gaming/SkillManager/SkillManager.cs @@ -52,6 +52,9 @@ namespace Gaming case ActiveSkillType.Rouse: Rouse(character); break; + case ActiveSkillType.ShowTime: + ShowTime(character); + break; default: return false; } diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs index b37bda6..9c8366c 100644 --- a/logic/Preparation/Interface/IOccupation.cs +++ b/logic/Preparation/Interface/IOccupation.cs @@ -101,10 +101,10 @@ namespace Preparation.Interface public BulletType InitBullet => BulletType.CommonAttackOfGhost; - public List ListOfIActiveSkill => new(new ActiveSkillType[] { }); + public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.ShowTime }); public List ListOfIPassiveSkill => new(new PassiveSkillType[] { }); - public double concealment = GameData.basicConcealment; + public double concealment = GameData.basicConcealment * 3 / 4; public double Concealment => concealment; public int alertnessRadius = GameData.basicGhostAlertnessRadius; @@ -414,6 +414,8 @@ namespace Preparation.Interface return new ANoisyPerson(); case CharacterType.TechOtaku: return new TechOtaku(); + case CharacterType.Idol: + return new Idol(); case CharacterType.Athlete: default: return new Athlete(); diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index 04950e8..c99608d 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -126,7 +126,7 @@ namespace Preparation.Interface public int SkillCD => GameData.commonSkillCD * 3; public int DurationTime => GameData.commonSkillTime; - private readonly object commonSkillLock = new object(); + private readonly object commonSkillLock = new(); public object ActiveSkillLock => commonSkillLock; public bool isBeingUsed = false; @@ -275,6 +275,8 @@ namespace Preparation.Interface return new Rouse(); case ActiveSkillType.Inspire: return new Inspire(); + case ActiveSkillType.ShowTime: + return new ShowTime(); default: return new NullSkill(); } @@ -308,6 +310,8 @@ namespace Preparation.Interface return ActiveSkillType.UseRobot; case Rouse: return ActiveSkillType.Rouse; + case ShowTime: + return ActiveSkillType.ShowTime; default: return ActiveSkillType.Null; } diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index fc9b4d7..9f426a3 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -83,6 +83,7 @@ namespace Preparation.Utility ANoisyPerson = 7, Robot = 8, Sunshine = 9, + Idol = 10, } public enum ActiveSkillType // 主动技能 { diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 70d634a..9e7d1cc 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -129,6 +129,7 @@ namespace Preparation.Utility CharacterType.Assassin => true, CharacterType.Klee => true, CharacterType.ANoisyPerson => true, + CharacterType.Idol => true, _ => false, }; } diff --git a/logic/Preparation/Utility/Transformation.cs b/logic/Preparation/Utility/Transformation.cs index 2735503..62fb05d 100644 --- a/logic/Preparation/Utility/Transformation.cs +++ b/logic/Preparation/Utility/Transformation.cs @@ -233,6 +233,8 @@ namespace Preparation.Utility return Protobuf.TrickerType.Klee; case Preparation.Utility.CharacterType.ANoisyPerson: return Protobuf.TrickerType.ANoisyPerson; + case CharacterType.Idol: + return TrickerType.Idol; default: return Protobuf.TrickerType.NullTrickerType; } @@ -247,6 +249,8 @@ namespace Preparation.Utility return Preparation.Utility.CharacterType.Klee; case Protobuf.TrickerType.ANoisyPerson: return Preparation.Utility.CharacterType.ANoisyPerson; + case TrickerType.Idol: + return CharacterType.Idol; default: return Preparation.Utility.CharacterType.Null; } diff --git a/logic/Preparation/Utility/XY.cs b/logic/Preparation/Utility/XY.cs index 3f91ae3..755a46e 100644 --- a/logic/Preparation/Utility/XY.cs +++ b/logic/Preparation/Utility/XY.cs @@ -75,10 +75,7 @@ namespace Preparation.Utility return Math.Atan2(y, x); } - public override bool Equals(object obj) - { - throw new NotImplementedException(); - } + public override bool Equals(object obj) => throw new NotImplementedException(); public override int GetHashCode() { diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index a3409ce..ba57920 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -44,133 +44,153 @@ namespace Server } public static MessageOfObj? Auto(MessageOfNews news) { - MessageOfObj objMsg = new(); - objMsg.NewsMessage = news; + MessageOfObj objMsg = new() + { + NewsMessage = news + }; return objMsg; } private static MessageOfObj? Student(Student player) { - MessageOfObj msg = new MessageOfObj(); if (player.IsGhost()) return null; - msg.StudentMessage = new(); + MessageOfObj msg = new() + { + StudentMessage = new() + { + X = player.Position.x, + Y = player.Position.y, + Speed = player.MoveSpeed, + Determination = player.HP, + Addiction = player.GamingAddiction, + Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place), + Guid = player.ID, + + PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState), + PlayerId = player.PlayerID, + ViewRange = player.ViewRange, + Radius = player.Radius, + DangerAlert = (player.BgmDictionary.ContainsKey(BgmType.GhostIsComing)) ? player.BgmDictionary[BgmType.GhostIsComing] : 0, + Score = player.Score, + TreatProgress = player.DegreeOfTreatment, + RescueProgress = player.TimeOfRescue, - msg.StudentMessage.X = player.Position.x; - msg.StudentMessage.Y = player.Position.y; - msg.StudentMessage.Speed = player.MoveSpeed; - msg.StudentMessage.Determination = player.HP; - msg.StudentMessage.Addiction = player.GamingAddiction; + BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer), + LearningSpeed = player.FixSpeed, + TreatSpeed = player.TreatSpeed, + FacingDirection = player.FacingDirection.Angle(), + StudentType = Transformation.ToStudentType(player.CharacterType) + } + }; foreach (var keyValue in player.TimeUntilActiveSkillAvailable) msg.StudentMessage.TimeUntilSkillAvailable.Add(keyValue.Value); - for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count(); ++i) + for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count; ++i) msg.StudentMessage.TimeUntilSkillAvailable.Add(-1); foreach (var value in player.PropInventory) msg.StudentMessage.Prop.Add(Transformation.ToPropType(value.GetPropType())); - msg.StudentMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place); - msg.StudentMessage.Guid = player.ID; - - msg.StudentMessage.PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState); - msg.StudentMessage.PlayerId = player.PlayerID; - msg.StudentMessage.ViewRange = player.ViewRange; - msg.StudentMessage.Radius = player.Radius; - msg.StudentMessage.DangerAlert = (player.BgmDictionary.ContainsKey(BgmType.GhostIsComing)) ? player.BgmDictionary[BgmType.GhostIsComing] : 0; - msg.StudentMessage.Score = player.Score; - msg.StudentMessage.TreatProgress = player.DegreeOfTreatment; - msg.StudentMessage.RescueProgress = player.TimeOfRescue; - foreach (KeyValuePair kvp in player.Buff) { if (kvp.Value) msg.StudentMessage.Buff.Add(Transformation.ToStudentBuffType(kvp.Key)); } - msg.StudentMessage.BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer); - msg.StudentMessage.LearningSpeed = player.FixSpeed; - msg.StudentMessage.TreatSpeed = player.TreatSpeed; - msg.StudentMessage.FacingDirection = player.FacingDirection.Angle(); - msg.StudentMessage.StudentType = Transformation.ToStudentType(player.CharacterType); return msg; } private static MessageOfObj? Tricker(Character player) { - MessageOfObj msg = new MessageOfObj(); if (!player.IsGhost()) return null; - msg.TrickerMessage = new(); + MessageOfObj msg = new() + { + TrickerMessage = new() + { + X = player.Position.x, + Y = player.Position.y, + Speed = player.MoveSpeed, + Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place), + + TrickerType = Transformation.ToTrickerType(player.CharacterType), + Guid = player.ID, + Score = player.Score, + PlayerId = player.PlayerID, + ViewRange = player.ViewRange, + Radius = player.Radius, + PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState), + TrickDesire = (player.BgmDictionary.ContainsKey(BgmType.StudentIsApproaching)) ? player.BgmDictionary[BgmType.StudentIsApproaching] : 0, + ClassVolume = (player.BgmDictionary.ContainsKey(BgmType.GeneratorIsBeingFixed)) ? player.BgmDictionary[BgmType.GeneratorIsBeingFixed] : 0, + FacingDirection = player.FacingDirection.Angle(), + BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer) + } + }; - msg.TrickerMessage.X = player.Position.x; - msg.TrickerMessage.Y = player.Position.y; - msg.TrickerMessage.Speed = player.MoveSpeed; foreach (var keyValue in player.TimeUntilActiveSkillAvailable) msg.TrickerMessage.TimeUntilSkillAvailable.Add(keyValue.Value); - for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count(); ++i) + for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count; ++i) msg.TrickerMessage.TimeUntilSkillAvailable.Add(-1); - msg.TrickerMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place); foreach (var value in player.PropInventory) msg.TrickerMessage.Prop.Add(Transformation.ToPropType(value.GetPropType())); - - msg.TrickerMessage.TrickerType = Transformation.ToTrickerType(player.CharacterType); - msg.TrickerMessage.Guid = player.ID; - msg.TrickerMessage.Score = player.Score; - msg.TrickerMessage.PlayerId = player.PlayerID; - msg.TrickerMessage.ViewRange = player.ViewRange; - msg.TrickerMessage.Radius = player.Radius; - msg.TrickerMessage.PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState); - msg.TrickerMessage.TrickDesire = (player.BgmDictionary.ContainsKey(BgmType.StudentIsApproaching)) ? player.BgmDictionary[BgmType.StudentIsApproaching] : 0; - msg.TrickerMessage.ClassVolume = (player.BgmDictionary.ContainsKey(BgmType.GeneratorIsBeingFixed)) ? player.BgmDictionary[BgmType.GeneratorIsBeingFixed] : 0; - msg.TrickerMessage.FacingDirection = player.FacingDirection.Angle(); - msg.TrickerMessage.BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer); foreach (KeyValuePair kvp in player.Buff) { if (kvp.Value) msg.TrickerMessage.Buff.Add(Transformation.ToTrickerBuffType(kvp.Key)); } - return msg; } private static MessageOfObj Bullet(Bullet bullet) { - MessageOfObj msg = new MessageOfObj(); - msg.BulletMessage = new(); - msg.BulletMessage.X = bullet.Position.x; - msg.BulletMessage.Y = bullet.Position.y; - msg.BulletMessage.FacingDirection = bullet.FacingDirection.Angle(); - msg.BulletMessage.Guid = bullet.ID; - msg.BulletMessage.Team = (bullet.Parent.IsGhost()) ? PlayerType.TrickerPlayer : PlayerType.StudentPlayer; - msg.BulletMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)bullet.Place); - msg.BulletMessage.BombRange = bullet.BulletBombRange; - msg.BulletMessage.Speed = bullet.Speed; + MessageOfObj msg = new() + { + BulletMessage = new() + { + X = bullet.Position.x, + Y = bullet.Position.y, + FacingDirection = bullet.FacingDirection.Angle(), + Guid = bullet.ID, + Team = (bullet.Parent.IsGhost()) ? PlayerType.TrickerPlayer : PlayerType.StudentPlayer, + Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)bullet.Place), + BombRange = bullet.BulletBombRange, + Speed = bullet.Speed + } + }; return msg; } private static MessageOfObj Prop(Prop prop) { - MessageOfObj msg = new MessageOfObj(); - msg.PropMessage = new(); - msg.PropMessage.Type = Transformation.ToPropType(prop.GetPropType()); - msg.PropMessage.X = prop.Position.x; - msg.PropMessage.Y = prop.Position.y; - msg.PropMessage.FacingDirection = prop.FacingDirection.Angle(); - msg.PropMessage.Guid = prop.ID; - msg.PropMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)prop.Place); + MessageOfObj msg = new() + { + PropMessage = new() + { + Type = Transformation.ToPropType(prop.GetPropType()), + X = prop.Position.x, + Y = prop.Position.y, + FacingDirection = prop.FacingDirection.Angle(), + Guid = prop.ID, + Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)prop.Place) + } + }; return msg; } private static MessageOfObj BombedBullet(BombedBullet bombedBullet) { - MessageOfObj msg = new MessageOfObj(); - msg.BombedBulletMessage = new(); - msg.BombedBulletMessage.X = bombedBullet.bulletHasBombed.Position.x; - msg.BombedBulletMessage.Y = bombedBullet.bulletHasBombed.Position.y; - msg.BombedBulletMessage.FacingDirection = bombedBullet.FacingDirection.Angle(); - msg.BombedBulletMessage.MappingId = bombedBullet.MappingID; - msg.BombedBulletMessage.BombRange = bombedBullet.bulletHasBombed.BulletBombRange; + MessageOfObj msg = new() + { + BombedBulletMessage = new() + { + X = bombedBullet.bulletHasBombed.Position.x, + Y = bombedBullet.bulletHasBombed.Position.y, + FacingDirection = bombedBullet.FacingDirection.Angle(), + MappingId = bombedBullet.MappingID, + BombRange = bombedBullet.bulletHasBombed.BulletBombRange + } + }; return msg; } @@ -188,49 +208,69 @@ namespace Server private static MessageOfObj Classroom(Generator generator) { - MessageOfObj msg = new MessageOfObj(); - msg.ClassroomMessage = new(); - msg.ClassroomMessage.X = generator.Position.x; - msg.ClassroomMessage.Y = generator.Position.y; - msg.ClassroomMessage.Progress = generator.DegreeOfRepair; + MessageOfObj msg = new() + { + ClassroomMessage = new() + { + X = generator.Position.x, + Y = generator.Position.y, + Progress = generator.DegreeOfRepair + } + }; return msg; } private static MessageOfObj Gate(Doorway doorway, int time) { - MessageOfObj msg = new MessageOfObj(); - msg.GateMessage = new(); - msg.GateMessage.X = doorway.Position.x; - msg.GateMessage.Y = doorway.Position.y; + MessageOfObj msg = new() + { + GateMessage = new() + { + X = doorway.Position.x, + Y = doorway.Position.y + } + }; int progress = ((doorway.OpenStartTime > 0) ? (time - doorway.OpenStartTime) : 0) + doorway.OpenDegree; msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress; return msg; } private static MessageOfObj HiddenGate(EmergencyExit Exit) { - MessageOfObj msg = new MessageOfObj(); - msg.HiddenGateMessage = new(); - msg.HiddenGateMessage.X = Exit.Position.x; - msg.HiddenGateMessage.Y = Exit.Position.y; - msg.HiddenGateMessage.Opened = Exit.IsOpen; + MessageOfObj msg = new() + { + HiddenGateMessage = new() + { + X = Exit.Position.x, + Y = Exit.Position.y, + Opened = Exit.IsOpen + } + }; return msg; } private static MessageOfObj Door(Door door) { - MessageOfObj msg = new MessageOfObj(); - msg.DoorMessage = new(); - msg.DoorMessage.X = door.Position.x; - msg.DoorMessage.Y = door.Position.y; - msg.DoorMessage.Progress = door.OpenOrLockDegree; - msg.DoorMessage.IsOpen = door.IsOpen; + MessageOfObj msg = new() + { + DoorMessage = new() + { + X = door.Position.x, + Y = door.Position.y, + Progress = door.OpenOrLockDegree, + IsOpen = door.IsOpen + } + }; return msg; } private static MessageOfObj Chest(Chest chest, int time) { - MessageOfObj msg = new MessageOfObj(); - msg.ChestMessage = new(); - msg.ChestMessage.X = chest.Position.x; - msg.ChestMessage.Y = chest.Position.y; + MessageOfObj msg = new() + { + ChestMessage = new() + { + X = chest.Position.x, + Y = chest.Position.y + } + }; int progress = (chest.OpenStartTime > 0) ? ((time - chest.OpenStartTime) * chest.WhoOpen.SpeedOfOpenChest) : 0; msg.ChestMessage.Progress = (progress > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : progress; return msg; From 2f57c053e77a8ee29c817c54b43d9719d33cd2a1 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Tue, 11 Apr 2023 19:35:10 +0800 Subject: [PATCH 16/37] feat(CAPI): :sparkles: add constants --- CAPI/cpp/API/include/constants.h | 297 ++++++++++++++++++++++++++++++- CAPI/python/PyAPI/constants.py | 251 ++++++++++++++++++++++++++ 2 files changed, 545 insertions(+), 3 deletions(-) create mode 100644 CAPI/python/PyAPI/constants.py diff --git a/CAPI/cpp/API/include/constants.h b/CAPI/cpp/API/include/constants.h index 7a700e5..6407b3a 100644 --- a/CAPI/cpp/API/include/constants.h +++ b/CAPI/cpp/API/include/constants.h @@ -2,17 +2,308 @@ #ifndef CONSTANTS_H #define CONSTANTS_H +#ifndef SCCI +#define SCCI static const constexpr inline +#endif + namespace Constants { - static const constexpr inline numOfGridPerCell = 1000; + // 地图相关 + SCCI int numOfGridPerCell = 1000; // 单位坐标数 + SCCI int rows = 50; // 地图行数 + SCCI int cols = 50; // 地图列数 + + SCCI int numOfClassroom = 10; // 教室数量 + SCCI int numOfChest = 8; // 宝箱数量 + + SCCI int maxClassroomProgress = 10000000; // 教室最大进度 + SCCI int maxDoorProgress = 10000000; // 开关门最大进度 + SCCI int maxChestProgress = 10000000; // 宝箱最大进度 + SCCI int maxGateProgress = 18000; // 大门最大进度 + + SCCI int numOfRequiredClassroomForGate = 7; // 打开大门需要完成的教室数量 + SCCI int numOfRequiredClassroomForHiddenGate = 3; // 打开隐藏门需要完成的教室数量 + + // 人物属性相关 + SCCI int basicTreatSpeed = 100; + SCCI int basicFixSpeed = 123; + SCCI int basicSpeedOfOpeningOrLocking = 4000; + SCCI int basicStudentSpeedOfClimbingThroughWindows = 611; + SCCI int basicTrickerSpeedOfClimbingThroughWindows = 1270; + SCCI int basicSpeedOfOpenChest = 1000; + + SCCI int basicHp = 3000000; + SCCI int basicMaxGamingAddiction = 60000; + SCCI int BeginGamingAddiction = 20900; + SCCI int MidGamingAddiction = 40300; + SCCI int basicTreatmentDegree = 1500000; + SCCI int basicTimeOfRescue = 1000; + + SCCI int basicStudentSpeed = 1270; + SCCI int basicTrickerSpeed = 1504; + + SCCI int maxSpeed = 12000; + + SCCI double basicConcealment = 1.0; + SCCI int basicStudentAlertnessRadius = 15 * numOfGridPerCell; + SCCI int basicTrickerAlertnessRadius = 17 * numOfGridPerCell; + SCCI int basicStudentViewRange = 10 * numOfGridPerCell; + SCCI int basicTrickerViewRange = 15 * numOfGridPerCell; + + SCCI int maxNumOfProp = 3; + + // 攻击相关 + + SCCI int basicApOfTricker = 1500000; + SCCI int basicCD = 3000; // 初始子弹冷却 + SCCI int basicCastTime = 500; // 基本前摇时间 + SCCI int basicBackswing = 800; // 基本后摇时间 + SCCI int basicRecoveryFromHit = 3700; // 基本命中攻击恢复时长 + SCCI int basicStunnedTimeOfStudent = 4300; + + SCCI int basicBulletMoveSpeed = 3700; // 基本子弹移动速度 + SCCI double basicRemoteAttackRange = 3000; // 基本远程攻击范围 + SCCI double basicAttackShortRange = 1100; // 基本近程攻击范围 + SCCI double basicBulletBombRange = 1000; // 基本子弹爆炸范围 + + // 道具相关 + + SCCI int apPropAdd = basicApOfTricker * 12 / 10; + SCCI int apSpearAdd = basicApOfTricker * 6 / 10; + SCCI int remainHpWhenAddLife = 100; + + // 职业相关 + struct Assassin + { + SCCI double moveSpeed = 1.1; + SCCI double maxHp = 1.0; + SCCI double concealment = 1.5; + SCCI double alertnessRadius = 1.3; + SCCI double viewRange = 1.2; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 1.0; + SCCI double speedOfOpenChest = 1.0; + }; + + struct Klee + { + SCCI double moveSpeed = 1.0; + SCCI double maxHp = 1.0; + SCCI double concealment = 1.0; + SCCI double alertnessRadius = 1.0; + SCCI double viewRange = 1.0; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 1.0; + SCCI double speedOfOpenChest = 1.1; + }; + + struct ANoisyPerson + { + SCCI double moveSpeed = 1.07; + SCCI double maxHp = 1.2; + SCCI double concealment = 0.8; + SCCI double alertnessRadius = 0.9; + SCCI double viewRange = 1.0; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 1.1; + SCCI double speedOfOpenChest = 1.1; + }; - struct StudentConstants + struct Idol { + SCCI double moveSpeed = 1.0; + SCCI double maxHp = 1.0; + SCCI double concealment = 0.75; + SCCI double alertnessRadius = 1.0; + SCCI double viewRange = 1.1; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 1.0; + SCCI double speedOfOpenChest = 1.0; }; - struct TrickerConstants + struct Athlete { + SCCI double moveSpeed = 1.1; + SCCI double maxHp = 1.0; + SCCI double maxAddiction = 0.9; + SCCI double fixSpeed = 0.6; + SCCI double treatSpeed = 0.8; + SCCI double concealment = 0.9; + SCCI double alertnessRadius = 1.0; + SCCI double viewRange = 1.1; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 1.2; + SCCI double speedOfOpenChest = 1.0; }; + struct Teacher + { + SCCI double moveSpeed = 0.75; + SCCI double maxHp = 10.0; + SCCI double maxAddiction = 10.0; + SCCI double fixSpeed = 0.0; + SCCI double treatSpeed = 0.7; + SCCI double concealment = 0.5; + SCCI double alertnessRadius = 0.5; + SCCI double viewRange = 0.9; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 0.5; + SCCI double speedOfOpenChest = 1.0; + }; + + struct StraightAStudent + { + SCCI double moveSpeed = 0.8; + SCCI double maxHp = 1.1; + SCCI double maxAddiction = 1.3; + SCCI double fixSpeed = 1.1; + SCCI double treatSpeed = 0.8; + SCCI double concealment = 0.9; + SCCI double alertnessRadius = 0.9; + SCCI double viewRange = 0.9; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 0.83333; + SCCI double speedOfOpenChest = 1.0; + }; + + struct Robot + { + SCCI double moveSpeed = 1.0; + SCCI double maxHp = 0.4; + SCCI double maxAddiction = 0.0; + SCCI double fixSpeed = 1.0; + SCCI double treatSpeed = 0.8; + SCCI double concealment = 1.0; + SCCI double alertnessRadius = 1.0; + SCCI double viewRange = 1.0; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 0.0016; + SCCI double speedOfOpenChest = 1.0; + }; + + struct TechOtaku + { + SCCI double moveSpeed = 0.75; + SCCI double maxHp = 0.9; + SCCI double maxAddiction = 1.1; + SCCI double fixSpeed = 1.1; + SCCI double treatSpeed = 0.9; + SCCI double concealment = 1.0; + SCCI double alertnessRadius = 1.0; + SCCI double viewRange = 0.9; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 0.75; + SCCI double speedOfOpenChest = 1.0; + }; + + struct Sunshine + { + SCCI double moveSpeed = 1.0; + SCCI double maxHp = 1.0667; + SCCI double maxAddiction = 1.1; + SCCI double fixSpeed = 1.0; + SCCI double treatSpeed = 2.0; + SCCI double concealment = 1.0; + SCCI double alertnessRadius = 1.0; + SCCI double viewRange = 1.0; + SCCI double speedOfOpeningOrLocking = 1.0; + SCCI double speedOfClimbingThroughWindows = 1.0; + SCCI double speedOfOpenChest = 1.0; + }; + + // 技能相关 + SCCI int maxNumOfSkill = 3; + SCCI int commonSkillCD = 30000; // 普通技能标准冷却时间 + SCCI int commonSkillTime = 10000; // 普通技能标准持续时间 + + SCCI int timeOfTrickerFaintingWhenCharge = 7220; + SCCI int timeOfStudentFaintingWhenCharge = 2090; + + SCCI int timeOfTrickerFaintingWhenPunish = 3070; + + SCCI int timeOfTrickerSwingingAfterHowl = 3070; + SCCI int timeOfStudentFaintingWhenHowl = 6110; + + SCCI int timeOfStunnedWhenJumpyDumpty = 3070; + + SCCI double addedTimeOfSpeedWhenInspire = 0.6; + SCCI int timeOfAddingSpeedWhenInspire = 6000; + struct CanBeginToCharge + { + SCCI double skillCD = 0.8; + SCCI double durationTime = 0.5; + }; + + struct BecomeInvisible + { + SCCI double skillCD = 2.0; + SCCI double durationTime = 0.6; + }; + + struct Punish + { + SCCI double skillCD = 1.0; + SCCI double durationTime = 0.0; + }; + + struct Rouse + { + SCCI double skillCD = 2.0; + SCCI double durationTime = 0.0; + }; + + struct Encourage + { + SCCI double skillCD = 2.0; + SCCI double durationTime = 0.0; + }; + + struct Inspire + { + SCCI double skillCD = 2.0; + SCCI double durationTime = 0.0; + }; + + struct Howl + { + SCCI double skillCD = 0.8333; + SCCI double durationTime = 0.0; + }; + + struct ShowTime + { + SCCI double skillCD = 3.0; + SCCI double durationTime = 1.0; + }; + + struct JumpyBomb + { + SCCI double skillCD = 0.5; + SCCI double durationTime = 0.3; + }; + + struct UseKnife + { + SCCI double skillCD = 1.0; + SCCI double durationTime = 0.1; + }; + + struct UseRobot + { + SCCI double skillCD = 0.0017; + SCCI double durationTime = 0.0; + }; + + struct WriteAnswers + { + SCCI double skillCD = 1.0; + SCCI double durationTime = 0.0; + }; + + struct SummonGolem + { + SCCI double skillCD = 1.0; + SCCI double durationTime = 0.0; + }; } // namespace Constants #endif diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py new file mode 100644 index 0000000..783c23d --- /dev/null +++ b/CAPI/python/PyAPI/constants.py @@ -0,0 +1,251 @@ +class Constants(): + numOfGridPerCell = 1000 # 单位坐标数 + rows = 50 # 地图行数 + cols = 50 # 地图列数 + + numOfClassroom = 10 # 教室数量 + numOfChest = 8 # 宝箱数量 + + maxClassroomProgress = 10000000 # 教室最大进度 + maxDoorProgress = 10000000 # 开关门最大进度 + maxChestProgress = 10000000 # 宝箱最大进度 + maxGateProgress = 18000 # 大门最大进度 + + numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量 + numOfRequiredClassroomForHiddenGate = 3 # 打开隐藏门需要完成的教室数量 + + # 人物属性相关 + basicTreatSpeed = 100 + basicFixSpeed = 123 + basicSpeedOfOpeningOrLocking = 4000 + basicStudentSpeedOfClimbingThroughWindows = 611 + basicTrickerSpeedOfClimbingThroughWindows = 1270 + basicSpeedOfOpenChest = 1000 + + basicHp = 3000000 + basicMaxGamingAddiction = 60000 + BeginGamingAddiction = 20900 + MidGamingAddiction = 40300 + basicTreatmentDegree = 1500000 + basicTimeOfRescue = 1000 + + basicStudentSpeed = 1270 + basicTrickerSpeed = 1504 + + maxSpeed = 12000 + + basicConcealment = 1.0 + basicStudentAlertnessRadius = 15 * numOfGridPerCell + basicTrickerAlertnessRadius = 17 * numOfGridPerCell + basicStudentViewRange = 10 * numOfGridPerCell + basicTrickerViewRange = 15 * numOfGridPerCell + + maxNumOfProp = 3 + + # 攻击相关 + + basicApOfTricker = 1500000 + basicCD = 3000 # 初始子弹冷却 + basicCastTime = 500 # 基本前摇时间 + basicBackswing = 800 # 基本后摇时间 + basicRecoveryFromHit = 3700 # 基本命中攻击恢复时长 + basicStunnedTimeOfStudent = 4300 + + basicBulletMoveSpeed = 3700 # 基本子弹移动速度 + basicRemoteAttackRange = 3000 # 基本远程攻击范围 + basicAttackShortRange = 1100 # 基本近程攻击范围 + basicBulletBombRange = 1000 # 基本子弹爆炸范围 + + # 道具相关 + + apPropAdd = basicApOfTricker * 12 / 10 + apSpearAdd = basicApOfTricker * 6 / 10 + remainHpWhenAddLife = 100 + + class Assassin: + moveSpeed = 1.1 + maxHp = 1.0 + concealment = 1.5 + alertnessRadius = 1.3 + viewRange = 1.2 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 1.0 + speedOfOpenChest = 1.0 + + class Klee: + moveSpeed = 1.0 + maxHp = 1.0 + concealment = 1.0 + alertnessRadius = 1.0 + viewRange = 1.0 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 1.0 + speedOfOpenChest = 1.1 + + class ANoisyPerson: + moveSpeed = 1.07 + maxHp = 1.2 + concealment = 0.8 + alertnessRadius = 0.9 + viewRange = 1.0 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 1.1 + speedOfOpenChest = 1.1 + + class Idol: + moveSpeed = 1.0 + maxHp = 1.0 + concealment = 0.75 + alertnessRadius = 1.0 + viewRange = 1.1 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 1.0 + speedOfOpenChest = 1.0 + + class Athlete: + moveSpeed = 1.1 + maxHp = 1.0 + maxAddiction = 0.9 + fixSpeed = 0.6 + treatSpeed = 0.8 + concealment = 0.9 + alertnessRadius = 1.0 + viewRange = 1.1 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 1.2 + speedOfOpenChest = 1.0 + + class Teacher: + moveSpeed = 0.75 + maxHp = 10.0 + maxAddiction = 10.0 + fixSpeed = 0.0 + treatSpeed = 0.7 + concealment = 0.5 + alertnessRadius = 0.5 + viewRange = 0.9 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 0.5 + speedOfOpenChest = 1.0 + + class StraightAStudent: + moveSpeed = 0.8 + maxHp = 1.1 + maxAddiction = 1.3 + fixSpeed = 1.1 + treatSpeed = 0.8 + concealment = 0.9 + alertnessRadius = 0.9 + viewRange = 0.9 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 0.83333 + speedOfOpenChest = 1.0 + + class Robot: + moveSpeed = 1.0 + maxHp = 0.4 + maxAddiction = 0.0 + fixSpeed = 1.0 + treatSpeed = 0.8 + concealment = 1.0 + alertnessRadius = 1.0 + viewRange = 1.0 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 0.0016 + speedOfOpenChest = 1.0 + + class TechOtaku: + moveSpeed = 0.75 + maxHp = 0.9 + maxAddiction = 1.1 + fixSpeed = 1.1 + treatSpeed = 0.9 + concealment = 1.0 + alertnessRadius = 1.0 + viewRange = 0.9 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 0.75 + speedOfOpenChest = 1.0 + + class Sunshine: + moveSpeed = 1.0 + maxHp = 1.0667 + maxAddiction = 1.1 + fixSpeed = 1.0 + treatSpeed = 2.0 + concealment = 1.0 + alertnessRadius = 1.0 + viewRange = 1.0 + speedOfOpeningOrLocking = 1.0 + speedOfClimbingThroughWindows = 1.0 + speedOfOpenChest = 1.0 + + # 技能相关 + maxNumOfSkill = 3 + commonSkillCD = 30000 # 普通技能标准冷却时间 + commonSkillTime = 10000 # 普通技能标准持续时间 + + timeOfTrickerFaintingWhenCharge = 7220 + timeOfStudentFaintingWhenCharge = 2090 + + timeOfTrickerFaintingWhenPunish = 3070 + + timeOfTrickerSwingingAfterHowl = 3070 + timeOfStudentFaintingWhenHowl = 6110 + + timeOfStunnedWhenJumpyDumpty = 3070 + + addedTimeOfSpeedWhenInspire = 0.6 + timeOfAddingSpeedWhenInspire = 6000 + + class CanBeginToCharge: + skillCD = 0.8 + durationTime = 0.5 + + class BecomeInvisible: + skillCD = 2.0 + durationTime = 0.6 + + class Punish: + skillCD = 1.0 + durationTime = 0.0 + + class Rouse: + skillCD = 2.0 + durationTime = 0.0 + + class Encourage: + skillCD = 2.0 + durationTime = 0.0 + + class Inspire: + skillCD = 2.0 + durationTime = 0.0 + + class Howl: + skillCD = 0.8333 + durationTime = 0.0 + + class ShowTime: + skillCD = 3.0 + durationTime = 1.0 + + class JumpyBomb: + skillCD = 0.5 + durationTime = 0.3 + + class UseKnife: + skillCD = 1.0 + durationTime = 0.1 + + class UseRobot: + skillCD = 0.0017 + durationTime = 0.0 + + class WriteAnswers: + skillCD = 1.0 + durationTime = 0.0 + + class SummonGolem: + skillCD = 1.0 + durationTime = 0.0 From bd5cec3b6efdbb75bef2b19a94bba1b2c5969c19 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Tue, 11 Apr 2023 19:41:13 +0800 Subject: [PATCH 17/37] style(CAPI): :art: change some func names --- CAPI/cpp/API/include/API.h | 16 +++++++------- CAPI/cpp/API/include/Communication.h | 4 ++-- CAPI/cpp/API/include/logic.h | 4 ++-- CAPI/cpp/API/src/AI.cpp | 1 + CAPI/cpp/API/src/API.cpp | 8 +++---- CAPI/cpp/API/src/Communication.cpp | 4 ++-- CAPI/cpp/API/src/DebugAPI.cpp | 16 +++++++------- CAPI/cpp/API/src/logic.cpp | 12 +++++------ CAPI/cpp/CAPI.sln | 31 ---------------------------- CAPI/python/PyAPI/AI.py | 4 ++++ CAPI/python/PyAPI/API.py | 8 +++---- CAPI/python/PyAPI/Communication.py | 4 ++-- CAPI/python/PyAPI/DebugAPI.py | 24 ++++++++++----------- CAPI/python/PyAPI/Interface.py | 8 +++---- CAPI/python/PyAPI/constants.py | 7 ++++++- CAPI/python/PyAPI/logic.py | 12 +++++------ 16 files changed, 71 insertions(+), 92 deletions(-) delete mode 100644 CAPI/cpp/CAPI.sln diff --git a/CAPI/cpp/API/include/API.h b/CAPI/cpp/API/include/API.h index c4516df..a8f3034 100644 --- a/CAPI/cpp/API/include/API.h +++ b/CAPI/cpp/API/include/API.h @@ -69,8 +69,8 @@ public: virtual bool Graduate() = 0; virtual bool StartLearning() = 0; - virtual bool StartTreatMate(int64_t mateID) = 0; - virtual bool StartRescueMate(int64_t mateID) = 0; + virtual bool StartEncourageMate(int64_t mateID) = 0; + virtual bool StartRouseMate(int64_t mateID) = 0; virtual bool OpenDoor() = 0; virtual bool CloseDoor() = 0; @@ -177,8 +177,8 @@ public: /*****学生阵营的特定函数*****/ virtual std::future StartLearning() = 0; - virtual std::future StartTreatMate(int64_t mateID) = 0; - virtual std::future StartRescueMate(int64_t mateID) = 0; + virtual std::future StartEncourageMate(int64_t mateID) = 0; + virtual std::future StartRouseMate(int64_t mateID) = 0; virtual std::future Graduate() = 0; [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; }; @@ -266,8 +266,8 @@ public: [[nodiscard]] std::vector GetPlayerGUIDs() const override; std::future StartLearning() override; - std::future StartTreatMate(int64_t mateID) override; - std::future StartRescueMate(int64_t mateID) override; + std::future StartEncourageMate(int64_t mateID) override; + std::future StartRouseMate(int64_t mateID) override; std::future Graduate() override; [[nodiscard]] std::shared_ptr GetSelfInfo() const override; @@ -434,8 +434,8 @@ public: [[nodiscard]] std::vector GetPlayerGUIDs() const override; std::future StartLearning() override; - std::future StartTreatMate(int64_t mateID) override; - std::future StartRescueMate(int64_t mateID) override; + std::future StartEncourageMate(int64_t mateID) override; + std::future StartRouseMate(int64_t mateID) override; std::future Graduate() override; [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const override; diff --git a/CAPI/cpp/API/include/Communication.h b/CAPI/cpp/API/include/Communication.h index 3490b75..2f75e43 100644 --- a/CAPI/cpp/API/include/Communication.h +++ b/CAPI/cpp/API/include/Communication.h @@ -39,8 +39,8 @@ public: bool Graduate(int64_t playerID); bool StartLearning(int64_t playerID); - bool StartTreatMate(int64_t playerID, int64_t mateID); - bool StartRescueMate(int64_t playerID, int64_t mateID); + bool StartEncourageMate(int64_t playerID, int64_t mateID); + bool StartRouseMate(int64_t playerID, int64_t mateID); bool Attack(double angle, int64_t playerID); diff --git a/CAPI/cpp/API/include/logic.h b/CAPI/cpp/API/include/logic.h index 2db779b..3e33682 100644 --- a/CAPI/cpp/API/include/logic.h +++ b/CAPI/cpp/API/include/logic.h @@ -125,8 +125,8 @@ private: bool StartLearning() override; - bool StartTreatMate(int64_t mateID) override; - bool StartRescueMate(int64_t mateID) override; + bool StartEncourageMate(int64_t mateID) override; + bool StartRouseMate(int64_t mateID) override; bool Attack(double angle) override; diff --git a/CAPI/cpp/API/src/AI.cpp b/CAPI/cpp/API/src/AI.cpp index 79c408b..5e94723 100644 --- a/CAPI/cpp/API/src/AI.cpp +++ b/CAPI/cpp/API/src/AI.cpp @@ -1,6 +1,7 @@ #include #include #include "AI.h" +#include "constants.h" // 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新 extern const bool asynchronous = false; diff --git a/CAPI/cpp/API/src/API.cpp b/CAPI/cpp/API/src/API.cpp index 03e08c7..ce38ae5 100644 --- a/CAPI/cpp/API/src/API.cpp +++ b/CAPI/cpp/API/src/API.cpp @@ -383,16 +383,16 @@ std::future StudentAPI::StartLearning() { return logic.StartLearning(); }); } -std::future StudentAPI::StartTreatMate(int64_t mateID) +std::future StudentAPI::StartEncourageMate(int64_t mateID) { return std::async(std::launch::async, [=]() - { return logic.StartTreatMate(mateID); }); + { return logic.StartEncourageMate(mateID); }); } -std::future StudentAPI::StartRescueMate(int64_t mateID) +std::future StudentAPI::StartRouseMate(int64_t mateID) { return std::async(std::launch::async, [=]() - { return logic.StartRescueMate(mateID); }); + { return logic.StartRouseMate(mateID); }); } std::future StudentAPI::Graduate() diff --git a/CAPI/cpp/API/src/Communication.cpp b/CAPI/cpp/API/src/Communication.cpp index 41a8590..01b4b25 100644 --- a/CAPI/cpp/API/src/Communication.cpp +++ b/CAPI/cpp/API/src/Communication.cpp @@ -183,7 +183,7 @@ bool Communication::StartLearning(int64_t playerID) return false; } -bool Communication::StartRescueMate(int64_t playerID, int64_t mateID) +bool Communication::StartRouseMate(int64_t playerID, int64_t mateID) { protobuf::BoolRes saveStudentResult; ClientContext context; @@ -195,7 +195,7 @@ bool Communication::StartRescueMate(int64_t playerID, int64_t mateID) return false; } -bool Communication::StartTreatMate(int64_t playerID, int64_t mateID) +bool Communication::StartEncourageMate(int64_t playerID, int64_t mateID) { protobuf::BoolRes healStudentResult; ClientContext context; diff --git a/CAPI/cpp/API/src/DebugAPI.cpp b/CAPI/cpp/API/src/DebugAPI.cpp index f307148..1bbab12 100644 --- a/CAPI/cpp/API/src/DebugAPI.cpp +++ b/CAPI/cpp/API/src/DebugAPI.cpp @@ -575,23 +575,23 @@ std::future StudentDebugAPI::StartLearning() return result; }); } -std::future StudentDebugAPI::StartRescueMate(int64_t mateID) +std::future StudentDebugAPI::StartRouseMate(int64_t mateID) { - logger->info("StartRescueMate: mate id={}, called at {}ms", mateID, Time::TimeSinceStart(startPoint)); + logger->info("StartRouseMate: mate id={}, called at {}ms", mateID, Time::TimeSinceStart(startPoint)); return std::async(std::launch::async, [=]() - { auto result = logic.StartRescueMate(mateID); + { auto result = logic.StartRouseMate(mateID); if (!result) - logger->warn("StartRescueMate: failed at {}ms", Time::TimeSinceStart(startPoint)); + logger->warn("StartRouseMate: failed at {}ms", Time::TimeSinceStart(startPoint)); return result; }); } -std::future StudentDebugAPI::StartTreatMate(int64_t mateID) +std::future StudentDebugAPI::StartEncourageMate(int64_t mateID) { - logger->info("StartTreatMate: mate id={}, called at {}ms", mateID, Time::TimeSinceStart(startPoint)); + logger->info("StartEncourageMate: mate id={}, called at {}ms", mateID, Time::TimeSinceStart(startPoint)); return std::async(std::launch::async, [=]() - { auto result = logic.StartTreatMate(mateID); + { auto result = logic.StartEncourageMate(mateID); if (!result) - logger->warn("StartTreatMate: failed at {}ms", Time::TimeSinceStart(startPoint)); + logger->warn("StartEncourageMate: failed at {}ms", Time::TimeSinceStart(startPoint)); return result; }); } diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index 4b8415c..8a83e03 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -251,16 +251,16 @@ bool Logic::StartLearning() return pComm->StartLearning(playerID); } -bool Logic::StartTreatMate(int64_t mateID) +bool Logic::StartEncourageMate(int64_t mateID) { - logger->debug("Called StartTreatMate"); - return pComm->StartTreatMate(playerID, mateID); + logger->debug("Called StartEncourageMate"); + return pComm->StartEncourageMate(playerID, mateID); } -bool Logic::StartRescueMate(int64_t mateID) +bool Logic::StartRouseMate(int64_t mateID) { - logger->debug("Called StartRescueMate"); - return pComm->StartRescueMate(playerID, mateID); + logger->debug("Called StartRouseMate"); + return pComm->StartRouseMate(playerID, mateID); } bool Logic::Attack(double angle) diff --git a/CAPI/cpp/CAPI.sln b/CAPI/cpp/CAPI.sln deleted file mode 100644 index 76cf3d8..0000000 --- a/CAPI/cpp/CAPI.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "API", "API\API.vcxproj", "{B9AC3133-177D-453C-8066-ED4702D3F36A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Debug|x64.ActiveCfg = Debug|x64 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Debug|x64.Build.0 = Debug|x64 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Debug|x86.ActiveCfg = Debug|Win32 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Debug|x86.Build.0 = Debug|Win32 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Release|x64.ActiveCfg = Release|x64 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Release|x64.Build.0 = Release|x64 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Release|x86.ActiveCfg = Release|Win32 - {B9AC3133-177D-453C-8066-ED4702D3F36A}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {372B1478-522C-4EEB-A527-983D310A3F50} - EndGlobalSection -EndGlobal diff --git a/CAPI/python/PyAPI/AI.py b/CAPI/python/PyAPI/AI.py index eb4abd0..a503018 100644 --- a/CAPI/python/PyAPI/AI.py +++ b/CAPI/python/PyAPI/AI.py @@ -1,6 +1,7 @@ import PyAPI.structures as THUAI6 from PyAPI.Interface import IStudentAPI, ITrickerAPI, IAI from typing import Union, Final, cast +from PyAPI.constants import Constants import queue import time @@ -147,4 +148,7 @@ class AI(IAI): api.PrintTricker() def TrickerPlay(self, api: ITrickerAPI) -> None: + api.UseSkill(0) + api.UseSkill(1) + api.PrintSelfInfo() return diff --git a/CAPI/python/PyAPI/API.py b/CAPI/python/PyAPI/API.py index bb5522b..2a04666 100644 --- a/CAPI/python/PyAPI/API.py +++ b/CAPI/python/PyAPI/API.py @@ -157,11 +157,11 @@ class StudentAPI(IStudentAPI, IGameTimer): def StartLearning(self) -> Future[bool]: return self.__pool.submit(self.__logic.StartLearning) - def StartTreatMate(self, mateID: int) -> Future[bool]: - return self.__pool.submit(self.__logic.StartTreatMate, mateID) + def StartEncourageMate(self, mateID: int) -> Future[bool]: + return self.__pool.submit(self.__logic.StartEncourageMate, mateID) - def StartRescueMate(self, mateID: int) -> Future[bool]: - return self.__pool.submit(self.__logic.StartRescueMate, mateID) + def StartRouseMate(self, mateID: int) -> Future[bool]: + return self.__pool.submit(self.__logic.StartRouseMate, mateID) def GetSelfInfo(self) -> THUAI6.Student: return cast(THUAI6.Student, self.__logic.GetSelfInfo()) diff --git a/CAPI/python/PyAPI/Communication.py b/CAPI/python/PyAPI/Communication.py index 41c201f..adeea1f 100644 --- a/CAPI/python/PyAPI/Communication.py +++ b/CAPI/python/PyAPI/Communication.py @@ -102,7 +102,7 @@ class Communication: else: return learnResult.act_success - def StartTreatMate(self, playerID: int, mateID: int) -> bool: + def StartEncourageMate(self, playerID: int, mateID: int) -> bool: try: helpResult = self.__THUAI6Stub.StartTreatMate( THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID)) @@ -111,7 +111,7 @@ class Communication: else: return helpResult.act_success - def StartRescueMate(self, playerID: int, mateID: int) -> bool: + def StartRouseMate(self, playerID: int, mateID: int) -> bool: try: helpResult = self.__THUAI6Stub.StartRescueMate( THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID)) diff --git a/CAPI/python/PyAPI/DebugAPI.py b/CAPI/python/PyAPI/DebugAPI.py index 5e18c5f..6901474 100644 --- a/CAPI/python/PyAPI/DebugAPI.py +++ b/CAPI/python/PyAPI/DebugAPI.py @@ -414,31 +414,31 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): return self.__pool.submit(logStart) - def StartTreatMate(self, mateID: int) -> Future[bool]: + def StartEncourageMate(self, mateID: int) -> Future[bool]: self.__logger.info( - f"StartTreatMate: called at {self.__GetTime()}ms") + f"StartEncourageMate: called at {self.__GetTime()}ms") - def logStartTreatMate() -> bool: - result = self.__logic.StartTreatMate(mateID) + def logStartEncourageMate() -> bool: + result = self.__logic.StartEncourageMate(mateID) if not result: self.__logger.warning( - f"StartTreatMate: failed at {self.__GetTime()}ms") + f"StartEncourageMate: failed at {self.__GetTime()}ms") return result - return self.__pool.submit(logStartTreatMate) + return self.__pool.submit(logStartEncourageMate) - def StartRescueMate(self, mateID: int) -> Future[bool]: + def StartRouseMate(self, mateID: int) -> Future[bool]: self.__logger.info( - f"StartRescueMate: called at {self.__GetTime()}ms") + f"StartRouseMate: called at {self.__GetTime()}ms") - def logStartRescueMate() -> bool: - result = self.__logic.StartRescueMate(mateID) + def logStartRouseMate() -> bool: + result = self.__logic.StartRouseMate(mateID) if not result: self.__logger.warning( - f"StartRescueMate: failed at {self.__GetTime()}ms") + f"StartRouseMate: failed at {self.__GetTime()}ms") return result - return self.__pool.submit(logStartRescueMate) + return self.__pool.submit(logStartRouseMate) def GetSelfInfo(self) -> THUAI6.Student: return cast(THUAI6.Student, self.__logic.GetSelfInfo()) diff --git a/CAPI/python/PyAPI/Interface.py b/CAPI/python/PyAPI/Interface.py index 9566363..07066f0 100644 --- a/CAPI/python/PyAPI/Interface.py +++ b/CAPI/python/PyAPI/Interface.py @@ -147,11 +147,11 @@ class ILogic(metaclass=ABCMeta): pass @abstractmethod - def StartTreatMate(self, mateID: int) -> bool: + def StartEncourageMate(self, mateID: int) -> bool: pass @abstractmethod - def StartRescueMate(self, mateID: int) -> bool: + def StartRouseMate(self, mateID: int) -> bool: pass @@ -350,11 +350,11 @@ class IStudentAPI(IAPI, metaclass=ABCMeta): pass @abstractmethod - def StartTreatMate(self, mateID: int) -> Future[bool]: + def StartEncourageMate(self, mateID: int) -> Future[bool]: pass @abstractmethod - def StartRescueMate(self, mateID: int) -> Future[bool]: + def StartRouseMate(self, mateID: int) -> Future[bool]: pass @abstractmethod diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index 783c23d..b4e4937 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -1,4 +1,9 @@ -class Constants(): +class NoInstance: + def __call__(self): + raise TypeError("This class cannot be instantiated.") + + +class Constants(NoInstance): numOfGridPerCell = 1000 # 单位坐标数 rows = 50 # 地图行数 cols = 50 # 地图列数 diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index 71f549e..205eb95 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -224,13 +224,13 @@ class Logic(ILogic): self.__logger.debug("Called StartLearning") return self.__comm.StartLearning(self.__playerID) - def StartTreatMate(self, mateID: int) -> bool: - self.__logger.debug("Called StartTreatMate") - return self.__comm.StartTreatMate(self.__playerID, mateID) + def StartEncourageMate(self, mateID: int) -> bool: + self.__logger.debug("Called StartEncourageMate") + return self.__comm.StartEncourageMate(self.__playerID, mateID) - def StartRescueMate(self, mateID: int) -> bool: - self.__logger.debug("Called StartRescueMate") - return self.__comm.StartRescueMate(self.__playerID, mateID) + def StartRouseMate(self, mateID: int) -> bool: + self.__logger.debug("Called StartRouseMate") + return self.__comm.StartRouseMate(self.__playerID, mateID) def Attack(self, angle: float) -> bool: self.__logger.debug("Called Trick") From 8b6e9fcdc4a30a0e5bde135f42b6c80a803dc263 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Tue, 11 Apr 2023 19:45:51 +0800 Subject: [PATCH 18/37] feat(CAPI): :sparkles: add new tricker type --- CAPI/cpp/API/include/structures.h | 3 ++- CAPI/cpp/API/include/utils.hpp | 4 ++-- CAPI/cpp/proto/MessageType.pb.cc | 11 +++++------ CAPI/cpp/proto/MessageType.pb.h | 4 ++-- CAPI/python/PyAPI/structures.py | 2 ++ CAPI/python/PyAPI/utils.py | 6 ++++-- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CAPI/cpp/API/include/structures.h b/CAPI/cpp/API/include/structures.h index 3b23b1e..a3d859d 100644 --- a/CAPI/cpp/API/include/structures.h +++ b/CAPI/cpp/API/include/structures.h @@ -94,7 +94,7 @@ namespace THUAI6 Assassin = 1, Klee = 2, ANoisyPerson = 3, - TrickerType4 = 4, + Idol = 4, }; // 学生Buff类型 @@ -292,6 +292,7 @@ namespace THUAI6 {TrickerType::Assassin, "Assassin"}, {TrickerType::Klee, "Klee"}, {TrickerType::ANoisyPerson, "ANoisyPerson"}, + {TrickerType::Idol, "Idol"}, }; inline std::map playerStateDict{ diff --git a/CAPI/cpp/API/include/utils.hpp b/CAPI/cpp/API/include/utils.hpp index fb06ece..2153925 100644 --- a/CAPI/cpp/API/include/utils.hpp +++ b/CAPI/cpp/API/include/utils.hpp @@ -119,7 +119,7 @@ namespace Proto2THUAI6 {protobuf::TrickerType::ASSASSIN, THUAI6::TrickerType::Assassin}, {protobuf::TrickerType::KLEE, THUAI6::TrickerType::Klee}, {protobuf::TrickerType::A_NOISY_PERSON, THUAI6::TrickerType::ANoisyPerson}, - {protobuf::TrickerType::TRICKERTYPE4, THUAI6::TrickerType::TrickerType4}, + {protobuf::TrickerType::IDOL, THUAI6::TrickerType::Idol}, }; inline std::map studentBuffTypeDict{ @@ -385,7 +385,7 @@ namespace THUAI62Proto {THUAI6::TrickerType::Assassin, protobuf::TrickerType::ASSASSIN}, {THUAI6::TrickerType::Klee, protobuf::TrickerType::KLEE}, {THUAI6::TrickerType::ANoisyPerson, protobuf::TrickerType::A_NOISY_PERSON}, - {THUAI6::TrickerType::TrickerType4, protobuf::TrickerType::TRICKERTYPE4}, + {THUAI6::TrickerType::Idol, protobuf::TrickerType::IDOL}, }; // inline std::map trickerBuffTypeDict{ diff --git a/CAPI/cpp/proto/MessageType.pb.cc b/CAPI/cpp/proto/MessageType.pb.cc index af6c6cc..83acf36 100644 --- a/CAPI/cpp/proto/MessageType.pb.cc +++ b/CAPI/cpp/proto/MessageType.pb.cc @@ -62,17 +62,16 @@ const char descriptor_table_protodef_MessageType_2eproto[] PROTOBUF_SECTION_VARI "\016TRICKER_PLAYER\020\002*q\n\013StudentType\022\025\n\021NULL" "_STUDENT_TYPE\020\000\022\013\n\007ATHLETE\020\001\022\013\n\007TEACHER\020" "\002\022\026\n\022STRAIGHT_A_STUDENT\020\003\022\t\n\005ROBOT\020\004\022\016\n\n" - "TECH_OTAKU\020\005*b\n\013TrickerType\022\025\n\021NULL_TRIC" + "TECH_OTAKU\020\005*Z\n\013TrickerType\022\025\n\021NULL_TRIC" "KER_TYPE\020\000\022\014\n\010ASSASSIN\020\001\022\010\n\004KLEE\020\002\022\022\n\016A_" - "NOISY_PERSON\020\003\022\020\n\014TRICKERTYPE4\020\004*P\n\tGame" - "State\022\023\n\017NULL_GAME_STATE\020\000\022\016\n\nGAME_START" - "\020\001\022\020\n\014GAME_RUNNING\020\002\022\014\n\010GAME_END\020\003b\006prot" - "o3"; + "NOISY_PERSON\020\003\022\010\n\004IDOL\020\004*P\n\tGameState\022\023\n" + "\017NULL_GAME_STATE\020\000\022\016\n\nGAME_START\020\001\022\020\n\014GA" + "ME_RUNNING\020\002\022\014\n\010GAME_END\020\003b\006proto3"; static ::_pbi::once_flag descriptor_table_MessageType_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_MessageType_2eproto = { false, false, - 1482, + 1474, descriptor_table_protodef_MessageType_2eproto, "MessageType.proto", &descriptor_table_MessageType_2eproto_once, diff --git a/CAPI/cpp/proto/MessageType.pb.h b/CAPI/cpp/proto/MessageType.pb.h index 7f7cfc9..1de7f3b 100644 --- a/CAPI/cpp/proto/MessageType.pb.h +++ b/CAPI/cpp/proto/MessageType.pb.h @@ -368,13 +368,13 @@ namespace protobuf ASSASSIN = 1, KLEE = 2, A_NOISY_PERSON = 3, - TRICKERTYPE4 = 4, + IDOL = 4, TrickerType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(), TrickerType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max() }; bool TrickerType_IsValid(int value); constexpr TrickerType TrickerType_MIN = NULL_TRICKER_TYPE; - constexpr TrickerType TrickerType_MAX = TRICKERTYPE4; + constexpr TrickerType TrickerType_MAX = IDOL; constexpr int TrickerType_ARRAYSIZE = TrickerType_MAX + 1; const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* TrickerType_descriptor(); diff --git a/CAPI/python/PyAPI/structures.py b/CAPI/python/PyAPI/structures.py index 5920f9e..9b3a6ff 100644 --- a/CAPI/python/PyAPI/structures.py +++ b/CAPI/python/PyAPI/structures.py @@ -7,6 +7,7 @@ if sys.version_info < (3, 9): else: Tuple = tuple + class GameState(Enum): NullGameState = 0 GameStart = 1 @@ -76,6 +77,7 @@ class TrickerType(Enum): Assassin = 1 Klee = 2 ANoisyPerson = 3 + Idol = 4 class StudentBuffType(Enum): diff --git a/CAPI/python/PyAPI/utils.py b/CAPI/python/PyAPI/utils.py index 305ad7b..b90913a 100644 --- a/CAPI/python/PyAPI/utils.py +++ b/CAPI/python/PyAPI/utils.py @@ -111,7 +111,8 @@ class Proto2THUAI6(NoInstance): MessageType.NULL_TRICKER_TYPE: THUAI6.TrickerType.NullTrickerType, MessageType.ASSASSIN: THUAI6.TrickerType.Assassin, MessageType.KLEE: THUAI6.TrickerType.Klee, - MessageType.A_NOISY_PERSON: THUAI6.TrickerType.ANoisyPerson, } + MessageType.A_NOISY_PERSON: THUAI6.TrickerType.ANoisyPerson, + MessageType.IDOL: THUAI6.TrickerType.Idol, } studentBuffTypeDict: Final[dict] = { MessageType.NULL_SBUFF_TYPE: THUAI6.StudentBuffType.NullStudentBuffType, @@ -314,7 +315,8 @@ class THUAI62Proto(NoInstance): THUAI6.TrickerType.NullTrickerType: MessageType.NULL_TRICKER_TYPE, THUAI6.TrickerType.Assassin: MessageType.ASSASSIN, THUAI6.TrickerType.Klee: MessageType.KLEE, - THUAI6.TrickerType.ANoisyPerson: MessageType.A_NOISY_PERSON, } + THUAI6.TrickerType.ANoisyPerson: MessageType.A_NOISY_PERSON, + THUAI6.TrickerType.Idol: MessageType.IDOL, } propTypeDict: Final[dict] = { THUAI6.PropType.NullPropType: MessageType.NULL_PROP_TYPE, From e81f46993ebde97f0893be6309b66307503dad0b Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Tue, 11 Apr 2023 23:09:57 +0800 Subject: [PATCH 19/37] build: :construction: a little help about CAPI --- CAPI/python/PyAPI/constants.py | 252 +++++++++--------- .../SkillManager/SkillManager.ActiveSkill.cs | 1 - logic/Preparation/Utility/GameData.cs | 4 +- logic/规则Logic.md | 54 ++-- 4 files changed, 156 insertions(+), 155 deletions(-) diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index b4e4937..ee7777e 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -20,8 +20,8 @@ class Constants(NoInstance): numOfRequiredClassroomForHiddenGate = 3 # 打开隐藏门需要完成的教室数量 # 人物属性相关 - basicTreatSpeed = 100 - basicFixSpeed = 123 + basicEncourageSpeed = 100 + basicLearnSpeed = 123 basicSpeedOfOpeningOrLocking = 4000 basicStudentSpeedOfClimbingThroughWindows = 611 basicTrickerSpeedOfClimbingThroughWindows = 1270 @@ -31,8 +31,8 @@ class Constants(NoInstance): basicMaxGamingAddiction = 60000 BeginGamingAddiction = 20900 MidGamingAddiction = 40300 - basicTreatmentDegree = 1500000 - basicTimeOfRescue = 1000 + basicEncouragementDegree = 1500000 + basicTimeOfRouse = 1000 basicStudentSpeed = 1270 basicTrickerSpeed = 1504 @@ -68,122 +68,118 @@ class Constants(NoInstance): remainHpWhenAddLife = 100 class Assassin: - moveSpeed = 1.1 - maxHp = 1.0 - concealment = 1.5 - alertnessRadius = 1.3 - viewRange = 1.2 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 1.0 - speedOfOpenChest = 1.0 + moveSpeed = 1.1*basicTrickerSpeed + concealment = 1.5*basicConcealment + alertnessRadius = 1.3*basicTrickerAlertnessRadius + viewRange = 1.2*basicTrickerViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 1.0*basicTrickerSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class Klee: - moveSpeed = 1.0 - maxHp = 1.0 - concealment = 1.0 - alertnessRadius = 1.0 - viewRange = 1.0 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 1.0 - speedOfOpenChest = 1.1 + moveSpeed = 1.0*basicTrickerSpeed + concealment = 1.0*basicConcealment + alertnessRadius = 1.0*basicTrickerAlertnessRadius + viewRange = 1.0*basicTrickerViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 1.0*basicTrickerSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.1*basicSpeedOfOpenChest class ANoisyPerson: - moveSpeed = 1.07 - maxHp = 1.2 - concealment = 0.8 - alertnessRadius = 0.9 - viewRange = 1.0 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 1.1 - speedOfOpenChest = 1.1 + moveSpeed = 1.07*basicTrickerSpeed + concealment = 0.8*basicConcealment + alertnessRadius = 0.9*basicTrickerAlertnessRadius + viewRange = 1.0*basicTrickerViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 1.1*basicTrickerSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.1*basicSpeedOfOpenChest class Idol: - moveSpeed = 1.0 - maxHp = 1.0 - concealment = 0.75 - alertnessRadius = 1.0 - viewRange = 1.1 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 1.0 - speedOfOpenChest = 1.0 + moveSpeed = 1.0*basicTrickerSpeed + concealment = 0.75*basicConcealment + alertnessRadius = 1.0*basicTrickerAlertnessRadius + viewRange = 1.1*basicTrickerViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 1.0*basicTrickerSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class Athlete: - moveSpeed = 1.1 - maxHp = 1.0 - maxAddiction = 0.9 - fixSpeed = 0.6 - treatSpeed = 0.8 - concealment = 0.9 - alertnessRadius = 1.0 - viewRange = 1.1 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 1.2 - speedOfOpenChest = 1.0 + moveSpeed = 1.1*basicStudentSpeed + maxHp = 1.0*basicHp + maxAddiction = 0.9*basicMaxGamingAddiction + LearnSpeed = 0.6*basicLearnSpeed + EncourageSpeed = 0.8*basicEncourageSpeed + concealment = 0.9*basicConcealment + alertnessRadius = 1.0*basicStudentAlertnessRadius + viewRange = 1.1*basicStudentViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 1.2*basicStudentSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class Teacher: - moveSpeed = 0.75 - maxHp = 10.0 - maxAddiction = 10.0 - fixSpeed = 0.0 - treatSpeed = 0.7 - concealment = 0.5 - alertnessRadius = 0.5 - viewRange = 0.9 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 0.5 - speedOfOpenChest = 1.0 + moveSpeed = 0.75*basicStudentSpeed + maxHp = 10.0*basicHp + maxAddiction = 10.0*basicMaxGamingAddiction + LearnSpeed = 0.0*basicLearnSpeed + EncourageSpeed = 0.7*basicEncourageSpeed + concealment = 0.5*basicConcealment + alertnessRadius = 0.5*basicStudentAlertnessRadius + viewRange = 0.9*basicStudentViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 0.5*basicStudentSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class StraightAStudent: - moveSpeed = 0.8 - maxHp = 1.1 - maxAddiction = 1.3 - fixSpeed = 1.1 - treatSpeed = 0.8 - concealment = 0.9 - alertnessRadius = 0.9 - viewRange = 0.9 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 0.83333 - speedOfOpenChest = 1.0 + moveSpeed = 0.8*basicStudentSpeed + maxHp = 1.1*basicHp + maxAddiction = 1.3*basicMaxGamingAddiction + LearnSpeed = 1.1*basicLearnSpeed + EncourageSpeed = 0.8*basicEncourageSpeed + concealment = 0.9*basicConcealment + alertnessRadius = 0.9*basicStudentAlertnessRadius + viewRange = 0.9*basicStudentViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 0.83333*basicStudentSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class Robot: - moveSpeed = 1.0 - maxHp = 0.4 - maxAddiction = 0.0 - fixSpeed = 1.0 - treatSpeed = 0.8 - concealment = 1.0 - alertnessRadius = 1.0 - viewRange = 1.0 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 0.0016 - speedOfOpenChest = 1.0 + moveSpeed = 1.0*basicStudentSpeed + maxHp = 0.4*basicHp + maxAddiction = 0.0*basicMaxGamingAddiction + LearnSpeed = 1.0*basicLearnSpeed + EncourageSpeed = 0.8*basicEncourageSpeed + concealment = 1.0*basicConcealment + alertnessRadius = 1.0*basicStudentAlertnessRadius + viewRange = 1.0*basicStudentViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 0.0016*basicStudentSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class TechOtaku: - moveSpeed = 0.75 - maxHp = 0.9 - maxAddiction = 1.1 - fixSpeed = 1.1 - treatSpeed = 0.9 - concealment = 1.0 - alertnessRadius = 1.0 - viewRange = 0.9 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 0.75 - speedOfOpenChest = 1.0 + moveSpeed = 0.75*basicStudentSpeed + maxHp = 0.9*basicHp + maxAddiction = 1.1*basicMaxGamingAddiction + LearnSpeed = 1.1*basicLearnSpeed + EncourageSpeed = 0.9*basicEncourageSpeed + concealment = 1.0*basicConcealment + alertnessRadius = 1.0*basicStudentAlertnessRadius + viewRange = 0.9*basicStudentViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 0.75*basicStudentSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest class Sunshine: - moveSpeed = 1.0 - maxHp = 1.0667 - maxAddiction = 1.1 - fixSpeed = 1.0 - treatSpeed = 2.0 - concealment = 1.0 - alertnessRadius = 1.0 - viewRange = 1.0 - speedOfOpeningOrLocking = 1.0 - speedOfClimbingThroughWindows = 1.0 - speedOfOpenChest = 1.0 + moveSpeed = 1.0*basicStudentSpeed + maxHp = 1.0667*basicHp + maxAddiction = 1.1*basicMaxGamingAddiction + LearnSpeed = 1.0*basicLearnSpeed + EncourageSpeed = 2.0*basicEncourageSpeed + concealment = 1.0*basicConcealment + alertnessRadius = 1.0*basicStudentAlertnessRadius + viewRange = 1.0*basicStudentViewRange + speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking + speedOfClimbingThroughWindows = 1.0*basicStudentSpeedOfClimbingThroughWindows + speedOfOpenChest = 1.0*basicSpeedOfOpenChest # 技能相关 maxNumOfSkill = 3 @@ -204,53 +200,53 @@ class Constants(NoInstance): timeOfAddingSpeedWhenInspire = 6000 class CanBeginToCharge: - skillCD = 0.8 - durationTime = 0.5 + skillCD = 0.8*commonSkillCD + durationTime = 0.5*commonSkillTime class BecomeInvisible: - skillCD = 2.0 - durationTime = 0.6 + skillCD = 2.0*commonSkillCD + durationTime = 0.6*commonSkillTime class Punish: - skillCD = 1.0 - durationTime = 0.0 + skillCD = 1.0*commonSkillCD + durationTime = 0.0*commonSkillTime class Rouse: - skillCD = 2.0 - durationTime = 0.0 + skillCD = 2.0*commonSkillCD + durationTime = 0.0*commonSkillTime class Encourage: - skillCD = 2.0 - durationTime = 0.0 + skillCD = 2.0*commonSkillCD + durationTime = 0.0*commonSkillTime class Inspire: - skillCD = 2.0 - durationTime = 0.0 + skillCD = 2.0*commonSkillCD + durationTime = 0.0*commonSkillTime class Howl: - skillCD = 0.8333 - durationTime = 0.0 + skillCD = 0.8333*commonSkillCD + durationTime = 0.0*commonSkillTime class ShowTime: - skillCD = 3.0 - durationTime = 1.0 + skillCD = 3.0*commonSkillCD + durationTime = 1.0*commonSkillTime class JumpyBomb: - skillCD = 0.5 - durationTime = 0.3 + skillCD = 0.5*commonSkillCD + durationTime = 0.3*commonSkillTime class UseKnife: - skillCD = 1.0 - durationTime = 0.1 + skillCD = 1.0*commonSkillCD + durationTime = 0.1*commonSkillTime class UseRobot: - skillCD = 0.0017 - durationTime = 0.0 + skillCD = 0.0017*commonSkillCD + durationTime = 0.0*commonSkillTime class WriteAnswers: - skillCD = 1.0 - durationTime = 0.0 + skillCD = 1.0*commonSkillCD + durationTime = 0.0*commonSkillTime class SummonGolem: - skillCD = 1.0 - durationTime = 0.0 + skillCD = 1.0*commonSkillCD + durationTime = 0.0*commonSkillTime diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 20bb373..2d02ea9 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -4,7 +4,6 @@ using Preparation.Interface; using Preparation.Utility; using System; using Timothy.FrameRateTask; -using Google.Protobuf.Compiler; namespace Gaming { diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 9e7d1cc..ecec57d 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -107,9 +107,9 @@ namespace Preparation.Utility #if DEBUG public const int basicStudentMoveSpeed = 9000;// 基本移动速度,单位:s-1 #else - public const int basicStudentMoveSpeed = 1270; + public const int basicStudentMoveSpeed = 1500; #endif - public const int basicGhostMoveSpeed = (int)(basicStudentMoveSpeed * 45.0 / 38); + public const int basicGhostMoveSpeed = (int)(basicStudentMoveSpeed * 1.2); public const int characterMaxSpeed = 12000; // 最大速度 diff --git a/logic/规则Logic.md b/logic/规则Logic.md index 55456a2..04304e0 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -173,20 +173,20 @@ ### 捣蛋鬼 -| 捣蛋鬼职业 | 基本量 | Assassin | Klee | 喧哗者ANoisyPerson | -| :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | -| 移动速度/s | 1,503 | 1.1 | 1 | 1.07 | -| 隐蔽度 | 1.0 | 1.5 | 1 | 0.8 | -| 警戒范围 | 17000 | 1.3 | 1 | 0.9 | -| 视野范围 | 15000 | 1.2 | 1 | 1 | -| 开锁门速度 | 4000 | 1 | 1 | 1 | -| 翻窗速度 | 1270 | 1 | 1 | 1.1 | -| 翻箱速度 | 1000 | 1 | 1.1 | 1 | - -#### 刺客 -- 普通攻击为 搞蛋鬼的一般攻击 +| 捣蛋鬼职业 | Assassin | Klee | 喧哗者ANoisyPerson | Idol | +| :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | +| 移动速度/s | 1980 | 1800 | 1926 | 1,800 | +| 隐蔽度 | 1.5 | 1 | 0.8 | 0.75| +| 警戒范围 | 22,100 | 17000 | 15,300 | 17000 +| 视野范围 | 18,000 | 15000 | 15000 | 16,500| +| 开锁门速度 | 4000 | 4000 | 4000 |4000 | +| 翻窗速度 | 1270 | 1270 | 1,397 | 1270| +| 翻箱速度 | 1000 | 1100 | 1000 |1000| + +#### Assassin +- 普通攻击为 CommonAttackOfGhost - 主动技能 - - 隐身 + - 隐身 BecomeInvisible - CD:60s 持续时间:6s - 在持续时间内玩家隐身 - 使用瞬间得分 @@ -196,25 +196,31 @@ - 不直接得分 #### Klee -- 普通攻击为 搞蛋鬼的一般攻击 +- 普通攻击为 CommonAttackOfGhost - 主动技能 - - 蹦蹦炸弹 + - 蹦蹦炸弹 JumpyBomb - CD:15s 持续时间:3s - 在持续时间内,攻击类型变为蹦蹦炸弹 - 当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上90°,270° 发出2个小炸弹 - 2个小炸弹运动停止前会因为碰撞爆炸,停止运动后学生碰撞会造成眩晕3.07s - 不直接得分,通过眩晕等获得对应得分 -#### 喧哗者 -- 普通攻击为 搞蛋鬼的一般攻击 +#### 喧哗者ANoisyPerson +- 普通攻击为 CommonAttackOfGhost - 主动技能 - - 嚎叫 + - 嚎叫 Howl - CD:25s - 使用瞬间,在视野半径范围内(不是可视区域)的学生被眩晕6110ms,自己进入3070ms的后摇 - 通过眩晕获得对应得分 - 特性 - 在场所有学生Bgm系统被设为无用的值 +#### Idol +- 普通攻击为 CommonAttackOfGhost +- 主动技能 + - ShowTime + - CD: 90s 持续时间:10s + - 持续时间内每一帧向所有学生发送向自己移动的指令。 ### 学生(&老师) @@ -234,14 +240,14 @@ #### 运动员 - 主动技能 - - 冲撞 + - 冲撞 CanBeginToCharge - CD:24s 持续时间:5s - 在持续时间内,速度变为三倍,期间撞到捣蛋鬼,会导致捣蛋鬼眩晕7.22s,学生眩晕2.09s - 通过眩晕获得对应得分 #### 教师 - 主动技能 - - 惩罚 + - 惩罚 Punish - CD:30s - 使用瞬间,在可视范围内的使用技能状态中、攻击前后摇的捣蛋鬼会被眩晕(3070)ms, - 通过眩晕获得对应得分 @@ -254,22 +260,22 @@ - 当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为0.3%/ms - 受到攻击(并非伤害)或学习或进入不可接受治疗状态(包括翻窗)学习进度清零 - 主动技能5 - - 写答案 + - 写答案 WriteAnswers - CD:30s - 使用瞬间,对于可互动范围内的一台电机增加这个学习进度 - 通过修机获得对应得分 #### 开心果 - 主动技能 - - 唤醒 + - 唤醒 Rouse - CD:60s - 使用瞬间,唤醒可视范围内一个沉迷中的人 - 通过唤醒获得对应得分 - - 勉励 + - 勉励 Encourage - CD:60s - 使用瞬间,勉励完成可视范围内一个毅力不足的人 - 通过勉励获得对应得分 - - 鼓舞 + - 鼓舞 Inspire - CD:60s - 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff - 每鼓舞一个学生得分10 From dfe9dc621090f2492719b9cc3a03eb667def6de3 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 02:01:30 +0800 Subject: [PATCH 20/37] build: :construction: issue the GameRules_cpp.md --- CAPI/cpp/API/include/constants.h | 15 +- CAPI/python/PyAPI/constants.py | 17 +- logic/Client/MainWindow.xaml.cs | 9 +- .../GameClass/GameObj/Bullet/Bullet.Ghost.cs | 4 +- logic/{规则Logic.md => GameRules_cpp.md} | 151 +++++++++++------- logic/Gaming/ActionManager.cs | 6 +- logic/Gaming/CharacterManager .cs | 2 +- logic/Gaming/PropManager.cs | 2 +- .../SkillManager/SkillManager.ActiveSkill.cs | 13 +- logic/Preparation/Interface/ISkill.cs | 4 +- logic/Preparation/Utility/GameData.cs | 40 ++--- 11 files changed, 153 insertions(+), 110 deletions(-) rename logic/{规则Logic.md => GameRules_cpp.md} (81%) diff --git a/CAPI/cpp/API/include/constants.h b/CAPI/cpp/API/include/constants.h index 6407b3a..b663460 100644 --- a/CAPI/cpp/API/include/constants.h +++ b/CAPI/cpp/API/include/constants.h @@ -49,6 +49,7 @@ namespace Constants SCCI int basicTrickerAlertnessRadius = 17 * numOfGridPerCell; SCCI int basicStudentViewRange = 10 * numOfGridPerCell; SCCI int basicTrickerViewRange = 15 * numOfGridPerCell; + SCCI int PinningDownRange = 5 * numOfGridPerCell; SCCI int maxNumOfProp = 3; @@ -216,13 +217,13 @@ namespace Constants SCCI int commonSkillCD = 30000; // 普通技能标准冷却时间 SCCI int commonSkillTime = 10000; // 普通技能标准持续时间 - SCCI int timeOfTrickerFaintingWhenCharge = 7220; - SCCI int timeOfStudentFaintingWhenCharge = 2090; + SCCI int timeOfTrickerStunnedWhenCharge = 7220; + SCCI int timeOfStudentStunnedWhenCharge = 2090; - SCCI int timeOfTrickerFaintingWhenPunish = 3070; + SCCI int timeOfTrickerStunnedWhenPunish = 3070; - SCCI int timeOfTrickerSwingingAfterHowl = 3070; - SCCI int timeOfStudentFaintingWhenHowl = 6110; + SCCI int timeOfTrickerSwingingAfterHowl = 800; + SCCI int timeOfStudentStunnedWhenHowl = 5500; SCCI int timeOfStunnedWhenJumpyDumpty = 3070; @@ -230,8 +231,8 @@ namespace Constants SCCI int timeOfAddingSpeedWhenInspire = 6000; struct CanBeginToCharge { - SCCI double skillCD = 0.8; - SCCI double durationTime = 0.5; + SCCI double skillCD = 4 / 3; + SCCI double durationTime = 1; }; struct BecomeInvisible diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index ee7777e..ded61af 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -44,6 +44,7 @@ class Constants(NoInstance): basicTrickerAlertnessRadius = 17 * numOfGridPerCell basicStudentViewRange = 10 * numOfGridPerCell basicTrickerViewRange = 15 * numOfGridPerCell + PinningDownRange = 5 * numOfPosGridPerCell maxNumOfProp = 3 @@ -186,13 +187,13 @@ class Constants(NoInstance): commonSkillCD = 30000 # 普通技能标准冷却时间 commonSkillTime = 10000 # 普通技能标准持续时间 - timeOfTrickerFaintingWhenCharge = 7220 - timeOfStudentFaintingWhenCharge = 2090 + timeOfTrickerStunnedWhenCharge = 7220 + timeOfStudentStunnedWhenCharge = 2090 - timeOfTrickerFaintingWhenPunish = 3070 + timeOfTrickerStunnedWhenPunish = 3070 - timeOfTrickerSwingingAfterHowl = 3070 - timeOfStudentFaintingWhenHowl = 6110 + timeOfTrickerSwingingAfterHowl = 800 + timeOfStudentStunnedWhenHowl = 5500 timeOfStunnedWhenJumpyDumpty = 3070 @@ -204,8 +205,8 @@ class Constants(NoInstance): durationTime = 0.5*commonSkillTime class BecomeInvisible: - skillCD = 2.0*commonSkillCD - durationTime = 0.6*commonSkillTime + skillCD = 4*commonSkillCD/3 + durationTime = commonSkillTime class Punish: skillCD = 1.0*commonSkillCD @@ -225,7 +226,7 @@ class Constants(NoInstance): class Howl: skillCD = 0.8333*commonSkillCD - durationTime = 0.0*commonSkillTime + durationTime = 0*commonSkillTime class ShowTime: skillCD = 3.0*commonSkillCD diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 3c437a8..3760689 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -807,11 +807,11 @@ namespace Client { Ellipse icon = new() { - Width = 10, - Height = 10, + Width = 2*bulletRadiusTimes*unitWidth, + Height = 2*bulletRadiusTimes*unitHeight, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, - Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth / 2, data.X * unitHeight / 1000.0 - unitHeight / 2, 0, 0), + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth*bulletRadiusTimes, data.X * unitHeight / 1000.0 - unitHeight *bulletRadiusTimes, 0, 0), Fill = Brushes.Red, }; switch (data.Type) @@ -849,7 +849,7 @@ namespace Client } case Protobuf.BulletType.JumpyDumpty: { - Ellipse icon = new Ellipse(); + Ellipse icon = new(); double bombRange = data.BombRange / 1000; icon.Width = bombRange * unitWidth; icon.Height = bombRange * unitHeight; @@ -1429,6 +1429,7 @@ namespace Client bool isEmergencyDrawed = false; bool isDataFixed = false; const double radiusTimes = 1.0 * Preparation.Utility.GameData.characterRadius / Preparation.Utility.GameData.numOfPosGridPerCell; + const double bulletRadiusTimes =1.0* GameData.bulletRadius/ Preparation.Utility.GameData.numOfPosGridPerCell; private int[] totalLife = new int[4] { 100, 100, 100, 100 }, totalDeath = new int[4] { 100, 100, 100, 100 }; private int[,] coolTime = new int[3, 5] { { 100, 100, 100, 100, 100 }, { 100, 100, 100, 100, 100 }, { 100, 100, 100, 100, 100 } }; } diff --git a/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs index 8760d02..32d0129 100644 --- a/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs +++ b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs @@ -69,10 +69,10 @@ namespace GameClass.GameObj ap = value; } } - public override int Speed => GameData.basicBulletMoveSpeed * 2; + public override int Speed => GameData.basicBulletMoveSpeed * 25 / 10; public override bool IsRemoteAttack => true; - public override int CastTime => GameData.basicCastTime; + public override int CastTime => GameData.basicCastTime * 4 / 5; public override int Backswing => 0; public override int RecoveryFromHit => 0; public const int cd = GameData.basicBackswing / 2; diff --git a/logic/规则Logic.md b/logic/GameRules_cpp.md similarity index 81% rename from logic/规则Logic.md rename to logic/GameRules_cpp.md index 04304e0..ec8c967 100644 --- a/logic/规则Logic.md +++ b/logic/GameRules_cpp.md @@ -1,13 +1,63 @@ -# 规则Logic - -## 通过接口了解规则喵 +# 规则(C++) +- [规则(C++)](#规则c) + - [接口与规则](#接口与规则) + - [地图](#地图) + - [移动](#移动) + - [使用技能](#使用技能) + - [人物](#人物) + - [攻击](#攻击) + - [交互](#交互) + - [破译与毕业](#破译与毕业) + - [勉励(Treat)](#勉励treat) + - [沉迷与唤醒](#沉迷与唤醒) + - [门](#门) + - [窗](#窗) + - [箱子](#箱子) + - [Bgm](#bgm) + - [队内信息](#队内信息) + - [线程控制](#线程控制) + - [信息获取](#信息获取) + - [道具](#道具) + - [得分](#得分) + - [捣蛋鬼](#捣蛋鬼) + - [学生](#学生) + - [职业与技能](#职业与技能) + - [捣蛋鬼](#捣蛋鬼-1) + - [Assassin](#assassin) + - [Klee](#klee) + - [喧哗者ANoisyPerson](#喧哗者anoisyperson) + - [Idol](#idol) + - [学生(\&老师)](#学生老师) + - [运动员](#运动员) + - [教师](#教师) + - [学霸](#学霸) + - [开心果](#开心果) + - [辅助函数](#辅助函数) + - [接口一览](#接口一览) + - [细则](#细则) + - [特殊说明](#特殊说明) + - [移动](#移动-1) + - [人物](#人物-1) + - [初始状态](#初始状态) + - [道具](#道具-1) + - [交互](#交互-1) + - [破译与毕业](#破译与毕业-1) + - [攻击](#攻击-1) + - [沉迷与唤醒](#沉迷与唤醒-1) + - [门](#门-1) + - [窗](#窗-1) + - [箱子](#箱子-1) + - [信息获取](#信息获取-1) + - [键鼠控制](#键鼠控制) + +## 接口与规则 ### 地图 - 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。 - **x坐标轴正方向竖直向下,y坐标轴正方向水平向右**; - **极坐标以x坐标轴为极轴,角度逆时针为正方向**。 - 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到: - - 略 + - $$CellX=\frac{x}{1000},CellY=\frac{y}{1000}$$ - 地图上格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 ### 移动 @@ -48,9 +98,9 @@ | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | | 子弹爆炸范围 | 0 | 0 | 1000 | 500 | | 子弹攻击距离 | 1100 | 39000 | 1100 | 2200 | -| 攻击力 | 1500000 | 1,200,000 | 1,800,000 | 900000 | -| 移动速度/s | 3700 | 7,400 | 3000 | 4300 | -| 前摇(ms) | 297 | 500 | 366 | 0 | +| 攻击力 | 1500000 | 1200000 | 1,800,000 | 900000 | +| 移动速度/s | 3700 | 9250 | 3000 | 4300 | +| 前摇(ms) | 297 | 400 | 366 | 0 | |未攻击至目标时的后摇(ms)| 800 | 0 | 3700 | 0 | |攻击至目标时的后摇(ms)| 3700 | 0 | 3700 | 0 | | CD(ms) | 800 | 400 | 3000 | - | @@ -61,7 +111,7 @@ - 交互进度每毫秒增加对应交互速度的值 - 作业,门,箱子完成/开启进度达到10000000为完成 -#### 破译与逃脱 +#### 破译与毕业 - 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。 - `std::future StartLearning()`:在教室(旁)做作业 - `std::future StartOpenGate()`:开启校门,所需时间为18秒,开启的进度不清空 @@ -136,38 +186,29 @@ | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| | Key5 | 能开启5教的门 |不得分| 能开启5教的门 |不得分| | Key6 | 能开启6教的门 |不得分| 能开启6教的门 |不得分| -| AddSpeed | 提高移动速度,持续10s |得分?| 提高移动速度,持续10s |得分?| -| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | -| AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | -| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生| -| RecoveryFromDizziness | 使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分?|使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分?| +| AddSpeed | 2倍速,持续10s | 得分10| 2倍速,持续10s |得分10| +| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分100 |10秒内得知全场玩家信息|得分10 | +| AddHpOrAp |回血750000 | 回血成功,得分10 | 10秒内下一次攻击增伤1800000|不得分 | +| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害,得分50 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内破盾,得分50 | +| RecoveryFromDizziness | 使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分30|使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分30| ## 得分 -### 屠夫 - -- [Tricker对Student造成伤害时,得伤害*100/基本伤害(1500000)分。] -- *[使用道具/技能得分]* - - 不同道具/技能有不同得分 -- 使Student进入沉迷状态时,得50分。 -- 使人类进入眩晕状态时,得25分。 -- 每淘汰一个Student,得1000分 -- 主动解除眩晕,得15分 -- 开锁门 - -### 人类 -- 修机得分 - - 人类每修n%的电机,得n分 - - 修完一台电机,额外得?分 -- [牵制得分] -- 使用道具/技能得分 - - 不同道具/技能有不同得分 -- 使屠夫进入特殊状态得分(如使之眩晕) -- 救人 -- 勉励 -- 逃脱 -- 解除眩晕 -- 开锁门 +### 捣蛋鬼 + +- 对学生造成伤害时,得伤害*100/基本伤害(1500000)分。 +- 对作业造成破坏时,每破坏n%的作业,得n分 +- 使学生进入沉迷状态时,得50分。 +- 使学生进入眩晕状态时,得20*眩晕时长(/s)分。 +- 每淘汰一个学生,得1000分 + +### 学生 +- 学生每完成n%的作业,得2n分 +- 学生与捣蛋鬼处于小于5000的距离认为在牵制状态,得(牵制时长(ms)*0.00369)分 +- 使捣蛋鬼进入眩晕状态时,得20*眩晕时长(/s)分。 +- 成功唤醒一名同学,得100分 +- 成功勉励一名同学,得50*勉励程度/基本勉励程度(1500000)分 +- 毕业,得1000分 ## 职业与技能 @@ -187,9 +228,9 @@ - 普通攻击为 CommonAttackOfGhost - 主动技能 - 隐身 BecomeInvisible - - CD:60s 持续时间:6s + - CD:40s 持续时间:10s - 在持续时间内玩家隐身 - - 使用瞬间得分 + - 使用瞬间得分15 - 使用飞刀 - CD:30s 持续时间:1s - 在持续时间内,攻击类型变为飞刀 @@ -210,7 +251,7 @@ - 主动技能 - 嚎叫 Howl - CD:25s - - 使用瞬间,在视野半径范围内(不是可视区域)的学生被眩晕6110ms,自己进入3070ms的后摇 + - 使用瞬间,在视野半径范围内(不是可视区域)的学生被眩晕5500ms,自己进入800ms的后摇 - 通过眩晕获得对应得分 - 特性 - 在场所有学生Bgm系统被设为无用的值 @@ -224,19 +265,19 @@ ### 学生(&老师) -| 学生职业 | 基本量 | 教师Teacher | 健身狂Athlete | 学霸StraightAStudent | 开心果Sunshine | -| :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | :--------------------- | -| 移动速度 | 1,270 | 3 / 4 | 1.1 | 0.8 | 1 | -| 最大毅力值 | 3000000 | 10 | 1 | 1.1 | 32/30 | -| 最大沉迷度 | 60000 | 10 | 0.9 | 1.3 | 1.1 | -| 学习一科速度/s | 1.23% | 0 | 0.6 | 1.1 | 1 | -| 勉励速度 | 100 | 0.7 | 0.8 | 0.8 | 2 | -| 隐蔽度 | 1.0 | 0.5 | 0.9 | 0.9 | 1 | -| 警戒范围 | 15000 | 0.5 | 1 | 0.9 | 1 | -| 视野范围 | 10000 | 0.9 | 1.1 | 0.9 | 1 | -| 开锁门速度 | 4000 | 1 | 1 | 1 | 1 | -| 翻窗速度 | 1270 | 0.5 | 1.2 | 10/12 | 1 | -| 翻箱速度 | 1000 | 1 | 1 | 1 | 1 | +| 学生职业 | 教师Teacher | 健身狂Athlete | 学霸StraightAStudent | 开心果Sunshine | +| :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | +| 移动速度 | 1,125 | 1,650 | 1,200 | 1,500 | +| 最大毅力值 | 30000000 | 3000000 | 3300000 | 3200000 | +| 最大沉迷度 | 600000 | 54,000 | 78,000 | 66,000 | +| 学习一科速度() | 0 | 73 | 135 | 123 | +| 勉励速度 | 70 | 80 | 80 | 200 | +| 隐蔽度 | 0.5 | 0.9 | 0.9 | 1 | +| 警戒范围 | 7500 | 15000 | 13,500 | 15000 | +| 视野范围 | 9,000 | 11000 | 9,000 | 10000 | +| 开锁门速度 | 4000 | 4000 | 4000 | 4000 | +| 翻窗速度 | 635 | 1,524 | 1,058 | 1270 | +| 翻箱速度 | 1000 | 1000 | 1000 | 1000 | #### 运动员 - 主动技能 @@ -419,7 +460,7 @@ public: - 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 - 实际上唤醒或勉励不同的人是有效的 -### 破译与逃脱 +### 破译与毕业 - 隐藏校门与校门对于人有碰撞体积 - 一个校门同时最多可以由一人开启 @@ -467,7 +508,7 @@ public: | J | (Tri)攻击,方向向上 | | 鼠标双击某点 | (Tri)攻击,方向与从Tricker指向该点的向量相同 | | K | (Stu)开始学习 | -| R | (Stu)开始营救(陷入沉迷状态的同伴) | +| R | (Stu)开始唤醒(陷入沉迷状态的同伴) | | T | (Stu)开始勉励(学习毅力下降的同伴) | | G | (Stu)发出毕业请求 | | H | (Stu)申请毕业(或称为开校门) | diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index a4fcbd4..5c6e5d8 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -30,9 +30,9 @@ namespace Gaming } if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) { - if (characterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) - player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenCharge)); - characterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge); + if (characterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostStunnedWhenCharge)) + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostStunnedWhenCharge)); + characterManager.BeStunned(player, GameData.TimeOfStudentStunnedWhenCharge); } } public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index 0626679..66df131 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -152,7 +152,7 @@ namespace Gaming { if (!noise && XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment)) newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position)); - if (newPlayer.CharacterType != CharacterType.Teacher && XY.Distance(newPlayer.Position, person.Position) <= newPlayer.ViewRange) + if (newPlayer.CharacterType != CharacterType.Teacher && XY.Distance(newPlayer.Position, person.Position) <= GameData.PinningDownRange) { TimePinningDown += GameData.checkInterval; newPlayer.AddScore(GameData.StudentScorePinDown(TimePinningDown) - ScoreAdded); diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs index 457ed44..ae97ce7 100644 --- a/logic/Gaming/PropManager.cs +++ b/logic/Gaming/PropManager.cs @@ -48,7 +48,7 @@ namespace Gaming if (!player.IsGhost()) if (player.HP < player.MaxHp) { - player.HP += GameData.basicTreatmentDegree; + player.HP += GameData.basicTreatmentDegree / 2; player.AddScore(GameData.ScorePropAddHp); } else player.AddAp(GameData.PropDuration); diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 2d02ea9..c045a26 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -32,7 +32,6 @@ namespace Gaming { if ((!player.Commandable())) return false; IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime); - characterManager.SetPlayerState(player, PlayerStateType.UsingSkill); return ActiveSkillEffect(skill, player, () => { @@ -41,7 +40,7 @@ namespace Gaming () => { new FrameRateTaskExecutor( - loopCondition: () => player.PlayerState == PlayerStateType.UsingSkill && gameMap.Timer.IsGaming, + loopCondition: () => player.Commandable() && gameMap.Timer.IsGaming, loopToDo: () => { gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); @@ -69,8 +68,6 @@ namespace Gaming }, () => { - if (player.PlayerState == PlayerStateType.UsingSkill) - player.SetPlayerStateNaturally(); } ); } @@ -167,8 +164,8 @@ namespace Gaming { if (!character.IsGhost() && XY.Distance(character.Position, player.Position) <= player.ViewRange) { - if (characterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl)) - player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStudentFaintingWhenHowl)); + if (characterManager.BeStunned(character, GameData.TimeOfStudentStunnedWhenHowl)) + player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStudentStunnedWhenHowl)); break; } } @@ -199,8 +196,8 @@ namespace Gaming || character.PlayerState == PlayerStateType.UsingSkill) && gameMap.CanSee(player, character)) { - if (characterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish)) - player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish)); + if (characterManager.BeStunned(character, GameData.TimeOfGhostStunnedWhenPunish)) + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostStunnedWhenPunish)); break; } } diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index c99608d..50a6082 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -33,8 +33,8 @@ namespace Preparation.Interface public class BecomeInvisible : IActiveSkill { - public int SkillCD => GameData.commonSkillCD * 2; - public int DurationTime => GameData.commonSkillTime * 6 / 10; + public int SkillCD => GameData.commonSkillCD * 4 / 3; + public int DurationTime => GameData.commonSkillTime; private readonly object commonSkillLock = new object(); public object ActiveSkillLock => commonSkillLock; diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index ecec57d..e860440 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -118,6 +118,8 @@ namespace Preparation.Utility public const int basicGhostAlertnessRadius = 17 * numOfPosGridPerCell; public const int basicStudentViewRange = 10 * numOfPosGridPerCell; public const int basicGhostViewRange = 15 * numOfPosGridPerCell; + public const int PinningDownRange = 5 * numOfPosGridPerCell; + public const int maxNumOfPropInPropInventory = 3; public static XY PosWhoDie = new XY(1, 1); @@ -140,47 +142,47 @@ namespace Preparation.Utility return damage * 100 / basicApOfGhost; } public const int TrickerScoreStudentBeAddicted = 50; - public const int TrickerScoreDestroyRobot = 20; + public const int TrickerScoreDestroyRobot = 30; public const int TrickerScoreStudentDie = 1000; public static int TrickerScoreStudentBeStunned(int time) { - return time; + return time * 20 / 1000; } public static int TrickerScoreDamageGenerator(int degree) { - return degree * 200 / degreeOfFixedGenerator; + return degree * 100 / degreeOfFixedGenerator; } public static int StudentScoreFix(int degreeOfFix) { return degreeOfFix * 200 / degreeOfFixedGenerator; } - public const int StudentScoreFixed = 25; + //public const int StudentScoreFixed = 25; public static int StudentScorePinDown(int timeOfPinningDown) { - return 0; + return (int)(timeOfPinningDown * 0.00369); } public static int StudentScoreTrickerBeStunned(int time) { - return time; + return time * 20 / 1000; } public const int StudentScoreRescue = 100; public static int StudentScoreTreat(int degree) { - return degree; + return degree * 50 / basicTreatmentDegree; } 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 ScorePropRemainHp = 100; + public const int ScorePropUseShield = 50; + public const int ScorePropUseSpear = 50; + public const int ScorePropAddAp = 0; public const int ScorePropAddSpeed = 10; public const int ScorePropClairaudience = 10; - public const int ScorePropAddHp = 20; - public const int ScorePropRecoverFromDizziness = 20; + public const int ScorePropAddHp = 10; + public const int ScorePropRecoverFromDizziness = 30; - public const int ScoreBecomeInvisible = 10; + public const int ScoreBecomeInvisible = 15; public const int ScoreInspire = ScorePropAddSpeed; #endregion #region 攻击与子弹相关 @@ -208,13 +210,13 @@ namespace Preparation.Utility public const int commonSkillCD = 30000; // 普通技能标准冷却时间 public const int commonSkillTime = 10000; // 普通技能标准持续时间 - public const int TimeOfGhostFaintingWhenCharge = 7220; - public const int TimeOfStudentFaintingWhenCharge = 2090; + public const int TimeOfGhostStunnedWhenCharge = 7220; + public const int TimeOfStudentStunnedWhenCharge = 2090; - public const int TimeOfGhostFaintingWhenPunish = 3070; + public const int TimeOfGhostStunnedWhenPunish = 3070; - public const int TimeOfGhostSwingingAfterHowl = 3070; - public const int TimeOfStudentFaintingWhenHowl = 6110; + public const int TimeOfGhostSwingingAfterHowl = 800; + public const int TimeOfStudentStunnedWhenHowl = 5500; public const int TimeOfStunnedWhenJumpyDumpty = 3070; From 267e0f87b2d0b7c7174ca8f814d53a3c6c610b50 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 10:25:40 +0800 Subject: [PATCH 21/37] build: :construction: help CAPI --- CAPI/cpp/API/include/constants.h | 179 +++++++++++++++---------------- logic/Client/MainWindow.xaml.cs | 8 +- logic/GameRules_cpp.md | 60 ++++++----- 3 files changed, 122 insertions(+), 125 deletions(-) diff --git a/CAPI/cpp/API/include/constants.h b/CAPI/cpp/API/include/constants.h index b663460..3ac4e1f 100644 --- a/CAPI/cpp/API/include/constants.h +++ b/CAPI/cpp/API/include/constants.h @@ -34,16 +34,12 @@ namespace Constants SCCI int basicHp = 3000000; SCCI int basicMaxGamingAddiction = 60000; - SCCI int BeginGamingAddiction = 20900; - SCCI int MidGamingAddiction = 40300; SCCI int basicTreatmentDegree = 1500000; SCCI int basicTimeOfRescue = 1000; SCCI int basicStudentSpeed = 1270; SCCI int basicTrickerSpeed = 1504; - SCCI int maxSpeed = 12000; - SCCI double basicConcealment = 1.0; SCCI int basicStudentAlertnessRadius = 15 * numOfGridPerCell; SCCI int basicTrickerAlertnessRadius = 17 * numOfGridPerCell; @@ -51,7 +47,7 @@ namespace Constants SCCI int basicTrickerViewRange = 15 * numOfGridPerCell; SCCI int PinningDownRange = 5 * numOfGridPerCell; - SCCI int maxNumOfProp = 3; + SCCI int maxNumOfProp = 3; // 人物道具栏容量 // 攻击相关 @@ -71,145 +67,140 @@ namespace Constants SCCI int apPropAdd = basicApOfTricker * 12 / 10; SCCI int apSpearAdd = basicApOfTricker * 6 / 10; - SCCI int remainHpWhenAddLife = 100; // 职业相关 struct Assassin { - SCCI double moveSpeed = 1.1; - SCCI double maxHp = 1.0; + SCCI double moveSpeed = basicTrickerSpeed * 1.1; SCCI double concealment = 1.5; - SCCI double alertnessRadius = 1.3; - SCCI double viewRange = 1.2; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 1.0; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicTrickerAlertnessRadius * 1.3; + SCCI double viewRange = basicTrickerViewRange * 1.2; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.0; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct Klee { - SCCI double moveSpeed = 1.0; - SCCI double maxHp = 1.0; + SCCI double moveSpeed = basicTrickerSpeed * 1.0; SCCI double concealment = 1.0; - SCCI double alertnessRadius = 1.0; - SCCI double viewRange = 1.0; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 1.0; - SCCI double speedOfOpenChest = 1.1; + SCCI double alertnessRadius = basicTrickerAlertnessRadius * 1.0; + SCCI double viewRange = basicTrickerViewRange * 1.0; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.0; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.1; }; struct ANoisyPerson { - SCCI double moveSpeed = 1.07; - SCCI double maxHp = 1.2; + SCCI double moveSpeed = basicTrickerSpeed * 1.07; SCCI double concealment = 0.8; - SCCI double alertnessRadius = 0.9; - SCCI double viewRange = 1.0; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 1.1; - SCCI double speedOfOpenChest = 1.1; + SCCI double alertnessRadius = basicTrickerAlertnessRadius * 0.9; + SCCI double viewRange = basicTrickerViewRange * 1.0; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.1; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.1; }; struct Idol { - SCCI double moveSpeed = 1.0; - SCCI double maxHp = 1.0; + SCCI double moveSpeed = basicTrickerSpeed * 1.0; SCCI double concealment = 0.75; - SCCI double alertnessRadius = 1.0; - SCCI double viewRange = 1.1; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 1.0; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicTrickerAlertnessRadius * 1.0; + SCCI double viewRange = basicTrickerViewRange * 1.1; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.0; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct Athlete { - SCCI double moveSpeed = 1.1; - SCCI double maxHp = 1.0; - SCCI double maxAddiction = 0.9; - SCCI double fixSpeed = 0.6; - SCCI double treatSpeed = 0.8; + SCCI double moveSpeed = basicStudentSpeed * 1.1; + SCCI double maxHp = basicHp * 1.0; + SCCI double maxAddiction = basicMaxGamingAddiction * 0.9; + SCCI double fixSpeed = basicFixSpeed * 0.6; + SCCI double treatSpeed = basicTreatSpeed * 0.8; SCCI double concealment = 0.9; - SCCI double alertnessRadius = 1.0; - SCCI double viewRange = 1.1; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 1.2; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicStudentAlertnessRadius * 1.0; + SCCI double viewRange = basicStudentViewRange * 1.1; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 1.2; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct Teacher { - SCCI double moveSpeed = 0.75; - SCCI double maxHp = 10.0; - SCCI double maxAddiction = 10.0; - SCCI double fixSpeed = 0.0; - SCCI double treatSpeed = 0.7; + SCCI double moveSpeed = basicStudentSpeed * 0.75; + SCCI double maxHp = basicHp * 10.0; + SCCI double maxAddiction = basicMaxGamingAddiction * 10.0; + SCCI double fixSpeed = basicFixSpeed * 0.0; + SCCI double treatSpeed = basicTreatSpeed * 0.7; SCCI double concealment = 0.5; - SCCI double alertnessRadius = 0.5; - SCCI double viewRange = 0.9; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 0.5; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicStudentAlertnessRadius * 0.5; + SCCI double viewRange = basicStudentViewRange * 0.9; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.5; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct StraightAStudent { - SCCI double moveSpeed = 0.8; - SCCI double maxHp = 1.1; - SCCI double maxAddiction = 1.3; - SCCI double fixSpeed = 1.1; - SCCI double treatSpeed = 0.8; + SCCI double moveSpeed = basicStudentSpeed * 0.8; + SCCI double maxHp = basicHp * 1.1; + SCCI double maxAddiction = basicMaxGamingAddiction * 1.3; + SCCI double fixSpeed = basicFixSpeed * 1.1; + SCCI double treatSpeed = basicTreatSpeed * 0.8; SCCI double concealment = 0.9; - SCCI double alertnessRadius = 0.9; - SCCI double viewRange = 0.9; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 0.83333; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicStudentAlertnessRadius * 0.9; + SCCI double viewRange = basicStudentViewRange * 0.9; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.83333; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct Robot { - SCCI double moveSpeed = 1.0; - SCCI double maxHp = 0.4; - SCCI double maxAddiction = 0.0; - SCCI double fixSpeed = 1.0; - SCCI double treatSpeed = 0.8; + SCCI double moveSpeed = basicStudentSpeed * 1.0; + SCCI double maxHp = basicHp * 0.4; + SCCI double maxAddiction = basicMaxGamingAddiction * 0.0; + SCCI double fixSpeed = basicFixSpeed * 1.0; + SCCI double treatSpeed = basicTreatSpeed * 0.8; SCCI double concealment = 1.0; - SCCI double alertnessRadius = 1.0; - SCCI double viewRange = 1.0; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 0.0016; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicStudentAlertnessRadius * 1; + SCCI double viewRange = basicStudentViewRange * 1.0; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.0016; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct TechOtaku { - SCCI double moveSpeed = 0.75; - SCCI double maxHp = 0.9; - SCCI double maxAddiction = 1.1; - SCCI double fixSpeed = 1.1; - SCCI double treatSpeed = 0.9; + SCCI double moveSpeed = basicStudentSpeed * 0.75; + SCCI double maxHp = basicHp * 0.9; + SCCI double maxAddiction = basicMaxGamingAddiction * 1.1; + SCCI double fixSpeed = basicFixSpeed * 1.1; + SCCI double treatSpeed = basicTreatSpeed * 0.9; SCCI double concealment = 1.0; - SCCI double alertnessRadius = 1.0; - SCCI double viewRange = 0.9; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 0.75; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicStudentAlertnessRadius; + SCCI double viewRange = basicStudentViewRange * 0.9; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.75; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; struct Sunshine { - SCCI double moveSpeed = 1.0; - SCCI double maxHp = 1.0667; - SCCI double maxAddiction = 1.1; - SCCI double fixSpeed = 1.0; - SCCI double treatSpeed = 2.0; + SCCI double moveSpeed = basicStudentSpeed * 1.0; + SCCI double maxHp = basicHp * 1.0667; + SCCI double maxAddiction = basicMaxGamingAddiction * 1.1; + SCCI double fixSpeed = basicFixSpeed * 1.0; + SCCI double treatSpeed = basicTreatSpeed * 2.0; SCCI double concealment = 1.0; - SCCI double alertnessRadius = 1.0; - SCCI double viewRange = 1.0; - SCCI double speedOfOpeningOrLocking = 1.0; - SCCI double speedOfClimbingThroughWindows = 1.0; - SCCI double speedOfOpenChest = 1.0; + SCCI double alertnessRadius = basicStudentAlertnessRadius * 1.0; + SCCI double viewRange = basicStudentViewRange * 1.0; + SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; + SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 1.0; + SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; }; // 技能相关 diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 3760689..8fac56f 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -807,11 +807,11 @@ namespace Client { Ellipse icon = new() { - Width = 2*bulletRadiusTimes*unitWidth, - Height = 2*bulletRadiusTimes*unitHeight, + Width = 2 * bulletRadiusTimes * unitWidth, + Height = 2 * bulletRadiusTimes * unitHeight, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, - Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth*bulletRadiusTimes, data.X * unitHeight / 1000.0 - unitHeight *bulletRadiusTimes, 0, 0), + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bulletRadiusTimes, data.X * unitHeight / 1000.0 - unitHeight * bulletRadiusTimes, 0, 0), Fill = Brushes.Red, }; switch (data.Type) @@ -1429,7 +1429,7 @@ namespace Client bool isEmergencyDrawed = false; bool isDataFixed = false; const double radiusTimes = 1.0 * Preparation.Utility.GameData.characterRadius / Preparation.Utility.GameData.numOfPosGridPerCell; - const double bulletRadiusTimes =1.0* GameData.bulletRadius/ Preparation.Utility.GameData.numOfPosGridPerCell; + const double bulletRadiusTimes = 1.0 * GameData.bulletRadius / Preparation.Utility.GameData.numOfPosGridPerCell; private int[] totalLife = new int[4] { 100, 100, 100, 100 }, totalDeath = new int[4] { 100, 100, 100, 100 }; private int[,] coolTime = new int[3, 5] { { 100, 100, 100, 100, 100 }, { 100, 100, 100, 100, 100 }, { 100, 100, 100, 100, 100 } }; } diff --git a/logic/GameRules_cpp.md b/logic/GameRules_cpp.md index ec8c967..83a3965 100644 --- a/logic/GameRules_cpp.md +++ b/logic/GameRules_cpp.md @@ -1,4 +1,5 @@ # 规则(C++) +V2.01 - [规则(C++)](#规则c) - [接口与规则](#接口与规则) - [地图](#地图) @@ -8,7 +9,7 @@ - [攻击](#攻击) - [交互](#交互) - [破译与毕业](#破译与毕业) - - [勉励(Treat)](#勉励treat) + - [勉励](#勉励) - [沉迷与唤醒](#沉迷与唤醒) - [门](#门) - [窗](#窗) @@ -107,24 +108,24 @@ | 最大子弹容量 | 1 | 1 | 1 | - | ### 交互 -- 除了翻窗,交互目标与交互者在一个九宫格方可交互 +- 除了翻窗,交互目标与交互者在一个**九宫格**方可交互 - 交互进度每毫秒增加对应交互速度的值 - 作业,门,箱子完成/开启进度达到10000000为完成 #### 破译与毕业 - 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。 -- `std::future StartLearning()`:在教室(旁)做作业 +- `std::future StartLearning()`:在教室里开始做作业 - `std::future StartOpenGate()`:开启校门,所需时间为18秒,开启的进度不清空 - 当**3间**教室的作业完成时,隐藏校门在3-5个刷新点之一随机显现;当只剩1名学生时,隐藏校门自动打开。 - `std::future Graduate()`:从开启的校门或隐藏校门毕业。 -#### 勉励(Treat) -- `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。 +#### 勉励 +- `std::future StartEncourageMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。 - 勉励中断时,被勉励程度保留;遭到攻击时被勉励程度清空 #### 沉迷与唤醒 - 当学生学习毅力归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 -- `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。 +- `std::future StartRouseMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。 - 进入沉迷状态时,如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; - 当学生沉迷程度达到其最大沉迷程度时,从游戏中出局 @@ -155,25 +156,30 @@ - `bool Wait()`:阻塞当前线程,直到下一次消息更新时继续运行。 ### 信息获取 -`std::vector> GetStudents() const` :返回所有可视学生的信息。 -`std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 -`std::vector> GetProps() const` :返回所有可视道具的信息。 -`std::vector> GetFullMap() const`:返回整张地图的地形信息。 - -- 下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 - -`THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 -`bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 -`int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 -`int32_t GetGateProgress(int32_t cellX, int32_t cellY) const`:查询特定位置校门开启进度 -`int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 -`THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 -`int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 - -`std::shared_ptr GetGameInfo() const`:查询当前游戏状态 -`std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID -`int GetFrameCount() const`:获取目前所进行的帧数 -`std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 +- 可视范围 + - 小于视野半径,且受限于墙和草地 + - 对于在从草地中的物体,物体与玩家连线上均为草地方可见 +- 查询可视范围内的信息 + - `std::vector> GetStudents() const` :返回所有可视学生的信息。 + - `std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 + - `std::vector> GetProps() const` :返回所有可视道具的信息。 + - `std::vector> GetBullets() const` :返回所有可视子弹(攻击)的信息。 + +- 查询特定位置物体的信息,下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 + - `THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 + - `bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 + - `int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 + - `int32_t GetGateProgress(int32_t cellX, int32_t cellY) const`:查询特定位置校门开启进度 + - `int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 + - `THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 + - `int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 +- 其他 + - `std::shared_ptr GetGameInfo() const`:查询当前游戏状态\ + - `std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID\ + - `int GetFrameCount() const`:获取目前所进行的帧数\ + - `std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 + - `std::vector> GetFullMap() const`:返回整张地图的地形信息。 + ### 道具 - 玩家最多同时拥有三个道具 @@ -422,8 +428,8 @@ public: /*****学生阵营的特定函数*****/ virtual std::future StartLearning() = 0; - virtual std::future StartTreatMate(int64_t mateID) = 0; - virtual std::future StartRescueMate(int64_t mateID) = 0; + virtual std::future StartEncourageMate(int64_t mateID) = 0; + virtual std::future StartRouseMate(int64_t mateID) = 0; virtual std::future Graduate() = 0; [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; }; From 2d18b381beb6d2c9747055fbefc75ff36af364eb Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 10:58:04 +0800 Subject: [PATCH 22/37] refactor: :bug: change the double of constants into int --- CAPI/cpp/API/include/constants.h | 230 +++++++++++++------------- CAPI/python/PyAPI/constants.py | 7 +- logic/Gaming/ActionManager.cs | 1 - logic/Preparation/Interface/ISkill.cs | 2 +- 4 files changed, 117 insertions(+), 123 deletions(-) diff --git a/CAPI/cpp/API/include/constants.h b/CAPI/cpp/API/include/constants.h index 3ac4e1f..bafde1c 100644 --- a/CAPI/cpp/API/include/constants.h +++ b/CAPI/cpp/API/include/constants.h @@ -40,7 +40,7 @@ namespace Constants SCCI int basicStudentSpeed = 1270; SCCI int basicTrickerSpeed = 1504; - SCCI double basicConcealment = 1.0; + SCCI double basicConcealment = 1; SCCI int basicStudentAlertnessRadius = 15 * numOfGridPerCell; SCCI int basicTrickerAlertnessRadius = 17 * numOfGridPerCell; SCCI int basicStudentViewRange = 10 * numOfGridPerCell; @@ -71,136 +71,136 @@ namespace Constants // 职业相关 struct Assassin { - SCCI double moveSpeed = basicTrickerSpeed * 1.1; + SCCI int moveSpeed = basicTrickerSpeed * 11 / 10; SCCI double concealment = 1.5; - SCCI double alertnessRadius = basicTrickerAlertnessRadius * 1.3; - SCCI double viewRange = basicTrickerViewRange * 1.2; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.0; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int alertnessRadius = basicTrickerAlertnessRadius * 13 / 10; + SCCI int viewRange = basicTrickerViewRange * 12 / 10; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct Klee { - SCCI double moveSpeed = basicTrickerSpeed * 1.0; - SCCI double concealment = 1.0; - SCCI double alertnessRadius = basicTrickerAlertnessRadius * 1.0; - SCCI double viewRange = basicTrickerViewRange * 1.0; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.0; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.1; + SCCI int moveSpeed = basicTrickerSpeed; + SCCI double concealment = 1; + SCCI int alertnessRadius = basicTrickerAlertnessRadius; + SCCI int viewRange = basicTrickerViewRange; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest * 11 / 10; }; struct ANoisyPerson { - SCCI double moveSpeed = basicTrickerSpeed * 1.07; + SCCI int moveSpeed = (int)(basicTrickerSpeed * 1.07); SCCI double concealment = 0.8; - SCCI double alertnessRadius = basicTrickerAlertnessRadius * 0.9; - SCCI double viewRange = basicTrickerViewRange * 1.0; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.1; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.1; + SCCI int alertnessRadius = basicTrickerAlertnessRadius * 9 / 10; + SCCI int viewRange = basicTrickerViewRange; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 11 / 10; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest * 11 / 10; }; struct Idol { - SCCI double moveSpeed = basicTrickerSpeed * 1.0; + SCCI int moveSpeed = basicTrickerSpeed; SCCI double concealment = 0.75; - SCCI double alertnessRadius = basicTrickerAlertnessRadius * 1.0; - SCCI double viewRange = basicTrickerViewRange * 1.1; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows * 1.0; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int alertnessRadius = basicTrickerAlertnessRadius; + SCCI int viewRange = basicTrickerViewRange * 11 / 10; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicTrickerSpeedOfClimbingThroughWindows; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct Athlete { - SCCI double moveSpeed = basicStudentSpeed * 1.1; - SCCI double maxHp = basicHp * 1.0; - SCCI double maxAddiction = basicMaxGamingAddiction * 0.9; - SCCI double fixSpeed = basicFixSpeed * 0.6; - SCCI double treatSpeed = basicTreatSpeed * 0.8; + SCCI int moveSpeed = basicStudentSpeed * 11 / 10; + SCCI int maxHp = basicHp; + SCCI int maxAddiction = basicMaxGamingAddiction * 9 / 10; + SCCI int fixSpeed = basicFixSpeed * 6 / 10; + SCCI int treatSpeed = basicTreatSpeed * 8 / 10; SCCI double concealment = 0.9; - SCCI double alertnessRadius = basicStudentAlertnessRadius * 1.0; - SCCI double viewRange = basicStudentViewRange * 1.1; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 1.2; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int alertnessRadius = basicStudentAlertnessRadius; + SCCI int viewRange = basicStudentViewRange * 11 / 10; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 12 / 10; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct Teacher { - SCCI double moveSpeed = basicStudentSpeed * 0.75; - SCCI double maxHp = basicHp * 10.0; - SCCI double maxAddiction = basicMaxGamingAddiction * 10.0; - SCCI double fixSpeed = basicFixSpeed * 0.0; - SCCI double treatSpeed = basicTreatSpeed * 0.7; + SCCI int moveSpeed = basicStudentSpeed * 3 / 4; + SCCI int maxHp = basicHp * 10; + SCCI int maxAddiction = basicMaxGamingAddiction * 10; + SCCI int fixSpeed = basicFixSpeed * 0; + SCCI int treatSpeed = basicTreatSpeed * 7 / 10; SCCI double concealment = 0.5; - SCCI double alertnessRadius = basicStudentAlertnessRadius * 0.5; - SCCI double viewRange = basicStudentViewRange * 0.9; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.5; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int alertnessRadius = basicStudentAlertnessRadius / 2; + SCCI int viewRange = basicStudentViewRange * 9 / 10; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows / 2; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct StraightAStudent { - SCCI double moveSpeed = basicStudentSpeed * 0.8; - SCCI double maxHp = basicHp * 1.1; - SCCI double maxAddiction = basicMaxGamingAddiction * 1.3; - SCCI double fixSpeed = basicFixSpeed * 1.1; - SCCI double treatSpeed = basicTreatSpeed * 0.8; + SCCI int moveSpeed = basicStudentSpeed * 8 / 10; + SCCI int maxHp = basicHp * 11 / 10; + SCCI int maxAddiction = basicMaxGamingAddiction * 13 / 10; + SCCI int fixSpeed = basicFixSpeed * 11 / 10; + SCCI int treatSpeed = basicTreatSpeed * 8 / 10; SCCI double concealment = 0.9; - SCCI double alertnessRadius = basicStudentAlertnessRadius * 0.9; - SCCI double viewRange = basicStudentViewRange * 0.9; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.83333; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int alertnessRadius = basicStudentAlertnessRadius * 9 / 10; + SCCI int viewRange = basicStudentViewRange * 9 / 10; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 10 / 12; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct Robot { - SCCI double moveSpeed = basicStudentSpeed * 1.0; - SCCI double maxHp = basicHp * 0.4; - SCCI double maxAddiction = basicMaxGamingAddiction * 0.0; - SCCI double fixSpeed = basicFixSpeed * 1.0; - SCCI double treatSpeed = basicTreatSpeed * 0.8; - SCCI double concealment = 1.0; - SCCI double alertnessRadius = basicStudentAlertnessRadius * 1; - SCCI double viewRange = basicStudentViewRange * 1.0; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.0016; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int moveSpeed = basicStudentSpeed; + SCCI int maxHp = basicHp * 0.4; + SCCI int maxAddiction = basicMaxGamingAddiction * 0; + SCCI int fixSpeed = basicFixSpeed; + SCCI int treatSpeed = basicTreatSpeed * 8 / 10; + SCCI double concealment = 1; + SCCI int alertnessRadius = basicStudentAlertnessRadius * 1; + SCCI int viewRange = basicStudentViewRange; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = 1; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct TechOtaku { - SCCI double moveSpeed = basicStudentSpeed * 0.75; - SCCI double maxHp = basicHp * 0.9; - SCCI double maxAddiction = basicMaxGamingAddiction * 1.1; - SCCI double fixSpeed = basicFixSpeed * 1.1; - SCCI double treatSpeed = basicTreatSpeed * 0.9; - SCCI double concealment = 1.0; - SCCI double alertnessRadius = basicStudentAlertnessRadius; - SCCI double viewRange = basicStudentViewRange * 0.9; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 0.75; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int moveSpeed = basicStudentSpeed * 3 / 4; + SCCI int maxHp = basicHp * 9 / 10; + SCCI int maxAddiction = basicMaxGamingAddiction * 11 / 10; + SCCI int fixSpeed = basicFixSpeed * 11 / 10; + SCCI int treatSpeed = basicTreatSpeed * 9 / 10; + SCCI double concealment = 1; + SCCI int alertnessRadius = basicStudentAlertnessRadius; + SCCI int viewRange = basicStudentViewRange * 9 / 10; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 3 / 4; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; struct Sunshine { - SCCI double moveSpeed = basicStudentSpeed * 1.0; - SCCI double maxHp = basicHp * 1.0667; - SCCI double maxAddiction = basicMaxGamingAddiction * 1.1; - SCCI double fixSpeed = basicFixSpeed * 1.0; - SCCI double treatSpeed = basicTreatSpeed * 2.0; - SCCI double concealment = 1.0; - SCCI double alertnessRadius = basicStudentAlertnessRadius * 1.0; - SCCI double viewRange = basicStudentViewRange * 1.0; - SCCI double speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 1.0; - SCCI double speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows * 1.0; - SCCI double speedOfOpenChest = basicSpeedOfOpenChest * 1.0; + SCCI int moveSpeed = basicStudentSpeed; + SCCI int maxHp = basicHp * 32 / 30; + SCCI int maxAddiction = basicMaxGamingAddiction * 11 / 10; + SCCI int fixSpeed = basicFixSpeed; + SCCI int treatSpeed = basicTreatSpeed * 2; + SCCI double concealment = 1; + SCCI int alertnessRadius = basicStudentAlertnessRadius; + SCCI int viewRange = basicStudentViewRange; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest; }; // 技能相关 @@ -222,80 +222,80 @@ namespace Constants SCCI int timeOfAddingSpeedWhenInspire = 6000; struct CanBeginToCharge { - SCCI double skillCD = 4 / 3; - SCCI double durationTime = 1; + SCCI int skillCD = commonSkillCD * 4 / 3; + SCCI int durationTime = commonSkillTime * 1; }; struct BecomeInvisible { - SCCI double skillCD = 2.0; - SCCI double durationTime = 0.6; + SCCI int skillCD = commonSkillCD * 2; + SCCI int durationTime = commonSkillTime * 6 / 10; }; struct Punish { - SCCI double skillCD = 1.0; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 1; + SCCI int durationTime = commonSkillTime * 0; }; struct Rouse { - SCCI double skillCD = 2.0; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 2; + SCCI int durationTime = commonSkillTime * 0; }; struct Encourage { - SCCI double skillCD = 2.0; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 2; + SCCI int durationTime = commonSkillTime * 0; }; struct Inspire { - SCCI double skillCD = 2.0; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 2; + SCCI int durationTime = commonSkillTime * 0; }; struct Howl { - SCCI double skillCD = 0.8333; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 25 / 30; + SCCI int durationTime = commonSkillTime * 0; }; struct ShowTime { - SCCI double skillCD = 3.0; - SCCI double durationTime = 1.0; + SCCI int skillCD = commonSkillCD * 3; + SCCI int durationTime = commonSkillTime * 1; }; struct JumpyBomb { - SCCI double skillCD = 0.5; - SCCI double durationTime = 0.3; + SCCI int skillCD = commonSkillCD / 2; + SCCI int durationTime = commonSkillTime * 3 / 10; }; struct UseKnife { - SCCI double skillCD = 1.0; - SCCI double durationTime = 0.1; + SCCI int skillCD = commonSkillCD * 1; + SCCI int durationTime = commonSkillTime / 10; }; struct UseRobot { - SCCI double skillCD = 0.0017; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD / 300; + SCCI int durationTime = commonSkillTime * 0; }; struct WriteAnswers { - SCCI double skillCD = 1.0; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 1; + SCCI int durationTime = commonSkillTime * 0; }; struct SummonGolem { - SCCI double skillCD = 1.0; - SCCI double durationTime = 0.0; + SCCI int skillCD = commonSkillCD * 1; + SCCI int durationTime = commonSkillTime * 0; }; } // namespace Constants #endif diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index ded61af..ec0c9ac 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -29,16 +29,12 @@ class Constants(NoInstance): basicHp = 3000000 basicMaxGamingAddiction = 60000 - BeginGamingAddiction = 20900 - MidGamingAddiction = 40300 basicEncouragementDegree = 1500000 basicTimeOfRouse = 1000 basicStudentSpeed = 1270 basicTrickerSpeed = 1504 - maxSpeed = 12000 - basicConcealment = 1.0 basicStudentAlertnessRadius = 15 * numOfGridPerCell basicTrickerAlertnessRadius = 17 * numOfGridPerCell @@ -46,7 +42,7 @@ class Constants(NoInstance): basicTrickerViewRange = 15 * numOfGridPerCell PinningDownRange = 5 * numOfPosGridPerCell - maxNumOfProp = 3 + maxNumOfProp = 3 # 人物道具栏容量 # 攻击相关 @@ -66,7 +62,6 @@ class Constants(NoInstance): apPropAdd = basicApOfTricker * 12 / 10 apSpearAdd = basicApOfTricker * 6 / 10 - remainHpWhenAddLife = 100 class Assassin: moveSpeed = 1.1*basicTrickerSpeed diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 5c6e5d8..54b29eb 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -382,7 +382,6 @@ namespace Gaming loopToDo: () => { flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null); - Preparation.Utility.Debugger.Output(doorToLock, flag.ToString()); doorToLock.OpenOrLockDegree += GameData.frameDuration * player.SpeedOfOpeningOrLocking; }, timeInterval: GameData.frameDuration, diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index 50a6082..2491d48 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -166,7 +166,7 @@ namespace Preparation.Interface public class UseRobot : IActiveSkill { - public int SkillCD => GameData.frameDuration; + public int SkillCD => GameData.commonSkillCD / 300; public int DurationTime => 0; private readonly object commonSkillLock = new object(); public object ActiveSkillLock => commonSkillLock; From 54f07a83d6050dd85da0a1ae6131a7e966cdeb2b Mon Sep 17 00:00:00 2001 From: DragonAura Date: Wed, 12 Apr 2023 12:32:29 +0800 Subject: [PATCH 23/37] feat(CAPI): :sparkles: add clairaudience --- CAPI/cpp/API/src/logic.cpp | 8 ++++++++ CAPI/python/PyAPI/logic.py | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index 8a83e03..799b281 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -699,6 +699,14 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) case THUAI6::MessageOfObj::StudentMessage: { bool flag = false; + for (const auto& buff : bufferState->trickerSelf->buff) + if (buff == THUAI6::TrickerBuffType::Clairaudience) + { + flag = true; + bufferState->students.push_back(Proto2THUAI6::Protobuf2THUAI6Student(item.student_message())); + logger->debug("Add Student!"); + break; + } for (int i = 0; i < item.student_message().buff_size(); i++) if (Proto2THUAI6::studentBuffTypeDict[item.student_message().buff(i)] == THUAI6::StudentBuffType::Invisible) { diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index 205eb95..1db66a7 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -452,6 +452,11 @@ class Logic(ILogic): self.__logger.debug("Add Tricker!") for item in message.obj_message: if item.WhichOneof("message_of_obj") == "student_message": + if THUAI6.TrickerBuffType.Clairaudience in self.__bufferState.self.buff: + self.__bufferState.students.append( + Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)) + self.__logger.debug("Add Student!") + continue if MessageType.STUDENT_INVISIBLE in item.student_message.buff: continue if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.student_message.x, item.student_message.y, self.__bufferState.gameMap): From 8d2a27f38a9852d4f9461d79cb054b8f1c8b5020 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 12:41:23 +0800 Subject: [PATCH 24/37] =?UTF-8?q?build:=20:construction:=20issue=20CPAI?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3.md=20and=20GameRules.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAPI/CPAI接口.md | 202 +++++++++++++++++++++++ logic/{GameRules_cpp.md => GameRules.md} | 124 ++++---------- logic/Preparation/Interface/ISkill.cs | 2 +- 3 files changed, 234 insertions(+), 94 deletions(-) create mode 100644 CAPI/CPAI接口.md rename logic/{GameRules_cpp.md => GameRules.md} (80%) diff --git a/CAPI/CPAI接口.md b/CAPI/CPAI接口.md new file mode 100644 index 0000000..4b1c230 --- /dev/null +++ b/CAPI/CPAI接口.md @@ -0,0 +1,202 @@ +# CAPI接口 +- [CAPI接口](#capi接口) + - [接口解释](#接口解释) + - [移动](#移动) + - [使用技能](#使用技能) + - [人物](#人物) + - [攻击](#攻击) + - [学习与毕业](#学习与毕业) + - [勉励](#勉励) + - [沉迷与唤醒](#沉迷与唤醒) + - [门](#门) + - [窗](#窗) + - [箱子](#箱子) + - [队内信息](#队内信息) + - [信息获取](#信息获取) + - [辅助函数](#辅助函数) + - [道具](#道具) + - [接口一览](#接口一览) + +## 接口解释 + +### 移动 +- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴** +- `bool MoveRight(uint32_t timeInMilliseconds)`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理 + +### 使用技能 +- `std::future UseSkill(int32_t skillID)`:使用对应序号的主动技能 + +### 人物 +- `std::future EndAllAction()`:可以使不处在不可行动状态中的玩家终止当前行动 + +### 攻击 +- `std::future Attack(double angleInRadian)`:`angleInRadian`为攻击方向 + +#### 学习与毕业 +- `std::future StartLearning()`:在教室里开始做作业 +- `std::future StartOpenGate()`:开始开启校门 +- `std::future Graduate()`:从开启的校门或隐藏校门毕业。 + +#### 勉励 +- `std::future StartEncourageMate(int64_t mateID)`:勉励对应玩家ID的学生, + +#### 沉迷与唤醒 +- `std::future StartRouseMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生。 + +#### 门 +- `std::future OpenDoor()`:开门 +- `std::future CloseDoor()`:关门 + +#### 窗 +- `std::future SkipWindow()`:翻窗 + +#### 箱子 +- `std::future StartOpenChest()`:开箱 + +### 队内信息 +- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。第一个参数指定发送的对象,第二个参数指定发送的内容,不得超过256字节。 +- `bool HaveMessage()`:是否有队友发来的尚未接收的信息。 +- `std::pair GetMessage()`:从玩家ID为第一个参数的队友获取信息。 + +### 信息获取 +- 查询可视范围内的信息 + - `std::vector> GetStudents() const` :返回所有可视学生的信息。 + - `std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 + - `std::vector> GetProps() const` :返回所有可视道具的信息。 + - `std::vector> GetBullets() const` :返回所有可视子弹(攻击)的信息。 + +- 查询特定位置物体的信息,下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 + - `THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 + - `bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 + - `int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 + - `int32_t GetGateProgress(int32_t cellX, int32_t cellY) const`:查询特定位置校门开启进度 + - `int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 + - `THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 + - `int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 +- 其他 + - `std::shared_ptr GetGameInfo() const`:查询当前游戏状态\ + - `std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID\ + - `int GetFrameCount() const`:获取目前所进行的帧数\ + - `std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 + - `std::vector> GetFullMap() const`:返回整张地图的地形信息。 + +## 辅助函数 +`static inline int CellToGrid(int cell) noexcept`:将地图格数 cell 转换为绝对坐标grid。 + +`static inline int GridToCell(int grid) noexcept`:将绝对坐标 grid 转换为地图格数cell。 + +下面为用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 +~~~c + void Print(std::string str) const; + void PrintStudent() const; + void PrintTricker() const; + void PrintProp() const; + void PrintSelfInfo() const; +~~~ + +### 道具 +- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 +- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 +- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 + +## 接口一览 +~~~csharp + // 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 + virtual std::future Move(int64_t timeInMilliseconds, double angleInRadian) = 0; + + // 向特定方向移动 + virtual std::future MoveRight(int64_t timeInMilliseconds) = 0; + virtual std::future MoveUp(int64_t timeInMilliseconds) = 0; + virtual std::future MoveLeft(int64_t timeInMilliseconds) = 0; + virtual std::future MoveDown(int64_t timeInMilliseconds) = 0; + + // 捡道具、使用技能 + virtual std::future PickProp(THUAI6::PropType prop) = 0; + virtual std::future UseProp(THUAI6::PropType prop) = 0; + virtual std::future UseSkill(int32_t skillID) = 0; + virtual std::future Attack(double angleInRadian) = 0; + + virtual std::future OpenDoor() = 0; + virtual std::future CloseDoor() = 0; + virtual std::future SkipWindow() = 0; + virtual std::future StartOpenGate() = 0; + virtual std::future StartOpenChest() = 0; + virtual std::future EndAllAction() = 0; + + // 发送信息、接受信息,注意收消息时无消息则返回nullopt + virtual std::future SendMessage(int64_t, std::string) = 0; + [[nodiscard]] virtual bool HaveMessage() = 0; + [[nodiscard]] virtual std::pair GetMessage() = 0; + + // 等待下一帧 + virtual std::future Wait() = 0; + + // 获取视野内可见的学生/捣蛋鬼的信息 + [[nodiscard]] virtual std::vector> GetStudents() const = 0; + [[nodiscard]] virtual std::vector> GetTrickers() const = 0; + + // 获取视野内可见的道具信息 + [[nodiscard]] virtual std::vector> GetProps() const = 0; + + // 获取地图信息,视野外的地图统一为Land + [[nodiscard]] virtual std::vector> GetFullMap() const = 0; + [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; + + [[nodiscard]] virtual bool IsDoorOpen(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetChestProgress(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetGateProgress(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const = 0; + [[nodiscard]] virtual int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const = 0; + + [[nodiscard]] virtual std::shared_ptr GetGameInfo() const = 0; + + // 获取所有玩家的GUID + [[nodiscard]] virtual std::vector GetPlayerGUIDs() const = 0; + + // 获取游戏目前所进行的帧数 + [[nodiscard]] virtual int GetFrameCount() const = 0; + + /*****选手可能用的辅助函数*****/ + + // 获取指定格子中心的坐标 + [[nodiscard]] static inline int CellToGrid(int cell) noexcept + { + return cell * numOfGridPerCell + numOfGridPerCell / 2; + } + + // 获取指定坐标点所位于的格子的 X 序号 + [[nodiscard]] static inline int GridToCell(int grid) noexcept + { + return grid / numOfGridPerCell; + } + + // 用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 + + virtual void Print(std::string str) const = 0; + virtual void PrintStudent() const = 0; + virtual void PrintTricker() const = 0; + virtual void PrintProp() const = 0; + virtual void PrintSelfInfo() const = 0; +}; + +class IStudentAPI : public IAPI +{ +public: + /*****学生阵营的特定函数*****/ + + virtual std::future StartLearning() = 0; + virtual std::future StartEncourageMate(int64_t mateID) = 0; + virtual std::future StartRouseMate(int64_t mateID) = 0; + virtual std::future Graduate() = 0; + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; +}; + +class ITrickerAPI : public IAPI +{ +public: + /*****捣蛋鬼阵营的特定函数*****/ + + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; +}; +~~~ \ No newline at end of file diff --git a/logic/GameRules_cpp.md b/logic/GameRules.md similarity index 80% rename from logic/GameRules_cpp.md rename to logic/GameRules.md index 83a3965..cb06b8d 100644 --- a/logic/GameRules_cpp.md +++ b/logic/GameRules.md @@ -1,23 +1,19 @@ -# 规则(C++) -V2.01 -- [规则(C++)](#规则c) - - [接口与规则](#接口与规则) +# 规则 +V3.7 +- [规则](#规则) + - [规则](#规则-1) - [地图](#地图) - - [移动](#移动) - - [使用技能](#使用技能) - [人物](#人物) - [攻击](#攻击) - [交互](#交互) - - [破译与毕业](#破译与毕业) + - [学习与毕业](#学习与毕业) - [勉励](#勉励) - [沉迷与唤醒](#沉迷与唤醒) - [门](#门) - [窗](#窗) - [箱子](#箱子) - - [Bgm](#bgm) - - [队内信息](#队内信息) - - [线程控制](#线程控制) - - [信息获取](#信息获取) + - [信息相关](#信息相关) + - [视野](#视野) - [道具](#道具) - [得分](#得分) - [捣蛋鬼](#捣蛋鬼) @@ -33,25 +29,24 @@ V2.01 - [教师](#教师) - [学霸](#学霸) - [开心果](#开心果) - - [辅助函数](#辅助函数) - [接口一览](#接口一览) - [细则](#细则) - [特殊说明](#特殊说明) - - [移动](#移动-1) + - [移动](#移动) - [人物](#人物-1) - [初始状态](#初始状态) - [道具](#道具-1) - [交互](#交互-1) - - [破译与毕业](#破译与毕业-1) + - [学习与毕业](#学习与毕业-1) - [攻击](#攻击-1) - [沉迷与唤醒](#沉迷与唤醒-1) - [门](#门-1) - [窗](#窗-1) - [箱子](#箱子-1) - - [信息获取](#信息获取-1) + - [信息获取](#信息获取) - [键鼠控制](#键鼠控制) -## 接口与规则 +## 规则 ### 地图 - 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。 @@ -61,17 +56,10 @@ V2.01 - $$CellX=\frac{x}{1000},CellY=\frac{y}{1000}$$ - 地图上格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 -### 移动 -- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴** - -### 使用技能 -- `std::future UseSkill(int32_t skillID)`:使用对应序号的主动技能 - ### 人物 - 人物半径为800 - 人物共有17种不可叠加的状态: 1. (可)移动状态 -- `std::future EndAllAction()`:可以使处在下者八项状态中的玩家终止交互 2. 学习 3. 被勉励 4. 在勉励 @@ -81,17 +69,17 @@ V2.01 8. 开启校门 9. 唤醒他人中 - 之后八项为不可行动状态 -10. 被唤醒中 -11. 沉迷 -12. 退学 -13. 毕业 -14. 被眩晕 -15. 前摇 -16. 后摇 -17. 翻窗 +1. 被唤醒中 +2. 沉迷 +3. 退学 +4. 毕业 +5. 被眩晕 +6. 前摇 +7. 后摇 +8. 翻窗 ### 攻击 -- `std::future Attack(double angleInRadian)`:`angleInRadian`为攻击方向,无论近战远程均产生bullet表示攻击 +- 无论近战远程均产生bullet表示攻击 - 攻击类型CommonAttackOfGhost攻击未写完的作业,会造成对应攻击力的损坏 - 捣蛋鬼攻击交互状态或前后摇的学生,将使学生眩晕4.3s @@ -112,20 +100,18 @@ V2.01 - 交互进度每毫秒增加对应交互速度的值 - 作业,门,箱子完成/开启进度达到10000000为完成 -#### 破译与毕业 +#### 学习与毕业 - 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。 -- `std::future StartLearning()`:在教室里开始做作业 -- `std::future StartOpenGate()`:开启校门,所需时间为18秒,开启的进度不清空 +- 开启校门所需时间为18秒,开启的进度不清空 - 当**3间**教室的作业完成时,隐藏校门在3-5个刷新点之一随机显现;当只剩1名学生时,隐藏校门自动打开。 -- `std::future Graduate()`:从开启的校门或隐藏校门毕业。 #### 勉励 -- `std::future StartEncourageMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。 +- 当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。 - 勉励中断时,被勉励程度保留;遭到攻击时被勉励程度清空 #### 沉迷与唤醒 - 当学生学习毅力归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 -- `std::future StartRouseMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。 +- 唤醒需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。 - 进入沉迷状态时,如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; - 当学生沉迷程度达到其最大沉迷程度时,从游戏中出局 @@ -133,60 +119,27 @@ V2.01 - 门分别属于三个教学区:三教,五教,六教 - 拥有对应教学区的钥匙才能开锁对应的门 - 锁门过程中,门所在格子内有人会使锁门过程中断 -- `std::future OpenDoor()`:开门 -- `std::future CloseDoor()`:关门 #### 窗 -- `std::future SkipWindow()`:翻窗时玩家应当在窗前后左右一个格子内 +- 翻窗时玩家应当在窗前后左右一个格子内 #### 箱子 -- `std::future StartOpenChest()`:开箱后将有2个随机道具掉落在玩家位置。 +- 开箱后将有2个随机道具掉落在玩家位置。 -### Bgm +### 信息相关 1. 不详的感觉:捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) 2. 期待搞事的感觉:学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) 3. 学习的声音: 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 +4. 可以向其他每一个队友发送不超过256字节的信息 -### 队内信息 -- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。第一个参数指定发送的对象,第二个参数指定发送的内容。 -- `bool HaveMessage()`:是否有队友发来的尚未接收的信息。 -- `std::pair GetMessage()`:从玩家ID为第一个参数的队友获取信息。 - -### 线程控制 -- `bool Wait()`:阻塞当前线程,直到下一次消息更新时继续运行。 - -### 信息获取 +### 视野 - 可视范围 - 小于视野半径,且受限于墙和草地 - 对于在从草地中的物体,物体与玩家连线上均为草地方可见 -- 查询可视范围内的信息 - - `std::vector> GetStudents() const` :返回所有可视学生的信息。 - - `std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 - - `std::vector> GetProps() const` :返回所有可视道具的信息。 - - `std::vector> GetBullets() const` :返回所有可视子弹(攻击)的信息。 - -- 查询特定位置物体的信息,下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 - - `THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 - - `bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 - - `int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 - - `int32_t GetGateProgress(int32_t cellX, int32_t cellY) const`:查询特定位置校门开启进度 - - `int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 - - `THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 - - `int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 -- 其他 - - `std::shared_ptr GetGameInfo() const`:查询当前游戏状态\ - - `std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID\ - - `int GetFrameCount() const`:获取目前所进行的帧数\ - - `std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 - - `std::vector> GetFullMap() const`:返回整张地图的地形信息。 - ### 道具 - 玩家最多同时拥有三个道具 -- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 -- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 -- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 - +- 可以捡起与自己处于同一个格子(cell)的道具,或将道具扔在原地 | 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| @@ -327,20 +280,6 @@ V2.01 - 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff - 每鼓舞一个学生得分10 -## 辅助函数 -`static inline int CellToGrid(int cell) noexcept`:将地图格数 cell 转换为绝对坐标grid。 - -`static inline int GridToCell(int grid) noexcept`:将绝对坐标 grid 转换为地图格数cell。 - -下面为用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 -~~~c - void Print(std::string str) const; - void PrintStudent() const; - void PrintTricker() const; - void PrintProp() const; - void PrintSelfInfo() const; -~~~ - ## 接口一览 ~~~csharp // 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 @@ -450,7 +389,6 @@ public: ### 移动 - 不鼓励选手面向地图编程,因为移动过程中你可以受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。 -- `bool MoveRight(uint32_t timeInMilliseconds)`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理 ### 人物 - 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 @@ -466,7 +404,7 @@ public: - 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 - 实际上唤醒或勉励不同的人是有效的 -### 破译与毕业 +### 学习与毕业 - 隐藏校门与校门对于人有碰撞体积 - 一个校门同时最多可以由一人开启 diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index 2491d48..89fad41 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -168,7 +168,7 @@ namespace Preparation.Interface { public int SkillCD => GameData.commonSkillCD / 300; public int DurationTime => 0; - private readonly object commonSkillLock = new object(); + private readonly object commonSkillLock = new(); public object ActiveSkillLock => commonSkillLock; public bool isBeingUsed = false; From 581ba481a5a2a6279a3b758d2fa84f05f520c5f8 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 16:24:33 +0800 Subject: [PATCH 25/37] build: :construction: change the double into int in constants.py --- CAPI/python/PyAPI/constants.py | 360 +++++++++++++++++---------------- logic/GameRules.md | 113 +---------- 2 files changed, 187 insertions(+), 286 deletions(-) diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index ec0c9ac..86b2dc5 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -1,3 +1,7 @@ +from ast import Constant +from asyncio import constants + + class NoInstance: def __call__(self): raise TypeError("This class cannot be instantiated.") @@ -5,8 +9,8 @@ class NoInstance: class Constants(NoInstance): numOfGridPerCell = 1000 # 单位坐标数 - rows = 50 # 地图行数 - cols = 50 # 地图列数 + rows = 50 # 地图行数 + cols = 50 # 地图列数 numOfClassroom = 10 # 教室数量 numOfChest = 8 # 宝箱数量 @@ -14,9 +18,9 @@ class Constants(NoInstance): maxClassroomProgress = 10000000 # 教室最大进度 maxDoorProgress = 10000000 # 开关门最大进度 maxChestProgress = 10000000 # 宝箱最大进度 - maxGateProgress = 18000 # 大门最大进度 + maxGateProgress = 18000 # 大门最大进度 - numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量 + numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量 numOfRequiredClassroomForHiddenGate = 3 # 打开隐藏门需要完成的教室数量 # 人物属性相关 @@ -36,24 +40,24 @@ class Constants(NoInstance): basicTrickerSpeed = 1504 basicConcealment = 1.0 - basicStudentAlertnessRadius = 15 * numOfGridPerCell - basicTrickerAlertnessRadius = 17 * numOfGridPerCell - basicStudentViewRange = 10 * numOfGridPerCell - basicTrickerViewRange = 15 * numOfGridPerCell - PinningDownRange = 5 * numOfPosGridPerCell + basicStudentalertnessRadius = 15 * numOfGridPerCell + basicTrickeralertnessRadius = 17 * numOfGridPerCell + basicStudentviewRange = 10 * numOfGridPerCell + basicTrickerviewRange = 15 * numOfGridPerCell + PinningDownRange = 5 * numOfGridPerCell maxNumOfProp = 3 # 人物道具栏容量 # 攻击相关 basicApOfTricker = 1500000 - basicCD = 3000 # 初始子弹冷却 - basicCastTime = 500 # 基本前摇时间 - basicBackswing = 800 # 基本后摇时间 + basicCD = 3000 # 初始子弹冷却 + basicCastTime = 500 # 基本前摇时间 + basicBackswing = 800 # 基本后摇时间 basicRecoveryFromHit = 3700 # 基本命中攻击恢复时长 basicStunnedTimeOfStudent = 4300 - basicBulletMoveSpeed = 3700 # 基本子弹移动速度 + basicBulletmoveSpeed = 3700 # 基本子弹移动速度 basicRemoteAttackRange = 3000 # 基本远程攻击范围 basicAttackShortRange = 1100 # 基本近程攻击范围 basicBulletBombRange = 1000 # 基本子弹爆炸范围 @@ -63,120 +67,6 @@ class Constants(NoInstance): apPropAdd = basicApOfTricker * 12 / 10 apSpearAdd = basicApOfTricker * 6 / 10 - class Assassin: - moveSpeed = 1.1*basicTrickerSpeed - concealment = 1.5*basicConcealment - alertnessRadius = 1.3*basicTrickerAlertnessRadius - viewRange = 1.2*basicTrickerViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 1.0*basicTrickerSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class Klee: - moveSpeed = 1.0*basicTrickerSpeed - concealment = 1.0*basicConcealment - alertnessRadius = 1.0*basicTrickerAlertnessRadius - viewRange = 1.0*basicTrickerViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 1.0*basicTrickerSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.1*basicSpeedOfOpenChest - - class ANoisyPerson: - moveSpeed = 1.07*basicTrickerSpeed - concealment = 0.8*basicConcealment - alertnessRadius = 0.9*basicTrickerAlertnessRadius - viewRange = 1.0*basicTrickerViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 1.1*basicTrickerSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.1*basicSpeedOfOpenChest - - class Idol: - moveSpeed = 1.0*basicTrickerSpeed - concealment = 0.75*basicConcealment - alertnessRadius = 1.0*basicTrickerAlertnessRadius - viewRange = 1.1*basicTrickerViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 1.0*basicTrickerSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class Athlete: - moveSpeed = 1.1*basicStudentSpeed - maxHp = 1.0*basicHp - maxAddiction = 0.9*basicMaxGamingAddiction - LearnSpeed = 0.6*basicLearnSpeed - EncourageSpeed = 0.8*basicEncourageSpeed - concealment = 0.9*basicConcealment - alertnessRadius = 1.0*basicStudentAlertnessRadius - viewRange = 1.1*basicStudentViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 1.2*basicStudentSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class Teacher: - moveSpeed = 0.75*basicStudentSpeed - maxHp = 10.0*basicHp - maxAddiction = 10.0*basicMaxGamingAddiction - LearnSpeed = 0.0*basicLearnSpeed - EncourageSpeed = 0.7*basicEncourageSpeed - concealment = 0.5*basicConcealment - alertnessRadius = 0.5*basicStudentAlertnessRadius - viewRange = 0.9*basicStudentViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 0.5*basicStudentSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class StraightAStudent: - moveSpeed = 0.8*basicStudentSpeed - maxHp = 1.1*basicHp - maxAddiction = 1.3*basicMaxGamingAddiction - LearnSpeed = 1.1*basicLearnSpeed - EncourageSpeed = 0.8*basicEncourageSpeed - concealment = 0.9*basicConcealment - alertnessRadius = 0.9*basicStudentAlertnessRadius - viewRange = 0.9*basicStudentViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 0.83333*basicStudentSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class Robot: - moveSpeed = 1.0*basicStudentSpeed - maxHp = 0.4*basicHp - maxAddiction = 0.0*basicMaxGamingAddiction - LearnSpeed = 1.0*basicLearnSpeed - EncourageSpeed = 0.8*basicEncourageSpeed - concealment = 1.0*basicConcealment - alertnessRadius = 1.0*basicStudentAlertnessRadius - viewRange = 1.0*basicStudentViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 0.0016*basicStudentSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class TechOtaku: - moveSpeed = 0.75*basicStudentSpeed - maxHp = 0.9*basicHp - maxAddiction = 1.1*basicMaxGamingAddiction - LearnSpeed = 1.1*basicLearnSpeed - EncourageSpeed = 0.9*basicEncourageSpeed - concealment = 1.0*basicConcealment - alertnessRadius = 1.0*basicStudentAlertnessRadius - viewRange = 0.9*basicStudentViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 0.75*basicStudentSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - - class Sunshine: - moveSpeed = 1.0*basicStudentSpeed - maxHp = 1.0667*basicHp - maxAddiction = 1.1*basicMaxGamingAddiction - LearnSpeed = 1.0*basicLearnSpeed - EncourageSpeed = 2.0*basicEncourageSpeed - concealment = 1.0*basicConcealment - alertnessRadius = 1.0*basicStudentAlertnessRadius - viewRange = 1.0*basicStudentViewRange - speedOfOpeningOrLocking = 1.0*basicSpeedOfOpeningOrLocking - speedOfClimbingThroughWindows = 1.0*basicStudentSpeedOfClimbingThroughWindows - speedOfOpenChest = 1.0*basicSpeedOfOpenChest - # 技能相关 maxNumOfSkill = 3 commonSkillCD = 30000 # 普通技能标准冷却时间 @@ -195,54 +85,168 @@ class Constants(NoInstance): addedTimeOfSpeedWhenInspire = 0.6 timeOfAddingSpeedWhenInspire = 6000 - class CanBeginToCharge: - skillCD = 0.8*commonSkillCD - durationTime = 0.5*commonSkillTime - - class BecomeInvisible: - skillCD = 4*commonSkillCD/3 - durationTime = commonSkillTime - - class Punish: - skillCD = 1.0*commonSkillCD - durationTime = 0.0*commonSkillTime - - class Rouse: - skillCD = 2.0*commonSkillCD - durationTime = 0.0*commonSkillTime - - class Encourage: - skillCD = 2.0*commonSkillCD - durationTime = 0.0*commonSkillTime - - class Inspire: - skillCD = 2.0*commonSkillCD - durationTime = 0.0*commonSkillTime - - class Howl: - skillCD = 0.8333*commonSkillCD - durationTime = 0*commonSkillTime - - class ShowTime: - skillCD = 3.0*commonSkillCD - durationTime = 1.0*commonSkillTime - - class JumpyBomb: - skillCD = 0.5*commonSkillCD - durationTime = 0.3*commonSkillTime - - class UseKnife: - skillCD = 1.0*commonSkillCD - durationTime = 0.1*commonSkillTime - - class UseRobot: - skillCD = 0.0017*commonSkillCD - durationTime = 0.0*commonSkillTime - - class WriteAnswers: - skillCD = 1.0*commonSkillCD - durationTime = 0.0*commonSkillTime - - class SummonGolem: - skillCD = 1.0*commonSkillCD - durationTime = 0.0*commonSkillTime +class Assassin: + moveSpeed = (int)(1.1*Constants.basicTrickerSpeed) + concealment = 1.5*Constants.basicConcealment + alertnessRadius = (int)(1.3*Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.2*Constants.basicTrickerViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(1.0*Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class Klee: + moveSpeed = (int)(1.0*Constants.basicTrickerSpeed) + concealment = 1.0*Constants.basicConcealment + alertnessRadius = (int)(1.0*Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.0*Constants.basicTrickerViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(1.0*Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.1*Constants.basicSpeedOfOpenChest) + +class ANoisyPerson: + moveSpeed = (int)(1.07*Constants.basicTrickerSpeed) + concealment = 0.8*Constants.basicConcealment + alertnessRadius = (int)(0.9*Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.0*Constants.basicTrickerViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(1.1*Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.1*Constants.basicSpeedOfOpenChest) + +class Idol: + moveSpeed = (int)(1.0*Constants.basicTrickerSpeed) + concealment = 0.75*Constants.basicConcealment + alertnessRadius = (int)(1.0*Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.1*Constants.basicTrickerViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(1.0*Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class Athlete: + moveSpeed = (int)(1.1*Constants.basicStudentSpeed) + maxHp = (int)(1.0*Constants.basicHp) + maxAddiction = (int)(0.9*Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(0.6*Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8*Constants.basicLearnSpeed) + concealment = 0.9*Constants.basicConcealment + alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) + viewRange = (int)(1.1*Constants.basicStudentViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(1.2*Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class Teacher: + moveSpeed = (int)(0.75*Constants.basicStudentSpeed) + maxHp = (int)(10.0*Constants.basicHp) + maxAddiction = (int)(10.0*Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(0.0*Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.7*Constants.basicLearnSpeed) + concealment = 0.5*Constants.basicConcealment + alertnessRadius = (int)(0.5*Constants.basicStudentAlertnessRadius) + viewRange = (int)(0.9*Constants.basicStudentViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(0.5*Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class StraightAStudent: + moveSpeed = (int)(0.8*Constants.basicStudentSpeed) + maxHp = (int)(1.1*Constants.basicHp) + maxAddiction = (int)(1.3*Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.1*Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8*Constants.basicLearnSpeed) + concealment = 0.9*Constants.basicConcealment + alertnessRadius = (int)(0.9*Constants.basicStudentAlertnessRadius) + viewRange = (int)(0.9*Constants.basicStudentViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(0.83333*Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class Robot: + moveSpeed = (int)(1.0*Constants.basicStudentSpeed) + maxHp = (int)(0.4*Constants.basicHp) + maxAddiction = (int)(0.0*Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.0*Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8*Constants.basicLearnSpeed) + concealment = 1.0*Constants.basicConcealment + alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) + viewRange = (int)(1.0*Constants.basicStudentViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(0.0016*Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class TechOtaku: + moveSpeed = (int)(0.75*Constants.basicStudentSpeed) + maxHp = (int)(0.9*Constants.basicHp) + maxAddiction = (int)(1.1*Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.1*Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.9*Constants.basicLearnSpeed) + concealment = 1.0*Constants.basicConcealment + alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) + viewRange = (int)(0.9*Constants.basicStudentViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(0.75*Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class Sunshine: + moveSpeed = (int)(1.0*Constants.basicStudentSpeed) + maxHp = (int)(1.0667*Constants.basicHp) + maxAddiction = (int)(1.1*Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.0*Constants.basicLearnSpeed) + EncourageSpeed = (int)(2.0*Constants.basicLearnSpeed) + concealment = 1.0*Constants.basicConcealment + alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) + viewRange = (int)(1.0*Constants.basicStudentViewRange) + speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)(1.0*Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + +class CanBeginToCharge: + skillCD = (int)(0.8*Constants.commonSkillCD) + durationTime = (int)(0.5*Constants.commonSkillTime) + +class BecomeInvisible: + skillCD = (int)(4*Constants.commonSkillCD/3) + durationTime = (int)(Constants.commonSkillTime) + +class Punish: + skillCD = (int)(1.0*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) + +class Rouse: + skillCD = (int)(2.0*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) + +class Encourage: + skillCD = (int)(2.0*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) + +class Inspire: + skillCD = (int)(2.0*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) + +class Howl: + skillCD = (int)(0.8333*Constants.commonSkillCD) + durationTime = (int)(0*Constants.commonSkillTime) + +class ShowTime: + skillCD = (int)(3.0*Constants.commonSkillCD) + durationTime = (int)(1.0*Constants.commonSkillTime) + +class JumpyBomb: + skillCD = (int)(0.5*Constants.commonSkillCD) + durationTime = (int)(0.3*Constants.commonSkillTime) + +class UseKnife: + skillCD = (int)(1.0*Constants.commonSkillCD) + durationTime = (int)(0.1*Constants.commonSkillTime) + +class UseRobot: + skillCD = (int)(0.0017*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) + +class WriteAnswers: + skillCD = (int)(1.0*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) + +class SummonGolem: + skillCD = (int)(1.0*Constants.commonSkillCD) + durationTime = (int)(0.0*Constants.commonSkillTime) diff --git a/logic/GameRules.md b/logic/GameRules.md index cb06b8d..fe087b1 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,7 +1,7 @@ # 规则 V3.7 - [规则](#规则) - - [规则](#规则-1) + - [简则](#简则) - [地图](#地图) - [人物](#人物) - [攻击](#攻击) @@ -13,7 +13,7 @@ V3.7 - [窗](#窗) - [箱子](#箱子) - [信息相关](#信息相关) - - [视野](#视野) + - [可视范围](#可视范围) - [道具](#道具) - [得分](#得分) - [捣蛋鬼](#捣蛋鬼) @@ -29,7 +29,6 @@ V3.7 - [教师](#教师) - [学霸](#学霸) - [开心果](#开心果) - - [接口一览](#接口一览) - [细则](#细则) - [特殊说明](#特殊说明) - [移动](#移动) @@ -46,7 +45,7 @@ V3.7 - [信息获取](#信息获取) - [键鼠控制](#键鼠控制) -## 规则 +## 简则 ### 地图 - 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。 @@ -132,14 +131,14 @@ V3.7 3. 学习的声音: 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 4. 可以向其他每一个队友发送不超过256字节的信息 -### 视野 -- 可视范围 +### 可视范围 - 小于视野半径,且受限于墙和草地 - 对于在从草地中的物体,物体与玩家连线上均为草地方可见 ### 道具 - 玩家最多同时拥有三个道具 - 可以捡起与自己处于同一个格子(cell)的道具,或将道具扔在原地 + | 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| @@ -280,108 +279,6 @@ V3.7 - 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff - 每鼓舞一个学生得分10 -## 接口一览 -~~~csharp - // 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 - virtual std::future Move(int64_t timeInMilliseconds, double angleInRadian) = 0; - - // 向特定方向移动 - virtual std::future MoveRight(int64_t timeInMilliseconds) = 0; - virtual std::future MoveUp(int64_t timeInMilliseconds) = 0; - virtual std::future MoveLeft(int64_t timeInMilliseconds) = 0; - virtual std::future MoveDown(int64_t timeInMilliseconds) = 0; - - // 捡道具、使用技能 - virtual std::future PickProp(THUAI6::PropType prop) = 0; - virtual std::future UseProp(THUAI6::PropType prop) = 0; - virtual std::future UseSkill(int32_t skillID) = 0; - virtual std::future Attack(double angleInRadian) = 0; - - virtual std::future OpenDoor() = 0; - virtual std::future CloseDoor() = 0; - virtual std::future SkipWindow() = 0; - virtual std::future StartOpenGate() = 0; - virtual std::future StartOpenChest() = 0; - virtual std::future EndAllAction() = 0; - - // 发送信息、接受信息,注意收消息时无消息则返回nullopt - virtual std::future SendMessage(int64_t, std::string) = 0; - [[nodiscard]] virtual bool HaveMessage() = 0; - [[nodiscard]] virtual std::pair GetMessage() = 0; - - // 等待下一帧 - virtual std::future Wait() = 0; - - // 获取视野内可见的学生/捣蛋鬼的信息 - [[nodiscard]] virtual std::vector> GetStudents() const = 0; - [[nodiscard]] virtual std::vector> GetTrickers() const = 0; - - // 获取视野内可见的道具信息 - [[nodiscard]] virtual std::vector> GetProps() const = 0; - - // 获取地图信息,视野外的地图统一为Land - [[nodiscard]] virtual std::vector> GetFullMap() const = 0; - [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; - - [[nodiscard]] virtual bool IsDoorOpen(int32_t cellX, int32_t cellY) const = 0; - [[nodiscard]] virtual int32_t GetChestProgress(int32_t cellX, int32_t cellY) const = 0; - [[nodiscard]] virtual int32_t GetGateProgress(int32_t cellX, int32_t cellY) const = 0; - [[nodiscard]] virtual int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const = 0; - [[nodiscard]] virtual THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const = 0; - [[nodiscard]] virtual int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const = 0; - - [[nodiscard]] virtual std::shared_ptr GetGameInfo() const = 0; - - // 获取所有玩家的GUID - [[nodiscard]] virtual std::vector GetPlayerGUIDs() const = 0; - - // 获取游戏目前所进行的帧数 - [[nodiscard]] virtual int GetFrameCount() const = 0; - - /*****选手可能用的辅助函数*****/ - - // 获取指定格子中心的坐标 - [[nodiscard]] static inline int CellToGrid(int cell) noexcept - { - return cell * numOfGridPerCell + numOfGridPerCell / 2; - } - - // 获取指定坐标点所位于的格子的 X 序号 - [[nodiscard]] static inline int GridToCell(int grid) noexcept - { - return grid / numOfGridPerCell; - } - - // 用于DEBUG的输出函数,选手仅在开启Debug模式的情况下可以使用 - - virtual void Print(std::string str) const = 0; - virtual void PrintStudent() const = 0; - virtual void PrintTricker() const = 0; - virtual void PrintProp() const = 0; - virtual void PrintSelfInfo() const = 0; -}; - -class IStudentAPI : public IAPI -{ -public: - /*****学生阵营的特定函数*****/ - - virtual std::future StartLearning() = 0; - virtual std::future StartEncourageMate(int64_t mateID) = 0; - virtual std::future StartRouseMate(int64_t mateID) = 0; - virtual std::future Graduate() = 0; - [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; -}; - -class ITrickerAPI : public IAPI -{ -public: - /*****捣蛋鬼阵营的特定函数*****/ - - [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; -}; -~~~ - ## 细则 ### 特殊说明 From 2ffc982ea2b6d25662daf68034488e680b110585 Mon Sep 17 00:00:00 2001 From: DragonAura <32223554+DragonAura@users.noreply.github.com> Date: Wed, 12 Apr 2023 16:37:19 +0800 Subject: [PATCH 26/37] =?UTF-8?q?Rename=20CPAI=E6=8E=A5=E5=8F=A3.md=20to?= =?UTF-8?q?=20CAPI=E6=8E=A5=E5=8F=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAPI/{CPAI接口.md => CAPI接口.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename CAPI/{CPAI接口.md => CAPI接口.md} (99%) diff --git a/CAPI/CPAI接口.md b/CAPI/CAPI接口.md similarity index 99% rename from CAPI/CPAI接口.md rename to CAPI/CAPI接口.md index 4b1c230..77ccfc3 100644 --- a/CAPI/CPAI接口.md +++ b/CAPI/CAPI接口.md @@ -199,4 +199,4 @@ public: [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; }; -~~~ \ No newline at end of file +~~~ From e93b65a32da760e133e0e058af4b599044b53289 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Wed, 12 Apr 2023 16:45:58 +0800 Subject: [PATCH 27/37] refactor(CAPI): :art: change names --- CAPI/cpp/API/include/constants.h | 18 +- CAPI/cpp/API/include/structures.h | 6 +- CAPI/cpp/API/src/DebugAPI.cpp | 6 +- CAPI/python/PyAPI/DebugAPI.py | 6 +- CAPI/python/PyAPI/constants.py | 291 +++++++++++++++++------------- CAPI/python/PyAPI/structures.py | 14 +- CAPI/python/PyAPI/utils.py | 14 +- 7 files changed, 199 insertions(+), 156 deletions(-) diff --git a/CAPI/cpp/API/include/constants.h b/CAPI/cpp/API/include/constants.h index bafde1c..a741d73 100644 --- a/CAPI/cpp/API/include/constants.h +++ b/CAPI/cpp/API/include/constants.h @@ -25,7 +25,7 @@ namespace Constants SCCI int numOfRequiredClassroomForHiddenGate = 3; // 打开隐藏门需要完成的教室数量 // 人物属性相关 - SCCI int basicTreatSpeed = 100; + SCCI int basicEncourageSpeed = 100; SCCI int basicFixSpeed = 123; SCCI int basicSpeedOfOpeningOrLocking = 4000; SCCI int basicStudentSpeedOfClimbingThroughWindows = 611; @@ -34,8 +34,8 @@ namespace Constants SCCI int basicHp = 3000000; SCCI int basicMaxGamingAddiction = 60000; - SCCI int basicTreatmentDegree = 1500000; - SCCI int basicTimeOfRescue = 1000; + SCCI int basicEncouragementDegree = 1500000; + SCCI int basicTimeOfRouse = 1000; SCCI int basicStudentSpeed = 1270; SCCI int basicTrickerSpeed = 1504; @@ -119,7 +119,7 @@ namespace Constants SCCI int maxHp = basicHp; SCCI int maxAddiction = basicMaxGamingAddiction * 9 / 10; SCCI int fixSpeed = basicFixSpeed * 6 / 10; - SCCI int treatSpeed = basicTreatSpeed * 8 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; SCCI double concealment = 0.9; SCCI int alertnessRadius = basicStudentAlertnessRadius; SCCI int viewRange = basicStudentViewRange * 11 / 10; @@ -134,7 +134,7 @@ namespace Constants SCCI int maxHp = basicHp * 10; SCCI int maxAddiction = basicMaxGamingAddiction * 10; SCCI int fixSpeed = basicFixSpeed * 0; - SCCI int treatSpeed = basicTreatSpeed * 7 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 7 / 10; SCCI double concealment = 0.5; SCCI int alertnessRadius = basicStudentAlertnessRadius / 2; SCCI int viewRange = basicStudentViewRange * 9 / 10; @@ -149,7 +149,7 @@ namespace Constants SCCI int maxHp = basicHp * 11 / 10; SCCI int maxAddiction = basicMaxGamingAddiction * 13 / 10; SCCI int fixSpeed = basicFixSpeed * 11 / 10; - SCCI int treatSpeed = basicTreatSpeed * 8 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; SCCI double concealment = 0.9; SCCI int alertnessRadius = basicStudentAlertnessRadius * 9 / 10; SCCI int viewRange = basicStudentViewRange * 9 / 10; @@ -164,7 +164,7 @@ namespace Constants SCCI int maxHp = basicHp * 0.4; SCCI int maxAddiction = basicMaxGamingAddiction * 0; SCCI int fixSpeed = basicFixSpeed; - SCCI int treatSpeed = basicTreatSpeed * 8 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; SCCI double concealment = 1; SCCI int alertnessRadius = basicStudentAlertnessRadius * 1; SCCI int viewRange = basicStudentViewRange; @@ -179,7 +179,7 @@ namespace Constants SCCI int maxHp = basicHp * 9 / 10; SCCI int maxAddiction = basicMaxGamingAddiction * 11 / 10; SCCI int fixSpeed = basicFixSpeed * 11 / 10; - SCCI int treatSpeed = basicTreatSpeed * 9 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 9 / 10; SCCI double concealment = 1; SCCI int alertnessRadius = basicStudentAlertnessRadius; SCCI int viewRange = basicStudentViewRange * 9 / 10; @@ -194,7 +194,7 @@ namespace Constants SCCI int maxHp = basicHp * 32 / 30; SCCI int maxAddiction = basicMaxGamingAddiction * 11 / 10; SCCI int fixSpeed = basicFixSpeed; - SCCI int treatSpeed = basicTreatSpeed * 2; + SCCI int encourageSpeed = basicEncourageSpeed * 2; SCCI double concealment = 1; SCCI int alertnessRadius = basicStudentAlertnessRadius; SCCI int viewRange = basicStudentViewRange; diff --git a/CAPI/cpp/API/include/structures.h b/CAPI/cpp/API/include/structures.h index a3d859d..1849f43 100644 --- a/CAPI/cpp/API/include/structures.h +++ b/CAPI/cpp/API/include/structures.h @@ -195,9 +195,9 @@ namespace THUAI6 int32_t determination; // 剩余毅力 int32_t addiction; // 沉迷程度 int32_t learningSpeed; - int32_t treatSpeed; - int32_t treatProgress; - int32_t rescueProgress; + int32_t encourageSpeed; + int32_t encourageProgress; + int32_t rouseProgress; double dangerAlert; std::vector buff; // buff }; diff --git a/CAPI/cpp/API/src/DebugAPI.cpp b/CAPI/cpp/API/src/DebugAPI.cpp index 1bbab12..7861349 100644 --- a/CAPI/cpp/API/src/DebugAPI.cpp +++ b/CAPI/cpp/API/src/DebugAPI.cpp @@ -661,7 +661,7 @@ void StudentDebugAPI::PrintStudent() const props += THUAI6::propTypeDict[prop] + ", "; logger->info("state={}, bullet={}, props={}", THUAI6::playerStateDict[student->playerState], THUAI6::bulletTypeDict[student->bulletType], props); logger->info("type={}, determination={}, addiction={}, danger alert={}", THUAI6::studentTypeDict[student->studentType], student->determination, student->addiction, student->dangerAlert); - logger->info("learning speed={}, treat speed={}, treat progress={}, rescue progress={}", student->learningSpeed, student->treatSpeed, student->treatProgress, student->rescueProgress); + logger->info("learning speed={}, encourage speed={}, encourage progress={}, rouse progress={}", student->learningSpeed, student->encourageSpeed, student->encourageProgress, student->rouseProgress); std::string studentBuff = ""; for (const auto& buff : student->buff) studentBuff += THUAI6::studentBuffDict[buff] + ", "; @@ -686,7 +686,7 @@ void TrickerDebugAPI::PrintStudent() const props += THUAI6::propTypeDict[prop] + ", "; logger->info("state={}, bullet={}, props={}", THUAI6::playerStateDict[student->playerState], THUAI6::bulletTypeDict[student->bulletType], props); logger->info("type={}, determination={}, addiction={}, danger alert={}", THUAI6::studentTypeDict[student->studentType], student->determination, student->addiction, student->dangerAlert); - logger->info("learning speed={}, treat speed={}, treat progress={}, rescue progress={}", student->learningSpeed, student->treatSpeed, student->treatProgress, student->rescueProgress); + logger->info("learning speed={}, encourage speed={}, encourage progress={}, rouse progress={}", student->learningSpeed, student->encourageSpeed, student->encourageProgress, student->rouseProgress); std::string studentBuff = ""; for (const auto& buff : student->buff) studentBuff += THUAI6::studentBuffDict[buff] + ", "; @@ -778,7 +778,7 @@ void StudentDebugAPI::PrintSelfInfo() const props += THUAI6::propTypeDict[prop] + ", "; logger->info("state={}, bullet={}, props={}", THUAI6::playerStateDict[student->playerState], THUAI6::bulletTypeDict[student->bulletType], props); logger->info("type={}, determination={}, addiction={}, danger alert={}", THUAI6::studentTypeDict[student->studentType], student->determination, student->addiction, student->dangerAlert); - logger->info("learning speed={}, treat speed={}, treat progress={}, rescue progress={}", student->learningSpeed, student->treatSpeed, student->treatProgress, student->rescueProgress); + logger->info("learning speed={}, encourage speed={}, encourage progress={}, rouse progress={}", student->learningSpeed, student->encourageSpeed, student->encourageProgress, student->rouseProgress); std::string studentBuff = ""; for (const auto& buff : student->buff) studentBuff += THUAI6::studentBuffDict[buff] + ", "; diff --git a/CAPI/python/PyAPI/DebugAPI.py b/CAPI/python/PyAPI/DebugAPI.py index 6901474..d8122e1 100644 --- a/CAPI/python/PyAPI/DebugAPI.py +++ b/CAPI/python/PyAPI/DebugAPI.py @@ -326,7 +326,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): self.__logger.info( f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}") self.__logger.info( - f"learning speed={student.learningSpeed}, treat speed={student.treatSpeed}, treat progress={student.treatProgress}, rescue progress={student.rescueProgress}") + f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}") studentBuff = "" for buff in student.buff: studentBuff += buff.name + ", " @@ -379,7 +379,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): self.__logger.info( f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}") self.__logger.info( - f"learning speed={student.learningSpeed}, treat speed={student.treatSpeed}, treat progress={student.treatProgress}, rescue progress={student.rescueProgress}") + f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}") studentBuff = "" for buff in student.buff: studentBuff += buff.name + ", " @@ -778,7 +778,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): self.__logger.info( f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}") self.__logger.info( - f"learning speed={student.learningSpeed}, treat speed={student.treatSpeed}, treat progress={student.treatProgress}, rescue progress={student.rescueProgress}") + f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}") studentBuff = "" for buff in student.buff: studentBuff += buff.name + ", " diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index 86b2dc5..fa944a2 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -40,13 +40,13 @@ class Constants(NoInstance): basicTrickerSpeed = 1504 basicConcealment = 1.0 - basicStudentalertnessRadius = 15 * numOfGridPerCell - basicTrickeralertnessRadius = 17 * numOfGridPerCell - basicStudentviewRange = 10 * numOfGridPerCell - basicTrickerviewRange = 15 * numOfGridPerCell + basicStudentAlertnessRadius = 15 * numOfGridPerCell + basicTrickerAlertnessRadius = 17 * numOfGridPerCell + basicStudentViewRange = 10 * numOfGridPerCell + basicTrickerViewRange = 15 * numOfGridPerCell PinningDownRange = 5 * numOfGridPerCell - maxNumOfProp = 3 # 人物道具栏容量 + maxNumOfProp = 3 # 人物道具栏容量 # 攻击相关 @@ -85,168 +85,211 @@ class Constants(NoInstance): addedTimeOfSpeedWhenInspire = 0.6 timeOfAddingSpeedWhenInspire = 6000 + class Assassin: - moveSpeed = (int)(1.1*Constants.basicTrickerSpeed) - concealment = 1.5*Constants.basicConcealment - alertnessRadius = (int)(1.3*Constants.basicTrickerAlertnessRadius) - viewRange = (int)(1.2*Constants.basicTrickerViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(1.0*Constants.basicTrickerSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.1 * Constants.basicTrickerSpeed) + concealment = 1.5 * Constants.basicConcealment + alertnessRadius = (int)(1.3 * Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.2 * Constants.basicTrickerViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class Klee: - moveSpeed = (int)(1.0*Constants.basicTrickerSpeed) - concealment = 1.0*Constants.basicConcealment - alertnessRadius = (int)(1.0*Constants.basicTrickerAlertnessRadius) - viewRange = (int)(1.0*Constants.basicTrickerViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(1.0*Constants.basicTrickerSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.1*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.0 * Constants.basicTrickerSpeed) + concealment = 1.0 * Constants.basicConcealment + alertnessRadius = (int)(1.0 * Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.0 * Constants.basicTrickerViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.1 * Constants.basicSpeedOfOpenChest) + class ANoisyPerson: - moveSpeed = (int)(1.07*Constants.basicTrickerSpeed) - concealment = 0.8*Constants.basicConcealment - alertnessRadius = (int)(0.9*Constants.basicTrickerAlertnessRadius) - viewRange = (int)(1.0*Constants.basicTrickerViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(1.1*Constants.basicTrickerSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.1*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.07 * Constants.basicTrickerSpeed) + concealment = 0.8 * Constants.basicConcealment + alertnessRadius = (int)(0.9 * Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.0 * Constants.basicTrickerViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 1.1 * Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.1 * Constants.basicSpeedOfOpenChest) + class Idol: - moveSpeed = (int)(1.0*Constants.basicTrickerSpeed) - concealment = 0.75*Constants.basicConcealment - alertnessRadius = (int)(1.0*Constants.basicTrickerAlertnessRadius) - viewRange = (int)(1.1*Constants.basicTrickerViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(1.0*Constants.basicTrickerSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.0 * Constants.basicTrickerSpeed) + concealment = 0.75 * Constants.basicConcealment + alertnessRadius = (int)(1.0 * Constants.basicTrickerAlertnessRadius) + viewRange = (int)(1.1 * Constants.basicTrickerViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class Athlete: - moveSpeed = (int)(1.1*Constants.basicStudentSpeed) - maxHp = (int)(1.0*Constants.basicHp) - maxAddiction = (int)(0.9*Constants.basicMaxGamingAddiction) - LearnSpeed = (int)(0.6*Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.8*Constants.basicLearnSpeed) - concealment = 0.9*Constants.basicConcealment - alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) - viewRange = (int)(1.1*Constants.basicStudentViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(1.2*Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.1 * Constants.basicStudentSpeed) + maxHp = (int)(1.0 * Constants.basicHp) + maxAddiction = (int)(0.9 * Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(0.6 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8 * Constants.basicLearnSpeed) + concealment = 0.9 * Constants.basicConcealment + alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) + viewRange = (int)(1.1 * Constants.basicStudentViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 1.2 * Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class Teacher: - moveSpeed = (int)(0.75*Constants.basicStudentSpeed) - maxHp = (int)(10.0*Constants.basicHp) - maxAddiction = (int)(10.0*Constants.basicMaxGamingAddiction) - LearnSpeed = (int)(0.0*Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.7*Constants.basicLearnSpeed) - concealment = 0.5*Constants.basicConcealment - alertnessRadius = (int)(0.5*Constants.basicStudentAlertnessRadius) - viewRange = (int)(0.9*Constants.basicStudentViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(0.5*Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(0.75 * Constants.basicStudentSpeed) + maxHp = (int)(10.0 * Constants.basicHp) + maxAddiction = (int)(10.0 * Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(0.0 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.7 * Constants.basicLearnSpeed) + concealment = 0.5 * Constants.basicConcealment + alertnessRadius = (int)(0.5 * Constants.basicStudentAlertnessRadius) + viewRange = (int)(0.9 * Constants.basicStudentViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 0.5 * Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class StraightAStudent: - moveSpeed = (int)(0.8*Constants.basicStudentSpeed) - maxHp = (int)(1.1*Constants.basicHp) - maxAddiction = (int)(1.3*Constants.basicMaxGamingAddiction) - LearnSpeed = (int)(1.1*Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.8*Constants.basicLearnSpeed) - concealment = 0.9*Constants.basicConcealment - alertnessRadius = (int)(0.9*Constants.basicStudentAlertnessRadius) - viewRange = (int)(0.9*Constants.basicStudentViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(0.83333*Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(0.8 * Constants.basicStudentSpeed) + maxHp = (int)(1.1 * Constants.basicHp) + maxAddiction = (int)(1.3 * Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.1 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8 * Constants.basicLearnSpeed) + concealment = 0.9 * Constants.basicConcealment + alertnessRadius = (int)(0.9 * Constants.basicStudentAlertnessRadius) + viewRange = (int)(0.9 * Constants.basicStudentViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 0.83333 * Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class Robot: - moveSpeed = (int)(1.0*Constants.basicStudentSpeed) - maxHp = (int)(0.4*Constants.basicHp) - maxAddiction = (int)(0.0*Constants.basicMaxGamingAddiction) - LearnSpeed = (int)(1.0*Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.8*Constants.basicLearnSpeed) - concealment = 1.0*Constants.basicConcealment - alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) - viewRange = (int)(1.0*Constants.basicStudentViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(0.0016*Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.0 * Constants.basicStudentSpeed) + maxHp = (int)(0.4 * Constants.basicHp) + maxAddiction = (int)(0.0 * Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.0 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8 * Constants.basicLearnSpeed) + concealment = 1.0 * Constants.basicConcealment + alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) + viewRange = (int)(1.0 * Constants.basicStudentViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 0.0016 * Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class TechOtaku: - moveSpeed = (int)(0.75*Constants.basicStudentSpeed) - maxHp = (int)(0.9*Constants.basicHp) - maxAddiction = (int)(1.1*Constants.basicMaxGamingAddiction) - LearnSpeed = (int)(1.1*Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.9*Constants.basicLearnSpeed) - concealment = 1.0*Constants.basicConcealment - alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) - viewRange = (int)(0.9*Constants.basicStudentViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(0.75*Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(0.75 * Constants.basicStudentSpeed) + maxHp = (int)(0.9 * Constants.basicHp) + maxAddiction = (int)(1.1 * Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.1 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.9 * Constants.basicLearnSpeed) + concealment = 1.0 * Constants.basicConcealment + alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) + viewRange = (int)(0.9 * Constants.basicStudentViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 0.75 * Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class Sunshine: - moveSpeed = (int)(1.0*Constants.basicStudentSpeed) - maxHp = (int)(1.0667*Constants.basicHp) - maxAddiction = (int)(1.1*Constants.basicMaxGamingAddiction) - LearnSpeed = (int)(1.0*Constants.basicLearnSpeed) - EncourageSpeed = (int)(2.0*Constants.basicLearnSpeed) - concealment = 1.0*Constants.basicConcealment - alertnessRadius = (int)(1.0*Constants.basicStudentAlertnessRadius) - viewRange = (int)(1.0*Constants.basicStudentViewRange) - speedOfOpeningOrLocking =(int)( 1.0*Constants.basicSpeedOfOpeningOrLocking) - speedOfClimbingThroughWindows = (int)(1.0*Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0*Constants.basicSpeedOfOpenChest) + moveSpeed = (int)(1.0 * Constants.basicStudentSpeed) + maxHp = (int)(1.0667 * Constants.basicHp) + maxAddiction = (int)(1.1 * Constants.basicMaxGamingAddiction) + LearnSpeed = (int)(1.0 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(2.0 * Constants.basicLearnSpeed) + concealment = 1.0 * Constants.basicConcealment + alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) + viewRange = (int)(1.0 * Constants.basicStudentViewRange) + speedOfOpeningOrLocking = (int)( + 1.0 * Constants.basicSpeedOfOpeningOrLocking) + speedOfClimbingThroughWindows = (int)( + 1.0 * Constants.basicStudentSpeedOfClimbingThroughWindows) + speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + class CanBeginToCharge: - skillCD = (int)(0.8*Constants.commonSkillCD) - durationTime = (int)(0.5*Constants.commonSkillTime) + skillCD = (int)(0.8 * Constants.commonSkillCD) + durationTime = (int)(0.5 * Constants.commonSkillTime) + class BecomeInvisible: - skillCD = (int)(4*Constants.commonSkillCD/3) + skillCD = (int)(4 * Constants.commonSkillCD / 3) durationTime = (int)(Constants.commonSkillTime) + class Punish: - skillCD = (int)(1.0*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(1.0 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) + class Rouse: - skillCD = (int)(2.0*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(2.0 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) + class Encourage: - skillCD = (int)(2.0*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(2.0 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) + class Inspire: - skillCD = (int)(2.0*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(2.0 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) + class Howl: - skillCD = (int)(0.8333*Constants.commonSkillCD) - durationTime = (int)(0*Constants.commonSkillTime) + skillCD = (int)(0.8333 * Constants.commonSkillCD) + durationTime = (int)(0 * Constants.commonSkillTime) + class ShowTime: - skillCD = (int)(3.0*Constants.commonSkillCD) - durationTime = (int)(1.0*Constants.commonSkillTime) + skillCD = (int)(3.0 * Constants.commonSkillCD) + durationTime = (int)(1.0 * Constants.commonSkillTime) + class JumpyBomb: - skillCD = (int)(0.5*Constants.commonSkillCD) - durationTime = (int)(0.3*Constants.commonSkillTime) + skillCD = (int)(0.5 * Constants.commonSkillCD) + durationTime = (int)(0.3 * Constants.commonSkillTime) + class UseKnife: - skillCD = (int)(1.0*Constants.commonSkillCD) - durationTime = (int)(0.1*Constants.commonSkillTime) + skillCD = (int)(1.0 * Constants.commonSkillCD) + durationTime = (int)(0.1 * Constants.commonSkillTime) + class UseRobot: - skillCD = (int)(0.0017*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(0.0017 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) + class WriteAnswers: - skillCD = (int)(1.0*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(1.0 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) + class SummonGolem: - skillCD = (int)(1.0*Constants.commonSkillCD) - durationTime = (int)(0.0*Constants.commonSkillTime) + skillCD = (int)(1.0 * Constants.commonSkillCD) + durationTime = (int)(0.0 * Constants.commonSkillTime) diff --git a/CAPI/python/PyAPI/structures.py b/CAPI/python/PyAPI/structures.py index 9b3a6ff..dbd83fe 100644 --- a/CAPI/python/PyAPI/structures.py +++ b/CAPI/python/PyAPI/structures.py @@ -104,11 +104,11 @@ class PlayerState(Enum): Addicted = 3 Quit = 4 Graduated = 5 - Treated = 6 - Rescued = 7 + Encouraged = 6 + Roused = 7 Stunned = 8 - Treating = 9 - Rescuing = 10 + Encouraging = 9 + Rousing = 10 Swinging = 11 Attacking = 12 Locking = 13 @@ -163,10 +163,10 @@ class Student(Player): studentType: StudentType determination: int addiction: int - treatProgress: int - rescueProgress: int + encourageProgress: int + rouseProgress: int learningSpeed: int - treatSpeed: int + encourageSpeed: int dangerAlert: float buff: List[StudentBuffType] = [] diff --git a/CAPI/python/PyAPI/utils.py b/CAPI/python/PyAPI/utils.py index b90913a..c1e31e2 100644 --- a/CAPI/python/PyAPI/utils.py +++ b/CAPI/python/PyAPI/utils.py @@ -136,11 +136,11 @@ class Proto2THUAI6(NoInstance): MessageType.ADDICTED: THUAI6.PlayerState.Addicted, MessageType.QUIT: THUAI6.PlayerState.Quit, MessageType.GRADUATED: THUAI6.PlayerState.Graduated, - MessageType.RESCUED: THUAI6.PlayerState.Rescued, - MessageType.TREATED: THUAI6.PlayerState.Treated, + MessageType.RESCUED: THUAI6.PlayerState.Roused, + MessageType.TREATED: THUAI6.PlayerState.Encouraged, MessageType.STUNNED: THUAI6.PlayerState.Stunned, - MessageType.RESCUING: THUAI6.PlayerState.Rescuing, - MessageType.TREATING: THUAI6.PlayerState.Treating, + MessageType.RESCUING: THUAI6.PlayerState.Rousing, + MessageType.TREATING: THUAI6.PlayerState.Encouraging, MessageType.SWINGING: THUAI6.PlayerState.Swinging, MessageType.ATTACKING: THUAI6.PlayerState.Attacking, MessageType.LOCKING: THUAI6.PlayerState.Locking, @@ -207,9 +207,9 @@ class Proto2THUAI6(NoInstance): student.facingDirection = studentMsg.facing_direction student.bulletType = Proto2THUAI6.bulletTypeDict[studentMsg.bullet_type] student.learningSpeed = studentMsg.learning_speed - student.treatSpeed = studentMsg.treat_speed - student.treatProgress = studentMsg.treat_progress - student.rescueProgress = studentMsg.rescue_progress + student.encourageSpeed = studentMsg.treat_speed + student.encourageProgress = studentMsg.treat_progress + student.rouseProgress = studentMsg.rescue_progress student.dangerAlert = studentMsg.danger_alert student.timeUntilSkillAvailable.clear() for time in studentMsg.time_until_skill_available: From 45ea6f595a6438c729c7f7d8e26f2745a29fc208 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Wed, 12 Apr 2023 16:52:18 +0800 Subject: [PATCH 28/37] refactor(CAPI): :art: add some missing changes --- CAPI/cpp/API/include/structures.h | 16 ++++++++-------- CAPI/cpp/API/include/utils.hpp | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CAPI/cpp/API/include/structures.h b/CAPI/cpp/API/include/structures.h index 1849f43..88fd26c 100644 --- a/CAPI/cpp/API/include/structures.h +++ b/CAPI/cpp/API/include/structures.h @@ -126,11 +126,11 @@ namespace THUAI6 Addicted = 3, Quit = 4, Graduated = 5, - Treated = 6, - Rescued = 7, + Encouraged = 6, + Roused = 7, Stunned = 8, - Treating = 9, - Rescuing = 10, + Encouraging = 9, + Rousing = 10, Swinging = 11, Attacking = 12, Locking = 13, @@ -302,11 +302,11 @@ namespace THUAI6 {PlayerState::Addicted, "Addicted"}, {PlayerState::Quit, "Quit"}, {PlayerState::Graduated, "Graduated"}, - {PlayerState::Treated, "Treated"}, - {PlayerState::Rescued, "Rescued"}, + {PlayerState::Encouraged, "Encouraged"}, + {PlayerState::Roused, "Roused"}, {PlayerState::Stunned, "Stunned"}, - {PlayerState::Treating, "Treating"}, - {PlayerState::Rescuing, "Rescuing"}, + {PlayerState::Encouraging, "Encouraging"}, + {PlayerState::Rousing, "Rousing"}, {PlayerState::Swinging, "Swinging"}, {PlayerState::Attacking, "Attacking"}, {PlayerState::Locking, "Locking"}, diff --git a/CAPI/cpp/API/include/utils.hpp b/CAPI/cpp/API/include/utils.hpp index 2153925..dd550c7 100644 --- a/CAPI/cpp/API/include/utils.hpp +++ b/CAPI/cpp/API/include/utils.hpp @@ -146,11 +146,11 @@ namespace Proto2THUAI6 {protobuf::PlayerState::ADDICTED, THUAI6::PlayerState::Addicted}, {protobuf::PlayerState::QUIT, THUAI6::PlayerState::Quit}, {protobuf::PlayerState::GRADUATED, THUAI6::PlayerState::Graduated}, - {protobuf::PlayerState::RESCUED, THUAI6::PlayerState::Rescued}, - {protobuf::PlayerState::TREATED, THUAI6::PlayerState::Treated}, + {protobuf::PlayerState::RESCUED, THUAI6::PlayerState::Roused}, + {protobuf::PlayerState::TREATED, THUAI6::PlayerState::Encouraged}, {protobuf::PlayerState::STUNNED, THUAI6::PlayerState::Stunned}, - {protobuf::PlayerState::RESCUING, THUAI6::PlayerState::Rescuing}, - {protobuf::PlayerState::TREATING, THUAI6::PlayerState::Treating}, + {protobuf::PlayerState::RESCUING, THUAI6::PlayerState::Rousing}, + {protobuf::PlayerState::TREATING, THUAI6::PlayerState::Encouraging}, {protobuf::PlayerState::SWINGING, THUAI6::PlayerState::Swinging}, {protobuf::PlayerState::ATTACKING, THUAI6::PlayerState::Attacking}, {protobuf::PlayerState::LOCKING, THUAI6::PlayerState::Locking}, @@ -240,9 +240,9 @@ namespace Proto2THUAI6 student->facingDirection = studentMsg.facing_direction(); student->bulletType = bulletTypeDict[studentMsg.bullet_type()]; student->learningSpeed = studentMsg.learning_speed(); - student->treatSpeed = studentMsg.treat_speed(); - student->treatProgress = studentMsg.treat_progress(); - student->rescueProgress = studentMsg.rescue_progress(); + student->encourageSpeed = studentMsg.treat_speed(); + student->encourageProgress = studentMsg.treat_progress(); + student->rouseProgress = studentMsg.rescue_progress(); student->dangerAlert = studentMsg.danger_alert(); student->timeUntilSkillAvailable.clear(); for (int i = 0; i < studentMsg.time_until_skill_available().size(); i++) From 96ef2da3a20682e2d767f7dd831ab1ee22a40f5a Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 17:05:36 +0800 Subject: [PATCH 29/37] =?UTF-8?q?build:=20:construction:=20add=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAPI/CPAI接口.md | 79 +++++++++++++++++++++---------------------- logic/GameRules.md | 36 +++----------------- logic/使用文档.md | 28 +++++++++++++++ 3 files changed, 70 insertions(+), 73 deletions(-) create mode 100644 logic/使用文档.md diff --git a/CAPI/CPAI接口.md b/CAPI/CPAI接口.md index 4b1c230..7d2e4da 100644 --- a/CAPI/CPAI接口.md +++ b/CAPI/CPAI接口.md @@ -1,35 +1,36 @@ -# CAPI接口 - [CAPI接口](#capi接口) - [接口解释](#接口解释) - - [移动](#移动) - - [使用技能](#使用技能) - - [人物](#人物) - - [攻击](#攻击) + - [主动指令](#主动指令) + - [移动](#移动) + - [使用技能](#使用技能) + - [人物](#人物) + - [攻击](#攻击) - [学习与毕业](#学习与毕业) - - [勉励](#勉励) - - [沉迷与唤醒](#沉迷与唤醒) - - [门](#门) - - [窗](#窗) - - [箱子](#箱子) - - [队内信息](#队内信息) + - [勉励与唤醒](#勉励与唤醒) + - [地图互动](#地图互动) + - [道具](#道具) - [信息获取](#信息获取) - - [辅助函数](#辅助函数) - - [道具](#道具) + - [队内信息](#队内信息) + - [查询可视范围内的信息](#查询可视范围内的信息) + - [查询特定位置物体的信息,下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。](#查询特定位置物体的信息下面的-cellx-和-celly-指的是地图格数而非绝对坐标) + - [其他](#其他) + - [辅助函数](#辅助函数) - [接口一览](#接口一览) - +# CAPI接口 ## 接口解释 -### 移动 +### 主动指令 +#### 移动 - `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴** -- `bool MoveRight(uint32_t timeInMilliseconds)`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理 +- `std::future MoveRight(uint32_t timeInMilliseconds)`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理 -### 使用技能 +#### 使用技能 - `std::future UseSkill(int32_t skillID)`:使用对应序号的主动技能 -### 人物 +#### 人物 - `std::future EndAllAction()`:可以使不处在不可行动状态中的玩家终止当前行动 -### 攻击 +#### 攻击 - `std::future Attack(double angleInRadian)`:`angleInRadian`为攻击方向 #### 学习与毕业 @@ -37,35 +38,35 @@ - `std::future StartOpenGate()`:开始开启校门 - `std::future Graduate()`:从开启的校门或隐藏校门毕业。 -#### 勉励 -- `std::future StartEncourageMate(int64_t mateID)`:勉励对应玩家ID的学生, - -#### 沉迷与唤醒 +#### 勉励与唤醒 +- `std::future StartEncourageMate(int64_t mateID)`:勉励对应玩家ID的学生。 - `std::future StartRouseMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生。 -#### 门 +#### 地图互动 - `std::future OpenDoor()`:开门 - `std::future CloseDoor()`:关门 - -#### 窗 - `std::future SkipWindow()`:翻窗 - -#### 箱子 - `std::future StartOpenChest()`:开箱 -### 队内信息 -- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。第一个参数指定发送的对象,第二个参数指定发送的内容,不得超过256字节。 -- `bool HaveMessage()`:是否有队友发来的尚未接收的信息。 -- `std::pair GetMessage()`:从玩家ID为第一个参数的队友获取信息。 +#### 道具 +- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 +- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 +- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 ### 信息获取 -- 查询可视范围内的信息 + +#### 队内信息 + - `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。第一个参数指定发送的对象,第二个参数指定发送的内容,不得超过256字节。 + - `bool HaveMessage()`:是否有队友发来的尚未接收的信息。 + - `std::pair GetMessage()`:从玩家ID为第一个参数的队友获取信息。 + +#### 查询可视范围内的信息 - `std::vector> GetStudents() const` :返回所有可视学生的信息。 - `std::vector> GetTrickers() const` :返回所有可视捣蛋鬼的信息。 - `std::vector> GetProps() const` :返回所有可视道具的信息。 - `std::vector> GetBullets() const` :返回所有可视子弹(攻击)的信息。 -- 查询特定位置物体的信息,下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 +#### 查询特定位置物体的信息,下面的 CellX 和 CellY 指的是地图格数,而非绝对坐标。 - `THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY)` :返回某一位置场地种类信息。场地种类详见 structure.h 。 - `bool IsDoorOpen(int32_t cellX, int32_t cellY) const`:查询特定位置门是否开启 - `int32_t GetChestProgress(int32_t cellX, int32_t cellY) const`:查询特定位置箱子开启进度 @@ -73,14 +74,15 @@ - `int32_t GetClassroomProgress(int32_t cellX, int32_t cellY) const`:查询特定位置教室作业完成进度 - `THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const`::查询特定位置隐藏校门状态 - `int32_t GetDoorProgress(int32_t cellX, int32_t cellY) const`:查询特定位置门开启状态 -- 其他 + +#### 其他 - `std::shared_ptr GetGameInfo() const`:查询当前游戏状态\ - `std::vector GetPlayerGUIDs() const`:获取所有玩家的GUID\ - `int GetFrameCount() const`:获取目前所进行的帧数\ - `std::shared_ptr GetSelfInfo() const`或`std::shared_ptr GetSelfInfo() const`:获取自己的信息 - `std::vector> GetFullMap() const`:返回整张地图的地形信息。 -## 辅助函数 +### 辅助函数 `static inline int CellToGrid(int cell) noexcept`:将地图格数 cell 转换为绝对坐标grid。 `static inline int GridToCell(int grid) noexcept`:将绝对坐标 grid 转换为地图格数cell。 @@ -94,11 +96,6 @@ void PrintSelfInfo() const; ~~~ -### 道具 -- `bool PickProp(THUAI6::PropType prop)`捡起与自己处于同一个格子(cell)的道具。 -- `bool UseProp(THUAI6::PropType prop)`使用对应类型的道具 -- `bool ThrowProp(THUAI6::PropType prop)`将对应类型的道具扔在原地 - ## 接口一览 ~~~csharp // 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 diff --git a/logic/GameRules.md b/logic/GameRules.md index fe087b1..e0ef0e7 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V3.7 +V3.9 - [规则](#规则) - [简则](#简则) - [地图](#地图) @@ -43,7 +43,6 @@ V3.7 - [窗](#窗-1) - [箱子](#箱子-1) - [信息获取](#信息获取) - - [键鼠控制](#键鼠控制) ## 简则 @@ -126,9 +125,9 @@ V3.7 - 开箱后将有2个随机道具掉落在玩家位置。 ### 信息相关 -1. 不详的感觉:捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) -2. 期待搞事的感觉:学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) -3. 学习的声音: 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 +1. 不详的感觉(dangerAlert):捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) +2. 期待搞事的感觉(trickDesire):学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) +3. 学习的声音(classVolume): 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 4. 可以向其他每一个队友发送不超过256字节的信息 ### 可视范围 @@ -337,30 +336,3 @@ V3.7 ### 信息获取 - 查询对应物体状态时物体不存在则返回false - -## 键鼠控制 - -| 键位 | 效果 | -| ------------ | ---------------------------------------------- | -| W/NumPad8 | (Both)向上移动 | -| S/NumPad2 | (Both)向下移动 | -| D/NumPad6 | (Both)向右移动 | -| A/NumPad4 | (Both)向左移动 | -| J | (Tri)攻击,方向向上 | -| 鼠标双击某点 | (Tri)攻击,方向与从Tricker指向该点的向量相同 | -| K | (Stu)开始学习 | -| R | (Stu)开始唤醒(陷入沉迷状态的同伴) | -| T | (Stu)开始勉励(学习毅力下降的同伴) | -| G | (Stu)发出毕业请求 | -| H | (Stu)申请毕业(或称为开校门) | -| O | (Both)开(教学楼)门 | -| P | (Both)关(教学楼)门 | -| U | (Both)翻窗 | -| I | (Both)翻箱子 | -| E | (Both)结束当前行动,回到Idle状态 | -| F | (Both)随机捡起一个在周围的道具 | -| C | (Both)随机扔下一个已经持有的道具 | -| V | (Both)随机使用一个已经持有的道具 | -| B | (Both)使用0号技能 | -| N | (Both)使用1号技能 | -| M | (Both)使用2号技能 | diff --git a/logic/使用文档.md b/logic/使用文档.md new file mode 100644 index 0000000..3f66b2d --- /dev/null +++ b/logic/使用文档.md @@ -0,0 +1,28 @@ + + +## 键鼠控制 + +| 键位 | 效果 | +| ------------ | ---------------------------------------------- | +| W/NumPad8 | (Both)向上移动 | +| S/NumPad2 | (Both)向下移动 | +| D/NumPad6 | (Both)向右移动 | +| A/NumPad4 | (Both)向左移动 | +| J | (Tri)攻击,方向向上 | +| 鼠标双击某点 | (Tri)攻击,方向与从Tricker指向该点的向量相同 | +| K | (Stu)开始学习 | +| R | (Stu)开始唤醒(陷入沉迷状态的同伴) | +| T | (Stu)开始勉励(学习毅力下降的同伴) | +| G | (Stu)发出毕业请求 | +| H | (Stu)申请毕业(或称为开校门) | +| O | (Both)开(教学楼)门 | +| P | (Both)关(教学楼)门 | +| U | (Both)翻窗 | +| I | (Both)翻箱子 | +| E | (Both)结束当前行动,回到Idle状态 | +| F | (Both)随机捡起一个在周围的道具 | +| C | (Both)随机扔下一个已经持有的道具 | +| V | (Both)随机使用一个已经持有的道具 | +| B | (Both)使用0号技能 | +| N | (Both)使用1号技能 | +| M | (Both)使用2号技能 | From 6a95b3fa9a214eef249386e72990f1cb27fd93b8 Mon Sep 17 00:00:00 2001 From: Shawqeem <1004837646@qq.com> Date: Wed, 12 Apr 2023 20:04:23 +0800 Subject: [PATCH 30/37] refactor: :art: add ID to each student add ID to each student --- logic/Client/MainWindow.xaml.cs | 51 ++++++++++++++++++--------- logic/GameRules.md | 62 ++++++++++++++++----------------- logic/cmd/gameServer.cmd | 4 +-- 3 files changed, 68 insertions(+), 49 deletions(-) diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 8fac56f..603597a 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -745,7 +745,22 @@ namespace Client Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * radiusTimes, data.X * unitHeight / 1000.0 - unitHeight * radiusTimes, 0, 0), Fill = Brushes.BlueViolet, }; + TextBox num = new() + { + FontSize = 7 * UpperLayerOfMap.ActualHeight / 650, + Width = 2 * radiusTimes * unitWidth, + Height = 2 * radiusTimes * unitHeight, + Text = Convert.ToString(data.PlayerId), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * radiusTimes, data.X * unitHeight / 1000.0 - unitHeight * radiusTimes, 0, 0), + Background = Brushes.Transparent, + BorderBrush = Brushes.Transparent, + IsReadOnly = true, + Foreground = Brushes.White, + }; UpperLayerOfMap.Children.Add(icon); + UpperLayerOfMap.Children.Add(num); } } foreach (var data in listOfButcher) @@ -836,27 +851,31 @@ namespace Client { case Protobuf.BulletType.BombBomb: { - Ellipse icon = new(); - double bombRange = data.BombRange / 1000; - icon.Width = bombRange * unitWidth; - icon.Height = bombRange * unitHeight; - icon.HorizontalAlignment = HorizontalAlignment.Left; - icon.VerticalAlignment = VerticalAlignment.Top; - icon.Margin = new Thickness(data.Y * unitWidth / 1000.0 - bombRange * unitWidth / 2, data.X * unitHeight / 1000.0 - bombRange * unitHeight / 2, 0, 0); - icon.Fill = Brushes.Red; + double bombRange = 1.0*data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; + Ellipse icon = new() + { + Width = 2 * bombRange * unitWidth, + Height = 2 * bombRange * unitHeight, + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bombRange, data.X * unitHeight / 1000.0 - unitHeight * bombRange, 0, 0), + Fill = Brushes.DarkRed, + }; UpperLayerOfMap.Children.Add(icon); break; } case Protobuf.BulletType.JumpyDumpty: { - Ellipse icon = new(); - double bombRange = data.BombRange / 1000; - icon.Width = bombRange * unitWidth; - icon.Height = bombRange * unitHeight; - icon.HorizontalAlignment = HorizontalAlignment.Left; - icon.VerticalAlignment = VerticalAlignment.Top; - icon.Margin = new Thickness(data.Y * unitWidth / 1000.0 - bombRange * unitWidth / 2, data.X * unitHeight / 1000.0 - bombRange * unitHeight / 2, 0, 0); - icon.Fill = Brushes.Red; + double bombRange = 1.0 * data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; + Ellipse icon = new() + { + Width = 2 * bombRange * unitWidth, + Height = 2 * bombRange * unitHeight, + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bombRange, data.X * unitHeight / 1000.0 - unitHeight * bombRange, 0, 0), + Fill = Brushes.DarkViolet, + }; UpperLayerOfMap.Children.Add(icon); break; } diff --git a/logic/GameRules.md b/logic/GameRules.md index e0ef0e7..917f786 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V3.9 +V4.0 - [规则](#规则) - [简则](#简则) - [地图](#地图) @@ -81,15 +81,15 @@ V3.9 - 攻击类型CommonAttackOfGhost攻击未写完的作业,会造成对应攻击力的损坏 - 捣蛋鬼攻击交互状态或前后摇的学生,将使学生眩晕4.3s -| 攻击类型 |搞蛋鬼的一般攻击CommonAttackOfGhost| 飞刀FlyingKnife | 蹦蹦炸弹BombBomb | JumpyDumpty | +| 攻击类型 |搞蛋鬼的一般攻击CommonAttackOfGhost| 飞刀FlyingKnife | 蹦蹦炸弹BombBomb | 小炸弹JumpyDumpty | | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | -| 子弹爆炸范围 | 0 | 0 | 1000 | 500 | +| 子弹爆炸范围 | 0 | 0 | 1000 | 500 | | 子弹攻击距离 | 1100 | 39000 | 1100 | 2200 | -| 攻击力 | 1500000 | 1200000 | 1,800,000 | 900000 | -| 移动速度/s | 3700 | 9250 | 3000 | 4300 | -| 前摇(ms) | 297 | 400 | 366 | 0 | -|未攻击至目标时的后摇(ms)| 800 | 0 | 3700 | 0 | -|攻击至目标时的后摇(ms)| 3700 | 0 | 3700 | 0 | +| 攻击力 | 1500000 | 1200000 | 1,800,000 | 900000 | +| 移动速度/s | 3700 | 9250 | 3000 | 4300 | +| 前摇(ms) | 297 | 400 | 366 | - | +|未攻击至目标时的后摇(ms)| 800 | 0 | 3700 | - | +|攻击至目标时的后摇(ms)| 3700 | 0 | 3700 | - | | CD(ms) | 800 | 400 | 3000 | - | | 最大子弹容量 | 1 | 1 | 1 | - | @@ -138,16 +138,16 @@ V3.9 - 玩家最多同时拥有三个道具 - 可以捡起与自己处于同一个格子(cell)的道具,或将道具扔在原地 -| 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | +| 道具 | 对学生增益 | 学生得分条件 | 对搞蛋鬼增益 | 搞蛋鬼得分条件 | | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| -| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| -| Key5 | 能开启5教的门 |不得分| 能开启5教的门 |不得分| -| Key6 | 能开启6教的门 |不得分| 能开启6教的门 |不得分| +| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| +| Key5 | 能开启5教的门 |不得分| 能开启5教的门 |不得分| +| Key6 | 能开启6教的门 |不得分| 能开启6教的门 |不得分| | AddSpeed | 2倍速,持续10s | 得分10| 2倍速,持续10s |得分10| -| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分100 |10秒内得知全场玩家信息|得分10 | +| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分100 |10秒内得知全场玩家信息|得分10 | | AddHpOrAp |回血750000 | 回血成功,得分10 | 10秒内下一次攻击增伤1800000|不得分 | -| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害,得分50 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内破盾,得分50 | -| RecoveryFromDizziness | 使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分30|使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分30| +| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害,得分50 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内破盾,得分50 | +| RecoveryFromDizziness | 使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分30|使用瞬间从眩晕状态中恢复 | 成功从眩晕状态中恢复,得分30| ## 得分 @@ -161,7 +161,7 @@ V3.9 ### 学生 - 学生每完成n%的作业,得2n分 -- 学生与捣蛋鬼处于小于5000的距离认为在牵制状态,得(牵制时长(ms)*0.00369)分 +- 学生与捣蛋鬼处于小于5000的距离认为在牵制状态,得(牵制时长(ms)*0.00246)分 - 使捣蛋鬼进入眩晕状态时,得20*眩晕时长(/s)分。 - 成功唤醒一名同学,得100分 - 成功勉励一名同学,得50*勉励程度/基本勉励程度(1500000)分 @@ -217,29 +217,29 @@ V3.9 - 普通攻击为 CommonAttackOfGhost - 主动技能 - ShowTime - - CD: 90s 持续时间:10s + - CD: 75s 持续时间:10s - 持续时间内每一帧向所有学生发送向自己移动的指令。 ### 学生(&老师) | 学生职业 | 教师Teacher | 健身狂Athlete | 学霸StraightAStudent | 开心果Sunshine | | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | -| 移动速度 | 1,125 | 1,650 | 1,200 | 1,500 | -| 最大毅力值 | 30000000 | 3000000 | 3300000 | 3200000 | +| 移动速度 | 1,125 | 1,350 | 1,200 | 1200 | +| 最大毅力值 | 30000000 | 3000000 | 3300000 | 3200000 | | 最大沉迷度 | 600000 | 54,000 | 78,000 | 66,000 | -| 学习一科速度() | 0 | 73 | 135 | 123 | -| 勉励速度 | 70 | 80 | 80 | 200 | -| 隐蔽度 | 0.5 | 0.9 | 0.9 | 1 | +| 学习一科速度 | 0 | 73 | 135 | 123 | +| 勉励速度 | 70 | 80 | 80 | 90 | +| 隐蔽度 | 0.5 | 0.9 | 0.9 | 0.8 | | 警戒范围 | 7500 | 15000 | 13,500 | 15000 | | 视野范围 | 9,000 | 11000 | 9,000 | 10000 | -| 开锁门速度 | 4000 | 4000 | 4000 | 4000 | +| 开锁门速度 | 4000 | 4000 | 4000 | 2500 | | 翻窗速度 | 635 | 1,524 | 1,058 | 1270 | -| 翻箱速度 | 1000 | 1000 | 1000 | 1000 | +| 翻箱速度 | 1000 | 1000 | 1000 | 800 | #### 运动员 - 主动技能 - 冲撞 CanBeginToCharge - - CD:24s 持续时间:5s + - CD:60s 持续时间:3s - 在持续时间内,速度变为三倍,期间撞到捣蛋鬼,会导致捣蛋鬼眩晕7.22s,学生眩晕2.09s - 通过眩晕获得对应得分 @@ -247,7 +247,7 @@ V3.9 - 主动技能 - 惩罚 Punish - CD:30s - - 使用瞬间,在可视范围内的使用技能状态中、攻击前后摇的捣蛋鬼会被眩晕(3070)ms, + - 使用瞬间,在可视范围内的翻窗、开锁门、攻击前后摇的捣蛋鬼会被眩晕(3070+300*已受伤害/基本伤害(1500000))ms, - 通过眩晕获得对应得分 - 特性 - 教师无法获得牵制得分 @@ -255,7 +255,7 @@ V3.9 #### 学霸 - 特性 - 冥想 - - 当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为0.3%/ms + - 当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为40/ms - 受到攻击(并非伤害)或学习或进入不可接受治疗状态(包括翻窗)学习进度清零 - 主动技能5 - 写答案 WriteAnswers @@ -266,15 +266,15 @@ V3.9 #### 开心果 - 主动技能 - 唤醒 Rouse - - CD:60s + - CD:120s - 使用瞬间,唤醒可视范围内一个沉迷中的人 - 通过唤醒获得对应得分 - 勉励 Encourage - - CD:60s - - 使用瞬间,勉励完成可视范围内一个毅力不足的人 + - CD:120s + - 使用瞬间,为可视范围内一个毅力不足的人补充750000的毅力值 - 通过勉励获得对应得分 - 鼓舞 Inspire - - CD:60s + - CD:120s - 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff - 每鼓舞一个学生得分10 diff --git a/logic/cmd/gameServer.cmd b/logic/cmd/gameServer.cmd index 6c4c56b..994cff9 100644 --- a/logic/cmd/gameServer.cmd +++ b/logic/cmd/gameServer.cmd @@ -1,6 +1,6 @@ @echo off -start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 60 --fileName test +start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 600 --fileName test ping -n 2 127.0.0.1 > NUL @@ -14,4 +14,4 @@ start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --ch start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 3 --type 1 --occupation 3 -start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 2030 \ No newline at end of file +::start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 2030 \ No newline at end of file From 0eda07998e3000f46a05aeed587bea8d44667e17 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Wed, 12 Apr 2023 20:15:57 +0800 Subject: [PATCH 31/37] feat(CAPI): :sparkles: add tool tutorial --- CAPI/Tool_tutorial.md | 931 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 931 insertions(+) create mode 100644 CAPI/Tool_tutorial.md diff --git a/CAPI/Tool_tutorial.md b/CAPI/Tool_tutorial.md new file mode 100644 index 0000000..0cd3ec2 --- /dev/null +++ b/CAPI/Tool_tutorial.md @@ -0,0 +1,931 @@ +# 工具使用合集 + +[toc] + +## Visual Studio使用说明 + +待更新... + +## cmd脚本的参数修改 + +待更新... + +## C++接口必看 + +**在此鸣谢\xfgg/\xfgg/\xfgg/,看到这里的选手可以到选手群膜一膜!!! ** + +除非特殊指明,以下代码均在 MSVC 19.28.29913 /std:c++17 与 g++ 10.2 for linux -std=c++17 两个平台下通过。 + + + +由于我们的比赛最终会运行在Linux平台上,因此程设课上学到的一些只适用于Windows的C++操作很可能并不能正确执行。此外,代码中使用了大量Modern C++中的新特性,可能会使选手在编程过程中遇到较大困难。因此,此处介绍一些比赛中使用C++接口必须了解的知识。 + + + +### 计时相关 + + + +编写代码过程中,我们可能需要获取系统时间等一系列操作,C++ 标准库提供了这样的行为。尤其注意**不要**使用 Windows 平台上的 `GetTickCount` 或者 `GetTickCount64` !!! 应当使用 `std::chrono` + +头文件:`#include ` + +可以用于获取时间戳,从而用于计时、例如计算某个操作花费的时间,或者协调队友间的合作。 + +```c++ +#include +#include +int main() +{ + auto sec = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + auto msec = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + std::cout << "从 1970 年元旦到现在的:秒数" << sec << ";毫秒数:" << msec << std::endl; + return 0; +} +``` + + + +### 线程睡眠 + + + +由于移动过程中会阻塞人物角色,因此玩家可能要在移动后让线程休眠一段时间,直到移动结束。C++ 标准库中使线程休眠需要包含头文件:`#include `。示例用法: + +```cpp +std::this_thread::sleep_for(std::chrono::milliseconds(20)); // 休眠 20 毫秒 +std::this_thread::sleep_for(std::chrono::seconds(2)); // 休眠 2 秒 + +// 下面这个也能休眠 200 毫秒 +std::this_thread::sleep_until(std::chrono::system_clock::now() += std::chrono::milliseconds(200)); +``` + +休眠过程中,线程将被阻塞,而不继续进行,直到休眠时间结束方继续向下执行。 + + + +### 异步接口的使用 + + + +本届比赛中,我们可能会看到类似 `std::future` 这样类型的接口返回值,这实际上是一个异步接口。在调用同步接口后,在接口内的函数未执行完之前,线程通常会阻塞住;但是异步接口的调用通常不会阻塞当前线程,而是会另外开启一个线程进行操作,当前线程则继续向下执行。当调用 `get()` 方法时,将返回异步接口的值,若此时异步接口内的函数依然未执行完,则会阻塞当前线程。 + +如果不需要返回值或没有返回值,但是希望接口内的函数执行完之后再进行下一步,即将接口当做常规的同步接口来调用,也可以调用 `wait()` 方法。 + + + +```c++ +#include +#include +#include +#include + +int f_sync() +{ + std::this_thread::sleep_for(std::chrono::seconds(1)); + return 8; +} + +std::future f_async() +{ + return std::async(std::launch::async, []() + { std::this_thread::sleep_for(std::chrono::seconds(1)); + return 8; }); +} + +int main() +{ + auto start = std::chrono::system_clock::now(); + std::cout << std::chrono::duration_cast>(std::chrono::system_clock::now() - start).count() << std::endl; + auto x = f_async(); + std::cout << std::chrono::duration_cast>(std::chrono::system_clock::now() - start).count() << std::endl; + std::cout << x.get() << std::endl; + std::cout << std::chrono::duration_cast>(std::chrono::system_clock::now() - start).count() << std::endl; + auto y = f_sync(); + std::cout << std::chrono::duration_cast>(std::chrono::system_clock::now() - start).count() << std::endl; + std::cout << y << std::endl; + std::cout << std::chrono::duration_cast>(std::chrono::system_clock::now() - start).count() << std::endl; +} +``` + + + +### `auto`类型推导 + + + +C++11开始支持使用 `auto` 自动推导变量类型,废除了原有的作为 storage-class-specifier 的作用: + +```c++ +int i = 4; +auto x = i; // auto 被推导为 int,x 是 int 类型 +auto& y = i; // auto 仍被推导为 int,y 是 int& 类型 +auto&& z = i; // auto 被推导为 int&,z 是 int&&&,被折叠为 int&,即 z 与 y 同类型 +auto&& w = 4; // auto 被推导为 int,w 是 int&& 类型 +``` + + + +### STL相关 + + + +#### std::vector + +头文件:`#include `,类似于可变长的数组,支持下标运算符 `[]` 访问其元素,此时与 C 风格数组用法相似。支持 `size` 成员函数获取其中的元素数量。 + +创建一个 `int` 型的 `vector` 对象: + +```cpp +std::vector v { 9, 1, 2, 3, 4 }; // 初始化 vector 有五个元素,v[0] = 9, ... +v.emplace_back(10); // 向 v 尾部添加一个元素,该元素饿构造函数的参数为 10(对于 int,只有一个语法意义上的构造函数,无真正的构造函数),即现在 v 有六个元素,v[5] 的值是10 +v.pop_back(); // 把最后一个元素删除,现在 v 还是 { 9, 1, 2, 3, 4 } +``` + + + +遍历其中所有元素的方式: + +```cpp +// std::vector v; +for (int i = 0; i < (int)v.size(); ++i) +{ + /*可以通过 v[i] 对其进行访问*/ +} + +for (auto itr = v.begin(); itr != v.end(); ++itr) +{ + /* + * itr 作为迭代器,可以通过其访问 vector 中的元素。其用法与指针几乎完全相同。 + * 可以通过 *itr 得到元素;以及 itr-> 的用法也是支持的 + * 实际上它内部就是封装了指向 vector 中元素的指针 + * 此外还有 v.cbegin()、v.rbegin()、v.crbegin() 等 + * v.begin()、v.end() 也可写为 begin(v)、end(v) + */ +} + +for (auto&& elem : v) +{ + /* + * elem 即是 v 中每个元素的引用,也可写成 auto& elem : v + * 它完全等价于: + * { + * auto&& __range = v; + * auto&& __begin = begin(v); + * auto&& __end = end(v); + * for (; __begin != __end; ++__begin) + * { + * auto&& elem = *__begin; + * // Some code + * } + * } + */ +} +``` + +例如: + +```cpp +for (auto elem&& : v) { std::cout << elem << ' '; } +std::cout << std::endl; +``` + + + +作为 STL 的容器之一,其具有容器的通用接口。但是由于这比较复杂,在此难以一一展开。有兴趣的同学可以在下方提供的链接里进行查阅。 + +**注:请千万不要试图使用 `std::vector`,若需使用,请用 `std::vector` 代替!** + +更多用法参见(点击进入):[cppreference_vector](https://zh.cppreference.com/w/cpp/container/vector) + + + +#### std::array + +头文件:`#include `,C 风格数组的类封装版本。 + +用法与 C 风格的数组是基本相似的,例如: + +```cpp +std::array arr { 9.0, 8.0, 7.0, 6.0, 5.0 }; +std::cout << arr[2] << std::endl; // 输出 7.0 +``` + +同时也支持各种容器操作: + +```cpp +double sum = 0.0; +for (auto itr = begin(arr); itr != end(arr); ++itr) +{ + sum += *itr; +} +// sum 结果是 35 +``` + + + +更多用法参见(点击进入):[cppreference_array](https://zh.cppreference.com/w/cpp/container/array)。 + + + +## Python接口必看 + + + +比赛中的Python接口大多使用异步接口,即返回一个类似于 `Future[bool]` 的值。为了获取实际的值,需要调用 `result()` 方法。 + +```python +from concurrent.futures import Future, ThreadPoolExecutor +import time + + +class Cls: + def __init__(self): + self.__pool: ThreadPoolExecutor = ThreadPoolExecutor(10) + + def Test(self, a: int, b: int) -> Future[int]: + def test(): + time.sleep(0.5) + return a + b + + return self.__pool.submit(test) + + +if __name__ == '__main__': + f1 = Cls().Test(1, 2) + print(time.time()) + print(f1.result()) + print(time.time()) + +``` + + + +## C++相关小知识 + + + +### lambda表达式 + + + +#### lambda表达式概述 + + + +lambda 表达式是 C++ 发展史上的一个重大事件,也是 C++ 支持函数式编程的重要一环。可以说,lambda 表达式不仅给 C++ 程序员带来了极大的便利,也开创了 C++ 的一个崭新的编程范式。但是同时 lambda 表达式也带来了诸多的语法难题,使用容易,但精通极难。 + +lambda 表达式确实是一个非常有用的语法特性。至少个人在学了 lambda 表达式之后,编写 C++ 代码就再也没有离开过。因为,它真的是非常的方便与易用。 + +lambda 表达式首先可以看做是一个临时使用的函数。它的一般格式如下: + +```c++ +[捕获列表] + lambda 声明(可选) + 复合语句 + +lambda 声明指的是: +(参数列表) + 一堆修饰符(可选) +``` + +下面是一个简单的例子: + +```c++ +#include +using namespace std; +int main(void) +{ + auto GetOne = []{ return 1; }; // GetOne 是一个 lambda 表达式 + cout << GetOne() << endl; // 使用起来就像一个函数,输出 1 + return 0; +} +``` + +它还可以有参数: + +```c++ +#include +using namespace std; +int main(void) +{ + auto GetSum = [](int x, int y){ return x + y; }; + cout << GetSum(2, 3) << endl; // 5 + return 0; +} +``` + +或者临时调用: + +```c++ +#include +using namespace std; +int main(void) +{ + cout << [](int x, int y){ return x + y; }(2, 3) << endl; // 5 + return 0; +} +``` + + + +#### lambda 表达式的捕获 + +##### 捕获的概念 + +lambda 表达式是不能够直接使用函数内的局部变量的(之后你将会看到这是为什么)。如果需要使用函数内的局部变量,需要手动进行捕获。捕获的方式有两种:按值捕获与按引用捕获。按值捕获,只会获得该值,而按引用捕获,则会获得函数内局部变量的引用。声明要捕获的变量就在 lambda 表达式的 `[]` 内: + ++ `[]`:不捕获任何局部变量 ++ `[x]`:按值捕获变量 `x` ++ `[&y]`:按引用捕获变量 `y` ++ `[=]`:按值捕获全部局部变量 ++ `[&]`:按引用捕获全部局部变量 ++ `[&, x]`:除了 `x` 按值捕获之外,其他变量均按引用捕获 ++ `[=, &y]`:什么意思不用我都说了吧 ++ `[r = x]`:声明一个变量 `r` ,捕获 `x` 的值 ++ `[&r = y]`:声明一个引用 `r`,捕获 `y` 的引用 ++ `[x, y, &z, w = p, &r = q]`:作为练习 ++ `[&, x, y, p = z]`:这个也作为练习 + +这样我们就可以写出下面的代码了: + +```cpp +#include +using namespace std; +int main(void) +{ + int x, y, z; + cin >> x >> y; + [x, y, &z](){ z = x + y; }(); + cout << z << endl; // z = x + y + return 0; +} +``` + + + +##### 捕获 `this` 与 `*this` + +当 lambda 表达式位于类的成员函数内时,该如何使用该类的成员变量呢?我们知道,在类的成员函数体内使用成员变量,都是通过 `this` 指针访问的,此处 `this` 作为成员函数的一个参数,因此只需要捕获 `this` 指针,就可以在 lambda 体内访问其成员变量了! + +捕获时,我们可以选择捕获 `[this]`,也可以捕获 `[*this]`。区别是,前者捕获的是 `this` 指针本身,而后者是按值捕获 `this` 指针所指向的对象,也就是以 `*this` 为参数复制构造了一个新的对象。看下面的代码: + +```c++ +#include +using namespace std; + +struct Foo +{ + int m_bar; + void Func() + { + [this]() + { + cout << ++m_bar << endl; + }(); + } +}; + +int main() +{ + Foo foo; + foo.m_bar = 999; + foo.Func(); // 输出 1000 +} +``` + + + +##### 附注 + +需要注意的是,lambda 表达式的捕获发生在 **lambda 表达式定义处**,而不是 lambda 表达式调用处,比如: + +```c++ +int a = 4; +auto f = [a]() { cout << a << endl; }; // 此时捕获 a,值是 4 +a = 9; +f(); // 输出 4,而非 9 +``` + + + +> **C++ 真奇妙:不需要捕获的情况** +> +> 看这特殊的引用块就知道,本段内容仅作介绍,感觉较难者请跳过本块。 +> +> 有时,即使是局部变量,不需要捕获也可以编译通过。这是 C++ 标准对编译器实现做出的妥协。这种现象叫做“常量折叠(constant folding)”;与之相对的是不能直接使用,必须进行捕获的情况,通常称作“odr-used”。这两个概念比较复杂,在此不做过多展开。看下面的例子: +> +> ```c++ +> int Func1(const int& x) { return x; } +> void Func2() +> { +> const int x = 4; +> []() +> { +> int y = x; // OK, constant folding +> int z = Func1(x); // Compile error! odr-used! x is not captured! +> }(); +> } +> ``` +> +> 但是个别较老的编译器即使是 odr-used 也可能会编译通过 + + + +#### lambda 表达式的修饰符 `mutable` + +lambda 表达式可以有一些修饰符,例如 `noexcept`、`mutable `等,这里仅介绍 `mutable`。 + +lambda 表达式按值捕获变量时,捕获的变量默认是不可修改: + +```c++ +int a = 4; +auto f = [a]() +{ + ++a; // Compile error: a cannot be modified! +}; +``` + +但是我们可以通过加 `mutable` 关键字让它达到这个目的: + +```c++ +int a = 4; +auto f = [a]() mutable +{ + ++a; // OK + cout << a << endl; +}; +f(); //输出 5 +cout << a << endl; //输出 4 +``` + +需要注意的是,按值捕获变量是生成了一个新的变量副本,而非原来的变量,所以在 lambda 外的 `a` 的值仍然是 `4` + + + +#### lambda 表达式的本质 + +本段内容仅是粗略地讲述,不做深入讨论。读者也可以跳过本块。 + +上面说了这么多语法规定,但是 lamdba 表达式究竟是什么?知道了这个可以帮助我们理解 lambda 表达式的这些规定。 + +C++17 标准中如此定义 lambda 的类型: + +> The type of a *lambda-expression* (which is also the type of the closure object ) is a unique, unnamed non-union class type, called the closure type.... + +lambda 表达式类型是一个独一无二的、没有名字的、并且不是联合体的类类型。我们把它叫做“**closure type**”。 + +后面还有一堆关于它性质的约束,这里就不展开了,大致上就是编译器可以自由决定它的很多性质,有兴趣的可以去翻阅《ISO/IEC 14882: 2017》第 8.1.5.1 款。 + +大体来看,一个 lamdba 表达式与一个类是大致上相同的。也就是说,lambda 表达式: + +```c++ +int a = 0, b = 0; +auto f = [a, &b](int x) { return a + b + x; } +f(5); +``` + +和下面的代码大致相同: + +```c++ +int a = 0, b = 0; +class __lambda__ +{ +private: + int a; + int& b; +public: + __lambda__(int& a, int& b) : a(a), b(b) {} + auto operator(int x) const { return a + b + x; } +}; +__lambda__ f(a, b); +f.operator()(5); +``` + +不过它们两个**并不完全相同**。首先,不同编译器的实现本身就有不同;另外,它们在语法上的规定也有一些差别。篇幅所限,在此不做过多展开。 + + + +#### lambda 表达式的应用 + +看了上面这么多介绍,你可能要问:这东西能用什么用处?为什么不直接写个函数,或者是干脆不用 lambda 表达式而直接写在函数体里呢?有这个疑问是正常的。因为我上面给的例子都是可以不用 lambda 表达式就能轻松解决的。但是,lambda 表达式在很多应用场景具有不可替代的优势。最简单的例子,比如在局部,你要重复某些操作,但是另写一个函数又不是很方便,就可以用 lambda 表达式完成。此外,它最大的作用就是在函数式编程中,或者是其他需要回调函数的情况,以 lambda 表达式作为函数的参数以作为回调函数。在下面的教程中,例如多线程、智能指针,我们将会多次用到 lambda 表达式。届时你将会看到使用 lambda 表达式是多么的方便。 + + + +#### 关于 lambda 表达式的其他说明 + +lambda 表达式还有很多有趣之处,例如泛型 lambda、返回 lambda 表达式的 lamdba 表达式,此外 `decltype` 在 lambda 表达式中的使用也是光怪陆离……总之,lambda 表达式非常有趣。 + +到了这里,相信你对 lambda 表达式已经有了相当的理解,就让我们来做一道简单的练习吧(狗头) + +> 请给出下面程序的输出(该程序选自《ISO/IEC 14882: 2017 Programming Language --- C++》第 107 页): +> +> ```c++ +>#include +> using namespace std; +> +> int main() +> { +> int a = 1, b = 1, c = 1; +> auto m1 = [a, &b, &c]() mutable +> { +> auto m2 = [a, b, &c]() mutable +> { +> cout << a << b << c; +> a = 4; b = 4; c = 4; +> }; +> a = 3; b = 3; c = 3; +> m2(); +> }; +> a = 2; b = 2; c = 2; +> m1(); +> cout << a << b << c << endl; +> return 0; +> } +> ``` +> 相信聪明的你一下就看出了答案。没错,答案就是我们小学二年级学习的数字:**123234**!怎么样,你答对了吗? +> + + + +如果阅读本文之后你觉得 lambda 表达式很有趣,欢迎阅读 《ISO/IEC 14882: 2017 Programming Language --- C++》110~120 页,或点击进入网址:[cppreference_lambda](https://zh.cppreference.com/w/cpp/language/lambda) 获取更多信息。 + + + + + +### std::thread + +头文件:`#include `。用于开启新的线程。示例代码: + +```c++ +#include +#include +#include + +void Func(int x, int& cnt) +{ + for (int i = 0; i < 110; ++i) + { + std::cout << "In Func: " << x << std::endl; + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } +} + +int main() +{ + int cnt = 0; + + // 由于这种情况下函数的调用与传参不是同时的,提供参数在函数调用之前,因此以引用方式传递参数时需要用 std::ref + std::thread thr(Func, 2021, std::ref(cnt)); + + for (int i = 0; i < 50; ++i) + { + std::cout << "In main: " << 110 << std::endl; + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + + thr.join(); // 等待子线程结束,在 thr 析构前若未 detach 则必须调用此函数,等待过程中主线程 main 被阻塞 + std::cout << "Count: " << cnt << std::endl; + return 0; +} +``` + + + +或者使用 lambda 表达式达到同样效果: + +```c++ +#include +#include +#include + +int main() +{ + int cnt = 0, x = 2021; + std::thread thr + ( + [x, &cnt]() + { + for (int i = 0; i < 110; ++i) + { + std::cout << "In Func: " << x << std::endl; + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + } + ); + + for (int i = 0; i < 50; ++i) + { + std::cout << "In main: " << 110 << std::endl; + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + + thr.join(); + std::cout << "Count: " << cnt << std::endl; + return 0; +} +``` + + + +如果不希望等待子线程结束,`main` 结束则程序结束,则可以构造临时对象调用 `detach` 函数: + +```c++ +#include +#include +#include + +int main() +{ + int cnt = 0, x = 2021; + std::thread + ( + [x, &cnt]() + { + for (int i = 0; i < 110; ++i) + { + std::cout << "In Func: " << x << std::endl; + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + } + ).detach(); + + for (int i = 0; i < 50; ++i) + { + std::cout << "In main: " << 110 << std::endl; + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + + std::cout << "Count: " << cnt << std::endl; + return 0; +} +``` + + + +更多内容请参看(点击进入):[cppreference_thread](https://en.cppreference.com/w/cpp/thread/thread) + + + +### 智能指针 + + + +#### 总述 + + + +头文件:`include ` + +智能指针是 C++ 标准库中对指针的封装,它的好处是可以不需要 `delete`,而自动对其指向的资源进行释放,这在一定程度上降低了 C++ 程序员管理内存的难度,但同时智能指针的使用也具有一定的技巧。 + +智能指针主要有三种:`shared_ptr`、`weak_ptr`、`unique_ptr`。 + + + +#### `std::shared_ptr` + +##### 概览 + +`shared_ptr` 可以说是最常用的智能指针了。它的用法最为灵活,内部实现方式是**引用计数**。即,它会记录有多少个 `shared_ptr` 正在指向某个资源,并当指向该资源的智能指针数为零时,调用相应的释放函数(默认为 `delete` 操作符)释放该资源。 + +像 `new` 会在自由存储区动态获取一块内存并返回其一样,如果要动态分配一块内存并得到其智能指针,可以使用 `std::make_shared` 模板,例如: + +```c++ +#include + +void Func() +{ + int* p = new int(110); // 在自由存储区 new 一个 int 对象,初值为 110 + auto sp = std::make_shared(110); // 在自由存储区 new 一个 int 对象,初值为 110 + // sp 被自动推导为 std::shared_ptr 类型 + delete p; // 释放内存 + + // 编译器调用 sp 的析构函数,并将其指向的 int 释放掉 +} +``` + +关于引用计数: + +```cpp +#include + +void Func() +{ + int x = 110; + { + auto sp1 = std::make_shared(x); // 得到一个 int,初值为 110。 + + // 上述此语句执行过后,只有一个智能指针 sp1 指向这个 int,引用计数为 1 + + { + auto sp2 = sp1; // 构造一个智能指针 sp2,指向 sp1 指向的内存,并将引用计数+1 + + // 故此处引用计数为2 + + std::cout << *sp2 << std::endl; // 输出 110 + + // 此处 sp2 生存期已到,调用 sp2 的析构函数,使引用计数-1,因此此时引用计数为1 + } + + // 此处 sp1 生命期也已经到了,调用 sp1 析构函数,引用计数再-1,故引用计数降为0 + // 也就是不再有智能指针指向它了,调用 delete 释放内存 + } +} +``` + +将普通指针交给智能指针托管: + +```cpp +int* p = new int(110); +int* q = new int(110); +std::shared_ptr sp(p); // 把 p 指向的内存交给 sp 托管,此后 p 便不需要 delete,sp 析构时会自动释放 +std::shared_ptr sq; // sq 什么也不托管 +sq.reset(q); // 让 sq 托管 q + +//此后 p 与 q 便不需要再 delete +``` + +需要注意的是,这种写法是非常危险的,既可能导致 `p` 与 `q` 变为野指针,也可能造成重复 `delete`,我们应该更多使用 make_shared。 + +##### 自定义释放函数 + +之前说过 ,默认情况下是释放内存的函数是 `delete` 运算符,但有时我们并不希望这样。比如下面的几个情况: + ++ 使用智能指针托管动态数组 + + ```cpp + #include + + void IntArrayDeleter(int* p) { delete[] p; } + + int main() + { + std::shared_ptr sp(new int[10], IntArrayDeleter); // 让 IntArrayDeleter 作为释放资源的函数 + // sp 析构时自动调用 IntArrayDeleter 释放该 int 数组 + return 0; + } + + // 或者利用 lambda 表达式:std::shared_ptr sp(new int[10], [](int* p) { delete[] p; }); + ``` + + + ++ 释放系统资源 + + 在编程过程中,难免与操作系统打交道,这时我们可能需要获取一系列的系统资源,并还给操作系统(实际上 `new` 和 `delete` 也就是一个例子)。一个比较有特色的例子就是 Windows API。在传统的 Win32 程序中,如果我们要在屏幕上进行绘制图形,我们首先需要获取设备的上下文信息,才能在设备上进行绘图。设想这样一个情景:我们有一个窗口,已经获得了指向这个窗口的句柄(即指针)`hWnd`,我们要在窗口上绘图,就要通过这个窗口句柄获取设备上下文信息。代码如下: + + ```c++ + HDC hdc; // DC: Device context,一个指向 DC 的句柄(HANDLE) + hdc = GetDC(hWnd); // 获取设备上下文 + /*执行绘图操作*/ + ReleaseDC(hWnd, hdc); // 绘图完毕,将设备上下文资源释放,归还给 Windows 系统 + ``` + + 使用智能指针对其进行托管,代码如下: + + ```c++ + // 使用 lambda 表达式写法(推荐) + std::shared_ptr sp(GetDC(hWnd), [hWnd](void* hdc) { ReleaseDC(hWnd, (HDC)hdc); }); + ``` + + ```cpp + // 不使用 lambda 表达式的写法: + struct Releaser + { + HWND hWnd; + Releaser(HWND hWnd) : hWnd(hWnd) {} + void operator()(void* hdc) + { + ReleaseDC(hWnd, (HDC)hdc); + } + }; + + void PaintFunc() + { + /*...*/ + std::shared_ptr sp(GetDC(hWnd), Releaser(hWnd)); + /*...*/ + } + ``` + +##### 常见的错误用法 + +`std::shared_ptr` 虽然方便,但是也有一些错误用法,这个是常见的: + +```c++ +#include + +void Func() +{ + int* p = new int(110); + std::shared_ptr sp(p); // 让 sp 托管 p + std::shared_ptr sq(p); // 让 sq 托管 p + + // Runtime Error! 程序至此崩溃 +} +``` + +这是因为,只有复制构造函数里面才有使引用计数加1的操作。即当我们写 `std::shared_ptr sq = sp` 的时候,确实引用计数变成了2,但是我们都用一个外部的裸指针 `p` 去初始化 `sp` 和 `sq`,智能指针并不能感知到它们托管的内存相同。所以 `sp` 和 `sq` 所托管的内存被看做是独立的。这样,当它们析构的时候,均会释放它们所指的内存,因此同一块内存被释放了两次,导致程序出错。所以个人还是推荐使用 `make_shared` ,而不是用裸指针去获取内存。 + +另一个著名的错误用法,请继续阅读 `std::weak_ptr`。 + + + +#### `std::weak_ptr` + +看完了上面的 `shared_ptr` 的讲述,相信你已经对使用智能指针胸有成竹了。一切都用 `shared_ptr`、`make_shared` 就万事大吉了嘛!但事情可能没那么简单。看下面的例子: + +```c++ +#include +#include + +class B; + +class A +{ +public: + void SetB(const std::shared_ptr& ipB) + { + pB = ipB; + } + +private: + std::shared_ptr pB; +}; + +class B +{ +public: + void SetA(const std::shared_ptr& ipA) + { + pA = ipA; + } + +private: + std::shared_ptr pA; +}; + +void Func() +{ + auto pA = std::make_shared(); + auto pB = std::make_shared(); + pA->SetB(pB); + pB->SetA(pA); + // 内存泄露!!! +} + +/*...*/ +``` + + + +太糟糕了!上面的 `pA` 指向的的对象和 `pB` 指向的对象一直到程序结束之前永远不会被释放!如果不相信,可以在它们的析构函数里输出些什么试一试。相信学习了引用计数的你,一定能想出来原因。我们就把它当作一道思考题作为练习:为什么这两个对象不会被释放呢?(提示:注意只有引用计数降为0的时候才会释放) + + + +实际上,`std::shared_ptr` 并不是乱用的。它除了作为一个指针之外,还表明了一种逻辑上的归属关系。从逻辑上看,类的成员代表一种归属权的关系,类的成员属于这个类。拥有 `shared_ptr` 作为**成员**的对象,是对 `shared_ptr` 所指向的对象具有所有权的,`shared_ptr` 也是基于这个理念设计的。但是,有时候我们并不希望这是个所有权的关系,例如我们有双亲和孩子的指针作为“人”的成员,但是人与人之间是平等相待和谐共处的,我们不能说一个人是另一个人的附属品。这时候,`std::weak_ptr` 便应运而生了! + +`std::weak_ptr` 与 `shared_ptr` 的区别是,它指向一个资源,并不会增加引用计数。当指向一个资源的 `shared_ptr` 的数量为 0 的时候,即使还有 `weak_ptr` 在指,资源也会被释放掉。也是因此,`weak_ptr`也是存在悬垂指针的可能的,即它指向的资源已经被释放掉。 也是因此,`weak_ptr` 不允许直接地被解引用,必须先转换为相应的 `shared_ptr` 才能解引用,获取其所指的资源。它的用法如下: + +```cpp +auto sp = std::make_shared(5); +std::weak_ptr wp = sp; // 正确,让 wp 指向 sp 指向的资源 +// std::shared_ptr sp1 = wp; // 错误,weak_ptr 不能直接赋值给 shared_ptr + +/* Do something */ + +if (wp.expired()) +{ + std::cout << "The resource has been released!" << std::endl; +} +else +{ + // std::cout << *wp << std::endl; // Compile error! weak_ptr 不能直接使用! + auto sp1 = wp.lock(); // 从 weak_ptr 中恢复出 shared_ptr,sp1 的类型为 std::shared_ptr + std::cout << *sp1 << std::endl; +} +``` + +从类的设计本身来看,`weak_ptr` 不会增加引用计数;从逻辑上看,`weak_ptr` 描述了一种联系,即 `weak_ptr` 的拥有者与其指向的对象之间不是一种归属关系,而是一种较弱的联系。一个类的对象只需知道另一个类的对象是谁,而不对其拥有占有权,这时候用 `weak_ptr` 是合适的。 + +上面的 `A` 类和 `B` 类的问题,将 `A` 和 `B` 成员从 `shared_ptr` 换成 `weak_ptr` 就会解决内存泄露的问题了! + + + +#### `std::unique_ptr` + +`std::unique_ptr` 顾名思义,独有的指针,即资源只能同时为一个 `unique_ptr` 所占有。它部分涉及到 `xvalue` 、右值引用与移动语义的问题,在此不做过多展开。 + + + +更多关于智能指针的知识,可以参考(点击进入): + ++ [cppreference_shared_ptr](https://zh.cppreference.com/w/cpp/memory/shared_ptr) ++ [cppreference_weak_ptr](https://zh.cppreference.com/w/cpp/memory/weak_ptr) + ++ [cppreference_unique_ptr](https://zh.cppreference.com/w/cpp/memory/unique_ptr) \ No newline at end of file From 2d9e8022a49117393c37a38acb28736432e0a1b8 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 22:28:17 +0800 Subject: [PATCH 32/37] fix: :bug: fix the Problem Of JumpyDumpty --- logic/GameRules.md | 32 ++++++++++++----------- logic/Gaming/ActionManager.cs | 2 +- logic/Gaming/AttackManager.cs | 16 ++++-------- logic/Gaming/CharacterManager .cs | 5 ++-- logic/Gaming/Game.cs | 2 +- logic/Preparation/Interface/ICharacter.cs | 2 ++ 6 files changed, 28 insertions(+), 31 deletions(-) diff --git a/logic/GameRules.md b/logic/GameRules.md index e0ef0e7..5d906d6 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V3.9 +V4.0 - [规则](#规则) - [简则](#简则) - [地图](#地图) @@ -42,17 +42,17 @@ V3.9 - [门](#门-1) - [窗](#窗-1) - [箱子](#箱子-1) - - [信息获取](#信息获取) + - [得分](#得分-1) ## 简则 ### 地图 -- 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。 +- 地图为矩形区域,游戏对象坐标为(x, y),x和y均为整数。 - **x坐标轴正方向竖直向下,y坐标轴正方向水平向右**; - **极坐标以x坐标轴为极轴,角度逆时针为正方向**。 - 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到: - $$CellX=\frac{x}{1000},CellY=\frac{y}{1000}$$ -- 地图上格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 +- 格子有对应区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子 ### 人物 - 人物半径为800 @@ -125,10 +125,11 @@ V3.9 - 开箱后将有2个随机道具掉落在玩家位置。 ### 信息相关 -1. 不详的感觉(dangerAlert):捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) -2. 期待搞事的感觉(trickDesire):学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) -3. 学习的声音(classVolume): 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 -4. 可以向其他每一个队友发送不超过256字节的信息 +- Bgm + 1. 不详的感觉(dangerAlert):捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) + 2. 期待搞事的感觉(trickDesire):学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) + 3. 学习的声音(classVolume): 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 +- 可以向其他每一个队友发送不超过256字节的信息 ### 可视范围 - 小于视野半径,且受限于墙和草地 @@ -155,14 +156,14 @@ V3.9 - 对学生造成伤害时,得伤害*100/基本伤害(1500000)分。 - 对作业造成破坏时,每破坏n%的作业,得n分 -- 使学生进入沉迷状态时,得50分。 -- 使学生进入眩晕状态时,得20*眩晕时长(/s)分。 +- 使学生沉迷时,得50分。 +- 使学生眩晕时,得20*眩晕时长(/s)分。 - 每淘汰一个学生,得1000分 ### 学生 - 学生每完成n%的作业,得2n分 -- 学生与捣蛋鬼处于小于5000的距离认为在牵制状态,得(牵制时长(ms)*0.00369)分 -- 使捣蛋鬼进入眩晕状态时,得20*眩晕时长(/s)分。 +- 学生与捣蛋鬼处于小于5000的距离认为正在牵制,得(牵制时长(ms)*0.00369)分 +- 使捣蛋鬼眩晕时,得20*眩晕时长(/s)分。 - 成功唤醒一名同学,得100分 - 成功勉励一名同学,得50*勉励程度/基本勉励程度(1500000)分 - 毕业,得1000分 @@ -250,7 +251,8 @@ V3.9 - 使用瞬间,在可视范围内的使用技能状态中、攻击前后摇的捣蛋鬼会被眩晕(3070)ms, - 通过眩晕获得对应得分 - 特性 - - 教师无法获得牵制得分 + - 无法获得牵制得分 + - 无法毕业 #### 学霸 - 特性 @@ -334,5 +336,5 @@ V3.9 - 箱子开启后其中道具才可以被观测和拿取 - 箱子道具不刷新 -### 信息获取 -- 查询对应物体状态时物体不存在则返回false +### 得分 +- 眩晕或毅力值归零时无牵制得分 \ No newline at end of file diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 54b29eb..2d07cea 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -122,7 +122,7 @@ namespace Gaming public bool Escape(Student player) { - if (!(player.Commandable()) || player.CharacterType == CharacterType.Robot) + if (!(player.Commandable()) || player.CharacterType == CharacterType.Robot || player.CharacterType == CharacterType.Teacher) return false; Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); if (doorwayForEscape != null && doorwayForEscape.IsOpen()) diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 40995b2..312f336 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -6,7 +6,6 @@ using Preparation.Utility; using GameEngine; using Preparation.Interface; using Timothy.FrameRateTask; -using System.Numerics; namespace Gaming { @@ -85,8 +84,6 @@ namespace Gaming return; } - Debugger.Output(bullet, bullet.TypeOfBullet.ToString()); - BombObj(bullet, objBeingShot); characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); return; @@ -105,6 +102,7 @@ namespace Gaming if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null) { bullet.Parent.BulletOfPlayer = BulletType.JumpyDumpty; + Debugger.Output(bullet.Parent, bullet.Parent.CharacterType.ToString() + " " + bullet.Parent.BulletNum.ToString()); Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI / 2.0); Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0); } @@ -146,15 +144,11 @@ namespace Gaming characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); } - public bool Attack(Character? player, double angle) + public bool Attack(Character player, double angle) { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange - if (player == null) - { - return false; - } - - if (player.BulletOfPlayer == BulletType.Null || !player.Commandable()) + if (player.BulletOfPlayer == BulletType.Null) return false; + Debugger.Output(player, player.CharacterType.ToString() + "Attack in " + player.BulletOfPlayer.ToString()); XY res = player.Position + new XY // 子弹紧贴人物生成。 ( @@ -166,7 +160,7 @@ namespace Gaming if (bullet != null) { - Debugger.Output(player, "Attack in" + bullet.ToString()); + Debugger.Output(player, "Attack in " + bullet.ToString()); bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0; bullet.CanMove = true; gameMap.Add(bullet); diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index 66df131..3b7a11e 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -141,8 +141,7 @@ namespace Gaming bgmVolume = newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position); } } - if (bgmVolume > 0) - newPlayer.AddBgm(BgmType.StudentIsApproaching, bgmVolume); + newPlayer.AddBgm(BgmType.StudentIsApproaching, bgmVolume); } else { @@ -152,7 +151,7 @@ namespace Gaming { if (!noise && XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment)) newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position)); - if (newPlayer.CharacterType != CharacterType.Teacher && XY.Distance(newPlayer.Position, person.Position) <= GameData.PinningDownRange) + if (newPlayer.CharacterType != CharacterType.Teacher && !newPlayer.NoHp() && newPlayer.PlayerState != PlayerStateType.Stunned && XY.Distance(newPlayer.Position, person.Position) <= GameData.PinningDownRange) { TimePinningDown += GameData.checkInterval; newPlayer.AddScore(GameData.StudentScorePinDown(TimePinningDown) - ScoreAdded); diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 914fd6d..4236430 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -220,7 +220,7 @@ namespace Gaming if (!gameMap.Timer.IsGaming) return false; Character? player = gameMap.FindPlayerToAction(playerID); - if (player != null) + if (player != null && player.Commandable()) { return attackManager.Attack(player, angle); } diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs index 5975b8c..ce2965c 100644 --- a/logic/Preparation/Interface/ICharacter.cs +++ b/logic/Preparation/Interface/ICharacter.cs @@ -12,6 +12,8 @@ namespace Preparation.Interface public double Vampire { get; } public PlayerStateType PlayerState { get; } public BulletType BulletOfPlayer { get; set; } + public CharacterType CharacterType { get; } + public int BulletNum { get; } public bool IsGhost(); } From 09ccd5147d431b0745cfafec46d09ddfc03084a8 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Wed, 12 Apr 2023 23:46:21 +0800 Subject: [PATCH 33/37] fix: :bug: fix the CopyInfo and improve the performance about the fuction of Attack --- logic/Client/MainWindow.xaml.cs | 2 +- logic/GameClass/GameObj/Map/Map.cs | 14 ++++++++ logic/GameRules.md | 2 +- logic/Gaming/AttackManager.cs | 58 +++++++++++++++--------------- logic/Gaming/CharacterManager .cs | 4 +-- logic/Server/CopyInfo.cs | 3 ++ 6 files changed, 49 insertions(+), 34 deletions(-) diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 603597a..b42743c 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -851,7 +851,7 @@ namespace Client { case Protobuf.BulletType.BombBomb: { - double bombRange = 1.0*data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; + double bombRange = 1.0 * data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; Ellipse icon = new() { Width = 2 * bombRange * unitWidth, diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index adbfc49..75645fc 100644 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -221,6 +221,20 @@ namespace GameClass.GameObj } return flag; } + public bool RemoveJustFromMap(GameObj gameObj) + { + GameObjLockDict[gameObj.Type].EnterWriteLock(); + bool flag; + try + { + flag = GameObjDict[gameObj.Type].Remove(gameObj); + } + finally + { + GameObjLockDict[gameObj.Type].ExitWriteLock(); + } + return flag; + } public void Add(GameObj gameObj) { GameObjLockDict[gameObj.Type].EnterWriteLock(); diff --git a/logic/GameRules.md b/logic/GameRules.md index f7903d1..377f1ab 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V4.0 +V4.1 - [规则](#规则) - [简则](#简则) - [地图](#地图) diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 312f336..44dbea5 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -6,6 +6,7 @@ using Preparation.Utility; using GameEngine; using Preparation.Interface; using Timothy.FrameRateTask; +using System.Numerics; namespace Gaming { @@ -73,22 +74,34 @@ namespace Gaming #endif bullet.CanMove = false; - if (gameMap.Remove(bullet) && bullet.BulletBombRange > 0) - gameMap.Add(new BombedBullet(bullet)); - if (bullet.BulletBombRange == 0) { + gameMap.Remove(bullet); if (objBeingShot == null) { - characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); + characterManager.BackSwing((Character)bullet.Parent, bullet.Backswing); return; } BombObj(bullet, objBeingShot); - characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); + characterManager.BackSwing((Character)bullet.Parent, bullet.RecoveryFromHit); return; } + if (gameMap.Remove(bullet)) + { + BombedBullet bombedBullet = new(bullet); + gameMap.Add(bombedBullet); + new Thread + (() => + { + Thread.Sleep(GameData.frameDuration); + gameMap.RemoveJustFromMap(bombedBullet); + } + ) + { IsBackground = true }.Start(); + } + /*if (objBeingShot != null) { else if (objBeingShot is Bullet) //子弹不能相互引爆,若要更改这一设定,取消注释即可。 @@ -138,10 +151,10 @@ namespace Gaming if (objBeingShot == null) { - characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); + characterManager.BackSwing((Character)bullet.Parent, bullet.Backswing); } else - characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); + characterManager.BackSwing((Character)bullet.Parent, bullet.RecoveryFromHit); } public bool Attack(Character player, double angle) @@ -169,35 +182,20 @@ namespace Gaming if (bullet.CastTime > 0) { characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); - - new Thread + if (bullet.IsRemoteAttack) + { + new Thread (() => { - new FrameRateTaskExecutor( - loopCondition: () => player.PlayerState == PlayerStateType.TryingToAttack && gameMap.Timer.IsGaming, - loopToDo: () => + Thread.Sleep(bullet.CastTime); + if (player.PlayerState == PlayerStateType.TryingToAttack) { - }, - timeInterval: GameData.frameDuration, - finallyReturn: () => 0, - maxTotalDuration: bullet.CastTime - ) - - .Start(); - - if (gameMap.Timer.IsGaming) - { - if (player.PlayerState == PlayerStateType.TryingToAttack) - { - characterManager.SetPlayerState(player); - } - else - bullet.IsMoving = false; - gameMap.Remove(bullet); + characterManager.SetPlayerState(player); } } ) - { IsBackground = true }.Start(); + { IsBackground = true }.Start(); + } } } if (bullet != null) diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index 3b7a11e..e5242a0 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -354,9 +354,9 @@ namespace Gaming else TryBeAwed(student, bullet); } - public bool BackSwing(Character? player, int time) + public bool BackSwing(Character player, int time) { - if (player == null || time <= 0) return false; + if (time <= 0) return false; if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false; SetPlayerState(player, PlayerStateType.Swinging); diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index ba57920..d255068 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -148,6 +148,7 @@ namespace Server { BulletMessage = new() { + Type = Transformation.ToBulletType(bullet.TypeOfBullet), X = bullet.Position.x, Y = bullet.Position.y, FacingDirection = bullet.FacingDirection.Angle(), @@ -184,6 +185,7 @@ namespace Server { BombedBulletMessage = new() { + Type = Transformation.ToBulletType(bombedBullet.bulletHasBombed.TypeOfBullet), X = bombedBullet.bulletHasBombed.Position.x, Y = bombedBullet.bulletHasBombed.Position.y, FacingDirection = bombedBullet.FacingDirection.Angle(), @@ -191,6 +193,7 @@ namespace Server BombRange = bombedBullet.bulletHasBombed.BulletBombRange } }; + // Debugger.Output(bombedBullet, bombedBullet.Place.ToString()+" "+bombedBullet.Position.ToString()); return msg; } From 942435837949e8c084a3627a87993a6e49a04679 Mon Sep 17 00:00:00 2001 From: Shawqeem <1004837646@qq.com> Date: Thu, 13 Apr 2023 01:03:46 +0800 Subject: [PATCH 34/37] refactor: :art: change the color of bombed bullets and improve the function CanSee change the color of bombed bullets and improve the function CanSee --- logic/Client/MainWindow.xaml.cs | 158 ++++++++++++++++++-------------- logic/Gaming/AttackManager.cs | 2 +- logic/cmd/gameServer.cmd | 2 +- 3 files changed, 89 insertions(+), 73 deletions(-) diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index b42743c..714fea1 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -564,23 +564,16 @@ namespace Client return true; if (humanOrButcher && human != null) { - if (human.Guid == msg.Guid) // 自己能看见自己 + if (msg.Place == human.Place) return true; } - if (msg.Place == Protobuf.PlaceType.Grass || msg.Place == Protobuf.PlaceType.Gate || msg.Place == Protobuf.PlaceType.HiddenGate) - return false; - if (msg.Place == Protobuf.PlaceType.Land || msg.Place == Protobuf.PlaceType.Classroom) - return true; - if (humanOrButcher && human != null) - { - if (msg.Place != human.Place) - return false; - } else if (!humanOrButcher && butcher != null) { - if (msg.Place != butcher.Place) - return false; + if (msg.Place == butcher.Place) + return true; } + if (msg.Place == Protobuf.PlaceType.Grass) + return false; return true; } @@ -593,20 +586,21 @@ namespace Client if (butcher.Guid == msg.Guid) // 自己能看见自己 return true; } - if (msg.Place == Protobuf.PlaceType.Grass || msg.Place == Protobuf.PlaceType.Gate || msg.Place == Protobuf.PlaceType.HiddenGate) - return false; - if (msg.Place == Protobuf.PlaceType.Land || msg.Place == Protobuf.PlaceType.Classroom) - return true; if (humanOrButcher && human != null) { - if (msg.Place != human.Place) - return false; - } - else if (!humanOrButcher && butcher != null) - { - if (msg.Place != butcher.Place) - return false; + if (msg.TrickerType == Protobuf.TrickerType.Assassin) + { + foreach (var buff in msg.Buff) + { + if (buff == Protobuf.TrickerBuffType.TrickerInvisible) + return false; + } + } + if (msg.Place == human.Place) + return true; } + if (msg.Place == Protobuf.PlaceType.Grass) + return false; return true; } @@ -614,18 +608,18 @@ namespace Client { if (isSpectatorMode) return true; - if (msg.Place == Protobuf.PlaceType.Land) - return true; if (humanOrButcher && human != null) { - if (msg.Place != human.Place) - return false; + if (msg.Place == human.Place) + return true; } else if (!humanOrButcher && butcher != null) { - if (msg.Place != butcher.Place) - return false; + if (msg.Place == butcher.Place) + return true; } + if (msg.Place == Protobuf.PlaceType.Grass) + return false; return true; } @@ -633,18 +627,37 @@ namespace Client { if (isSpectatorMode) return true; - if (msg.Place == Protobuf.PlaceType.Land) - return true; if (humanOrButcher && human != null) { - if (msg.Place != human.Place) - return false; + if (msg.Place == human.Place) + return true; } else if (!humanOrButcher && butcher != null) { - if (msg.Place != butcher.Place) - return false; + if (msg.Place == butcher.Place) + return true; } + if (msg.Place == Protobuf.PlaceType.Grass) + return false; + return true; + } + + private bool CanSee(MessageOfBombedBullet msg) + { + if (isSpectatorMode) + return true; + //if (humanOrButcher && human != null) + //{ + // if (msg.Place == human.Place) + // return true; + //} + //else if (!humanOrButcher && butcher != null) + //{ + // if (msg.Place == butcher.Place) + // return true; + //} + //if (msg.Place == Protobuf.PlaceType.Grass) + // return false; return true; } @@ -847,46 +860,49 @@ namespace Client } foreach (var data in listOfBombedBullet) { - switch (data.Type) + if (CanSee(data)) { - case Protobuf.BulletType.BombBomb: - { - double bombRange = 1.0 * data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; - Ellipse icon = new() + switch (data.Type) + { + case Protobuf.BulletType.BombBomb: { - Width = 2 * bombRange * unitWidth, - Height = 2 * bombRange * unitHeight, - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Top, - Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bombRange, data.X * unitHeight / 1000.0 - unitHeight * bombRange, 0, 0), - Fill = Brushes.DarkRed, - }; - UpperLayerOfMap.Children.Add(icon); - break; - } - case Protobuf.BulletType.JumpyDumpty: - { - double bombRange = 1.0 * data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; - Ellipse icon = new() + double bombRange = 1.0 * data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; + Ellipse icon = new() + { + Width = 2 * bombRange * unitWidth, + Height = 2 * bombRange * unitHeight, + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bombRange, data.X * unitHeight / 1000.0 - unitHeight * bombRange, 0, 0), + Fill = Brushes.DarkRed, + }; + UpperLayerOfMap.Children.Add(icon); + break; + } + case Protobuf.BulletType.JumpyDumpty: { - Width = 2 * bombRange * unitWidth, - Height = 2 * bombRange * unitHeight, - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Top, - Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bombRange, data.X * unitHeight / 1000.0 - unitHeight * bombRange, 0, 0), - Fill = Brushes.DarkViolet, - }; - UpperLayerOfMap.Children.Add(icon); + double bombRange = 1.0 * data.BombRange / Preparation.Utility.GameData.numOfPosGridPerCell; + Ellipse icon = new() + { + Width = 2 * bombRange * unitWidth, + Height = 2 * bombRange * unitHeight, + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(data.Y * unitWidth / 1000.0 - unitWidth * bombRange, data.X * unitHeight / 1000.0 - unitHeight * bombRange, 0, 0), + Fill = Brushes.DarkRed, + }; + UpperLayerOfMap.Children.Add(icon); + break; + } + //case Protobuf.BulletType.LineBullet: + // { + // double bombRange = data.BombRange / 1000; + // DrawLaser(new Point(data.Y * unitWidth / 1000.0, data.X * unitHeight / 1000.0), -data.FacingDirection + Math.PI / 2, bombRange * unitHeight, 0.5 * unitWidth); + // break; + // } + default: break; - } - //case Protobuf.BulletType.LineBullet: - // { - // double bombRange = data.BombRange / 1000; - // DrawLaser(new Point(data.Y * unitWidth / 1000.0, data.X * unitHeight / 1000.0), -data.FacingDirection + Math.PI / 2, bombRange * unitHeight, 0.5 * unitWidth); - // break; - // } - default: - break; + } } } foreach (var data in listOfClassroom) diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 44dbea5..98a0d37 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -95,7 +95,7 @@ namespace Gaming new Thread (() => { - Thread.Sleep(GameData.frameDuration); + Thread.Sleep(GameData.frameDuration * 5); gameMap.RemoveJustFromMap(bombedBullet); } ) diff --git a/logic/cmd/gameServer.cmd b/logic/cmd/gameServer.cmd index 994cff9..3d9e370 100644 --- a/logic/cmd/gameServer.cmd +++ b/logic/cmd/gameServer.cmd @@ -4,7 +4,7 @@ start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 -- ping -n 2 127.0.0.1 > NUL -start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 2 +start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 1 start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 0 --type 1 --occupation 1 From 3d513d1b8a8f44749193a5e5e2694f658cd09b80 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Thu, 13 Apr 2023 02:06:01 +0800 Subject: [PATCH 35/37] build: :construction: edit GameData --- CAPI/cpp/API/include/constants.h | 34 +++++++++---------- CAPI/python/PyAPI/constants.py | 32 ++++++++--------- logic/GameRules.md | 14 ++++---- logic/Gaming/AttackManager.cs | 2 +- .../SkillManager/SkillManager.ActiveSkill.cs | 10 +++--- logic/Preparation/Interface/IOccupation.cs | 20 +++++------ logic/Preparation/Interface/ISkill.cs | 10 +++--- logic/Preparation/Utility/GameData.cs | 5 ++- 8 files changed, 65 insertions(+), 62 deletions(-) diff --git a/CAPI/cpp/API/include/constants.h b/CAPI/cpp/API/include/constants.h index a741d73..55f3d00 100644 --- a/CAPI/cpp/API/include/constants.h +++ b/CAPI/cpp/API/include/constants.h @@ -115,11 +115,11 @@ namespace Constants struct Athlete { - SCCI int moveSpeed = basicStudentSpeed * 11 / 10; + SCCI int moveSpeed = basicStudentSpeed * 105 / 100; SCCI int maxHp = basicHp; SCCI int maxAddiction = basicMaxGamingAddiction * 9 / 10; SCCI int fixSpeed = basicFixSpeed * 6 / 10; - SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 9 / 10; SCCI double concealment = 0.9; SCCI int alertnessRadius = basicStudentAlertnessRadius; SCCI int viewRange = basicStudentViewRange * 11 / 10; @@ -130,11 +130,11 @@ namespace Constants struct Teacher { - SCCI int moveSpeed = basicStudentSpeed * 3 / 4; + SCCI int moveSpeed = basicStudentSpeed * 9 / 10; SCCI int maxHp = basicHp * 10; SCCI int maxAddiction = basicMaxGamingAddiction * 10; SCCI int fixSpeed = basicFixSpeed * 0; - SCCI int encourageSpeed = basicEncourageSpeed * 7 / 10; + SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; SCCI double concealment = 0.5; SCCI int alertnessRadius = basicStudentAlertnessRadius / 2; SCCI int viewRange = basicStudentViewRange * 9 / 10; @@ -145,11 +145,11 @@ namespace Constants struct StraightAStudent { - SCCI int moveSpeed = basicStudentSpeed * 8 / 10; + SCCI int moveSpeed = basicStudentSpeed * 96 / 100; SCCI int maxHp = basicHp * 11 / 10; SCCI int maxAddiction = basicMaxGamingAddiction * 13 / 10; SCCI int fixSpeed = basicFixSpeed * 11 / 10; - SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; + SCCI int encourageSpeed = basicEncourageSpeed; SCCI double concealment = 0.9; SCCI int alertnessRadius = basicStudentAlertnessRadius * 9 / 10; SCCI int viewRange = basicStudentViewRange * 9 / 10; @@ -164,7 +164,7 @@ namespace Constants SCCI int maxHp = basicHp * 0.4; SCCI int maxAddiction = basicMaxGamingAddiction * 0; SCCI int fixSpeed = basicFixSpeed; - SCCI int encourageSpeed = basicEncourageSpeed * 8 / 10; + SCCI int encourageSpeed = 0; SCCI double concealment = 1; SCCI int alertnessRadius = basicStudentAlertnessRadius * 1; SCCI int viewRange = basicStudentViewRange; @@ -194,13 +194,13 @@ namespace Constants SCCI int maxHp = basicHp * 32 / 30; SCCI int maxAddiction = basicMaxGamingAddiction * 11 / 10; SCCI int fixSpeed = basicFixSpeed; - SCCI int encourageSpeed = basicEncourageSpeed * 2; + SCCI int encourageSpeed = basicEncourageSpeed * 12 / 10; SCCI double concealment = 1; SCCI int alertnessRadius = basicStudentAlertnessRadius; SCCI int viewRange = basicStudentViewRange; - SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking; + SCCI int speedOfOpeningOrLocking = basicSpeedOfOpeningOrLocking * 7 / 10; SCCI int speedOfClimbingThroughWindows = basicStudentSpeedOfClimbingThroughWindows; - SCCI int speedOfOpenChest = basicSpeedOfOpenChest; + SCCI int speedOfOpenChest = basicSpeedOfOpenChest * 9 / 10; }; // 技能相关 @@ -222,14 +222,14 @@ namespace Constants SCCI int timeOfAddingSpeedWhenInspire = 6000; struct CanBeginToCharge { - SCCI int skillCD = commonSkillCD * 4 / 3; - SCCI int durationTime = commonSkillTime * 1; + SCCI int skillCD = commonSkillCD * 2; + SCCI int durationTime = commonSkillTime * 3 / 10; }; struct BecomeInvisible { - SCCI int skillCD = commonSkillCD * 2; - SCCI int durationTime = commonSkillTime * 6 / 10; + SCCI int skillCD = commonSkillCD * 4 / 3; + SCCI int durationTime = commonSkillTime; }; struct Punish @@ -240,19 +240,19 @@ namespace Constants struct Rouse { - SCCI int skillCD = commonSkillCD * 2; + SCCI int skillCD = commonSkillCD * 4; SCCI int durationTime = commonSkillTime * 0; }; struct Encourage { - SCCI int skillCD = commonSkillCD * 2; + SCCI int skillCD = commonSkillCD * 4; SCCI int durationTime = commonSkillTime * 0; }; struct Inspire { - SCCI int skillCD = commonSkillCD * 2; + SCCI int skillCD = commonSkillCD * 4; SCCI int durationTime = commonSkillTime * 0; }; diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py index fa944a2..e76b7d9 100644 --- a/CAPI/python/PyAPI/constants.py +++ b/CAPI/python/PyAPI/constants.py @@ -135,11 +135,11 @@ class Idol: class Athlete: - moveSpeed = (int)(1.1 * Constants.basicStudentSpeed) + moveSpeed = (int)(1.05 * Constants.basicStudentSpeed) maxHp = (int)(1.0 * Constants.basicHp) maxAddiction = (int)(0.9 * Constants.basicMaxGamingAddiction) LearnSpeed = (int)(0.6 * Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.8 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.9 * Constants.basicEncourageSpeed) concealment = 0.9 * Constants.basicConcealment alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) viewRange = (int)(1.1 * Constants.basicStudentViewRange) @@ -151,11 +151,11 @@ class Athlete: class Teacher: - moveSpeed = (int)(0.75 * Constants.basicStudentSpeed) + moveSpeed = (int)(0.9 * Constants.basicStudentSpeed) maxHp = (int)(10.0 * Constants.basicHp) maxAddiction = (int)(10.0 * Constants.basicMaxGamingAddiction) LearnSpeed = (int)(0.0 * Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.7 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.8 * Constants.basicEncourageSpeed) concealment = 0.5 * Constants.basicConcealment alertnessRadius = (int)(0.5 * Constants.basicStudentAlertnessRadius) viewRange = (int)(0.9 * Constants.basicStudentViewRange) @@ -167,11 +167,11 @@ class Teacher: class StraightAStudent: - moveSpeed = (int)(0.8 * Constants.basicStudentSpeed) + moveSpeed = (int)(0.96 * Constants.basicStudentSpeed) maxHp = (int)(1.1 * Constants.basicHp) maxAddiction = (int)(1.3 * Constants.basicMaxGamingAddiction) LearnSpeed = (int)(1.1 * Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.8 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(Constants.basicEncourageSpeed) concealment = 0.9 * Constants.basicConcealment alertnessRadius = (int)(0.9 * Constants.basicStudentAlertnessRadius) viewRange = (int)(0.9 * Constants.basicStudentViewRange) @@ -187,7 +187,7 @@ class Robot: maxHp = (int)(0.4 * Constants.basicHp) maxAddiction = (int)(0.0 * Constants.basicMaxGamingAddiction) LearnSpeed = (int)(1.0 * Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.8 * Constants.basicLearnSpeed) + EncourageSpeed = 0 concealment = 1.0 * Constants.basicConcealment alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) viewRange = (int)(1.0 * Constants.basicStudentViewRange) @@ -203,7 +203,7 @@ class TechOtaku: maxHp = (int)(0.9 * Constants.basicHp) maxAddiction = (int)(1.1 * Constants.basicMaxGamingAddiction) LearnSpeed = (int)(1.1 * Constants.basicLearnSpeed) - EncourageSpeed = (int)(0.9 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(0.9 * Constants.basicEncourageSpeed) concealment = 1.0 * Constants.basicConcealment alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) viewRange = (int)(0.9 * Constants.basicStudentViewRange) @@ -219,20 +219,20 @@ class Sunshine: maxHp = (int)(1.0667 * Constants.basicHp) maxAddiction = (int)(1.1 * Constants.basicMaxGamingAddiction) LearnSpeed = (int)(1.0 * Constants.basicLearnSpeed) - EncourageSpeed = (int)(2.0 * Constants.basicLearnSpeed) + EncourageSpeed = (int)(1.2 * Constants.basicEncourageSpeed) concealment = 1.0 * Constants.basicConcealment alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) viewRange = (int)(1.0 * Constants.basicStudentViewRange) speedOfOpeningOrLocking = (int)( - 1.0 * Constants.basicSpeedOfOpeningOrLocking) + 0.7 * Constants.basicSpeedOfOpeningOrLocking) speedOfClimbingThroughWindows = (int)( 1.0 * Constants.basicStudentSpeedOfClimbingThroughWindows) - speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) + speedOfOpenChest = (int)(0.9 * Constants.basicSpeedOfOpenChest) class CanBeginToCharge: - skillCD = (int)(0.8 * Constants.commonSkillCD) - durationTime = (int)(0.5 * Constants.commonSkillTime) + skillCD = (int)(2 * Constants.commonSkillCD) + durationTime = (int)(0.3 * Constants.commonSkillTime) class BecomeInvisible: @@ -246,17 +246,17 @@ class Punish: class Rouse: - skillCD = (int)(2.0 * Constants.commonSkillCD) + skillCD = (int)(4.0 * Constants.commonSkillCD) durationTime = (int)(0.0 * Constants.commonSkillTime) class Encourage: - skillCD = (int)(2.0 * Constants.commonSkillCD) + skillCD = (int)(4.0 * Constants.commonSkillCD) durationTime = (int)(0.0 * Constants.commonSkillTime) class Inspire: - skillCD = (int)(2.0 * Constants.commonSkillCD) + skillCD = (int)(4.0 * Constants.commonSkillCD) durationTime = (int)(0.0 * Constants.commonSkillTime) diff --git a/logic/GameRules.md b/logic/GameRules.md index 377f1ab..9244692 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V4.1 +V4.2 - [规则](#规则) - [简则](#简则) - [地图](#地图) @@ -225,17 +225,17 @@ V4.1 | 学生职业 | 教师Teacher | 健身狂Athlete | 学霸StraightAStudent | 开心果Sunshine | | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | -| 移动速度 | 1,125 | 1,350 | 1,200 | 1200 | +| 移动速度 | 1350 | 1575 | 1440 | 1500 | | 最大毅力值 | 30000000 | 3000000 | 3300000 | 3200000 | | 最大沉迷度 | 600000 | 54,000 | 78,000 | 66,000 | | 学习一科速度 | 0 | 73 | 135 | 123 | -| 勉励速度 | 70 | 80 | 80 | 90 | +| 勉励速度 | 80 | 90 | 100 | 120 | | 隐蔽度 | 0.5 | 0.9 | 0.9 | 0.8 | | 警戒范围 | 7500 | 15000 | 13,500 | 15000 | | 视野范围 | 9,000 | 11000 | 9,000 | 10000 | -| 开锁门速度 | 4000 | 4000 | 4000 | 2500 | +| 开锁门速度 | 4000 | 4000 | 4000 | 2800 | | 翻窗速度 | 635 | 1,524 | 1,058 | 1270 | -| 翻箱速度 | 1000 | 1000 | 1000 | 800 | +| 翻箱速度 | 1000 | 1000 | 1000 | 900 | #### 运动员 - 主动技能 @@ -273,8 +273,8 @@ V4.1 - 通过唤醒获得对应得分 - 勉励 Encourage - CD:120s - - 使用瞬间,为可视范围内一个毅力不足的人补充750000的毅力值 - - 通过勉励获得对应得分 + - 使用瞬间,为可视范围内随机一个毅力不足的人试图补充750000的毅力值 + - 获得勉励750000的毅力值对应得分 - 鼓舞 Inspire - CD:120s - 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 44dbea5..98a0d37 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -95,7 +95,7 @@ namespace Gaming new Thread (() => { - Thread.Sleep(GameData.frameDuration); + Thread.Sleep(GameData.frameDuration * 5); gameMap.RemoveJustFromMap(bombedBullet); } ) diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index c045a26..55d4740 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -193,11 +193,11 @@ namespace Gaming { if (character.IsGhost() && (character.PlayerState == PlayerStateType.TryingToAttack || character.PlayerState == PlayerStateType.Swinging - || character.PlayerState == PlayerStateType.UsingSkill) + || character.PlayerState == PlayerStateType.UsingSkill || character.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || character.PlayerState == PlayerStateType.ClimbingThroughWindows) && gameMap.CanSee(player, character)) { - if (characterManager.BeStunned(character, GameData.TimeOfGhostStunnedWhenPunish)) - player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostStunnedWhenPunish)); + if (characterManager.BeStunned(character, GameData.TimeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP))) + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP))); break; } } @@ -254,8 +254,8 @@ namespace Gaming { if ((character.HP < character.MaxHp) && gameMap.CanSee(player, character)) { - player.AddScore(GameData.StudentScoreTreat(character.MaxHp - character.HP)); - character.HP = character.MaxHp; + player.AddScore(GameData.StudentScoreTreat(GameData.AddHpWhenEncourage)); + character.HP += GameData.AddHpWhenEncourage; ((Student)character).SetDegreeOfTreatment0(); break; } diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs index 9c8366c..390ad46 100644 --- a/logic/Preparation/Interface/IOccupation.cs +++ b/logic/Preparation/Interface/IOccupation.cs @@ -155,7 +155,7 @@ namespace Preparation.Interface } public class Teacher : IStudentType { - private const int moveSpeed = GameData.basicStudentMoveSpeed * 3 / 4; + private const int moveSpeed = GameData.basicStudentMoveSpeed * 9 / 10; public int MoveSpeed => moveSpeed; private const int maxHp = GameData.basicHp * 10; @@ -172,7 +172,7 @@ namespace Preparation.Interface public const int fixSpeed = 0; public int FixSpeed => fixSpeed; - public const int treatSpeed = (int)(GameData.basicTreatSpeed * 0.7); + public const int treatSpeed = (int)(GameData.basicTreatSpeed * 0.8); public int TreatSpeed => treatSpeed; public const double concealment = GameData.basicConcealment * 0.5; @@ -195,7 +195,7 @@ namespace Preparation.Interface } public class Athlete : IStudentType { - private const int moveSpeed = GameData.basicStudentMoveSpeed * 11 / 10; + private const int moveSpeed = GameData.basicStudentMoveSpeed * 105 / 100; public int MoveSpeed => moveSpeed; private const int maxHp = GameData.basicHp; @@ -212,7 +212,7 @@ namespace Preparation.Interface public const int fixSpeed = GameData.basicFixSpeed * 6 / 10; public int FixSpeed => fixSpeed; - public const int treatSpeed = GameData.basicTreatSpeed * 8 / 10; + public const int treatSpeed = GameData.basicTreatSpeed * 9 / 10; public int TreatSpeed => treatSpeed; public const double concealment = GameData.basicConcealment * 0.9; @@ -235,7 +235,7 @@ namespace Preparation.Interface } public class StraightAStudent : IStudentType { - private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 0.8); + private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 0.96); public int MoveSpeed => moveSpeed; private const int maxHp = (int)(GameData.basicHp * 1.1); @@ -252,7 +252,7 @@ namespace Preparation.Interface public const int fixSpeed = GameData.basicFixSpeed * 11 / 10; public int FixSpeed => fixSpeed; - public const int treatSpeed = GameData.basicTreatSpeed * 8 / 10; + public const int treatSpeed = GameData.basicTreatSpeed; public int TreatSpeed => treatSpeed; public const double concealment = GameData.basicConcealment * 0.9; @@ -292,7 +292,7 @@ namespace Preparation.Interface public const int fixSpeed = GameData.basicFixSpeed; public int FixSpeed => fixSpeed; - public const int treatSpeed = GameData.basicTreatSpeed * 8 / 10; + public const int treatSpeed = 0; public int TreatSpeed => treatSpeed; public const double concealment = GameData.basicConcealment; @@ -372,7 +372,7 @@ namespace Preparation.Interface public const int fixSpeed = GameData.basicFixSpeed; public int FixSpeed => fixSpeed; - public const int treatSpeed = GameData.basicTreatSpeed * 2; + public const int treatSpeed = GameData.basicTreatSpeed * 12 / 10; public int TreatSpeed => treatSpeed; public const double concealment = GameData.basicConcealment; @@ -384,13 +384,13 @@ namespace Preparation.Interface public int viewRange = GameData.basicStudentViewRange; public int ViewRange => viewRange; - public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; + public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking * 7 / 10; public int SpeedOfOpeningOrLocking => speedOfOpeningOrLocking; public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows; public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; - public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; + public int speedOfOpenChest = GameData.basicSpeedOfOpenChest * 9 / 10; public int SpeedOfOpenChest => speedOfOpenChest; } diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index 89fad41..01ad1b3 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -18,8 +18,8 @@ namespace Preparation.Interface } public class CanBeginToCharge : IActiveSkill { - public int SkillCD => GameData.commonSkillCD * 24 / 30; - public int DurationTime => GameData.commonSkillTime * 5 / 10; + public int SkillCD => GameData.commonSkillCD * 2; + public int DurationTime => GameData.commonSkillTime * 3 / 10; private readonly object commonSkillLock = new object(); public object ActiveSkillLock => commonSkillLock; @@ -63,7 +63,7 @@ namespace Preparation.Interface public class Rouse : IActiveSkill { - public int SkillCD => GameData.commonSkillCD * 2; + public int SkillCD => GameData.commonSkillCD * 4; public int DurationTime => 0; private readonly object commonSkillLock = new object(); @@ -78,7 +78,7 @@ namespace Preparation.Interface public class Encourage : IActiveSkill { - public int SkillCD => GameData.commonSkillCD * 2; + public int SkillCD => GameData.commonSkillCD * 4; public int DurationTime => 0; private readonly object commonSkillLock = new object(); @@ -93,7 +93,7 @@ namespace Preparation.Interface public class Inspire : IActiveSkill { - public int SkillCD => GameData.commonSkillCD * 2; + public int SkillCD => GameData.commonSkillCD * 4; public int DurationTime => 0; private readonly object commonSkillLock = new object(); diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index e860440..be19eb2 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -160,7 +160,7 @@ namespace Preparation.Utility //public const int StudentScoreFixed = 25; public static int StudentScorePinDown(int timeOfPinningDown) { - return (int)(timeOfPinningDown * 0.00369); + return (int)(timeOfPinningDown * 0.00246); } public static int StudentScoreTrickerBeStunned(int time) { @@ -214,6 +214,7 @@ namespace Preparation.Utility public const int TimeOfStudentStunnedWhenCharge = 2090; public const int TimeOfGhostStunnedWhenPunish = 3070; + public const int factorOfTimeStunnedWhenPunish = 300 / basicApOfGhost; public const int TimeOfGhostSwingingAfterHowl = 800; public const int TimeOfStudentStunnedWhenHowl = 5500; @@ -223,6 +224,8 @@ namespace Preparation.Utility public const double AddedTimeOfSpeedWhenInspire = 0.6; public const int TimeOfAddingSpeedWhenInspire = 6000; + public const int AddHpWhenEncourage = basicHp / 4; + #endregion #region 道具相关 public const int PropRadius = numOfPosGridPerCell / 2; From 77861d9ae11f0d01e2f4ff3dfafadb2eac0d2a46 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Fri, 14 Apr 2023 00:25:19 +0800 Subject: [PATCH 36/37] fix: :bug: fix a bug about the Update of Bgm --- logic/GameRules.md | 16 ++++++++++------ logic/Gaming/CharacterManager .cs | 11 +++++++---- logic/Server/Properties/launchSettings.json | 2 +- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/logic/GameRules.md b/logic/GameRules.md index 9244692..f49482b 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V4.2 +V4.3 - [规则](#规则) - [简则](#简则) - [地图](#地图) @@ -43,6 +43,7 @@ V4.2 - [窗](#窗-1) - [箱子](#箱子-1) - [得分](#得分-1) + - [信息相关](#信息相关-1) ## 简则 @@ -125,10 +126,10 @@ V4.2 - 开箱后将有2个随机道具掉落在玩家位置。 ### 信息相关 -- Bgm - 1. 不详的感觉(dangerAlert):捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)时,学生收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) - 2. 期待搞事的感觉(trickDesire):学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)时,捣蛋鬼收到;捣蛋鬼距离学生越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的学生距离) - 3. 学习的声音(classVolume): 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离 +- Bgm (在structures.h/.py中的student类或Tricker类中作为其属性) + 1. 不详的感觉(dangerAlert):如果捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)的距离,则学生的dangerAlert=(int)(警戒半径/二者距离) + 2. 期待搞事的感觉(trickDesire):如果有学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)的距离,则捣蛋鬼trickDesire=(警戒半径/可被发觉的最近的学生距离) + 3. 学习的声音(classVolume): 警戒半径内有人学习时,捣蛋鬼classVolume=(警戒半径x学习进度百分比)/二者距离 - 可以向其他每一个队友发送不超过256字节的信息 ### 可视范围 @@ -337,4 +338,7 @@ V4.2 - 箱子道具不刷新 ### 得分 -- 眩晕或毅力值归零时无牵制得分 \ No newline at end of file +- 眩晕或毅力值归零时无牵制得分 + +### 信息相关 +- Bgm在没有符合条件的情况下,值为0。 \ No newline at end of file diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index e5242a0..399666f 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -149,8 +149,12 @@ namespace Gaming { if (person.IsGhost()) { - if (!noise && XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment)) - newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position)); + if (!noise) + { + if (XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment)) + newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position)); + else newPlayer.AddBgm(BgmType.GhostIsComing, 0); + } if (newPlayer.CharacterType != CharacterType.Teacher && !newPlayer.NoHp() && newPlayer.PlayerState != PlayerStateType.Stunned && XY.Distance(newPlayer.Position, person.Position) <= GameData.PinningDownRange) { TimePinningDown += GameData.checkInterval; @@ -182,8 +186,7 @@ namespace Gaming bgmVolume = (double)newPlayer.AlertnessRadius * generator.DegreeOfRepair / GameData.degreeOfFixedGenerator / XY.Distance(newPlayer.Position, generator.Position); } } - if (bgmVolume > 0) - newPlayer.AddBgm(BgmType.GeneratorIsBeingFixed, bgmVolume); + newPlayer.AddBgm(BgmType.GeneratorIsBeingFixed, bgmVolume); } finally { diff --git a/logic/Server/Properties/launchSettings.json b/logic/Server/Properties/launchSettings.json index f15a2d1..5a08357 100644 --- a/logic/Server/Properties/launchSettings.json +++ b/logic/Server/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Server": { "commandName": "Project", - "commandLineArgs": "--ip 0.0.0.0 -p 8888 --studentCount 1 --trickerCount 0" + "commandLineArgs": "--ip 0.0.0.0 -p 8888 --characterID 2030" } } } \ No newline at end of file From 155da9463e6cd09220359e068e915c72abd4376f Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Fri, 14 Apr 2023 18:30:09 +0800 Subject: [PATCH 37/37] fix: :ambulance: fix the bug about interrupting the attack --- logic/GameRules.md | 48 ++++++++++++------------ logic/Gaming/AttackManager.cs | 69 ++++++++++++++++++++++------------- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/logic/GameRules.md b/logic/GameRules.md index f49482b..5c032cd 100644 --- a/logic/GameRules.md +++ b/logic/GameRules.md @@ -1,5 +1,5 @@ # 规则 -V4.3 +V4.4 - [规则](#规则) - [简则](#简则) - [地图](#地图) @@ -78,11 +78,10 @@ V4.3 8. 翻窗 ### 攻击 -- 无论近战远程均产生bullet表示攻击 - 攻击类型CommonAttackOfGhost攻击未写完的作业,会造成对应攻击力的损坏 - 捣蛋鬼攻击交互状态或前后摇的学生,将使学生眩晕4.3s -| 攻击类型 |搞蛋鬼的一般攻击CommonAttackOfGhost| 飞刀FlyingKnife | 蹦蹦炸弹BombBomb | 小炸弹JumpyDumpty | +| 攻击(子弹)类型 |搞蛋鬼的一般攻击CommonAttackOfGhost| 飞刀FlyingKnife | 蹦蹦炸弹BombBomb | 小炸弹JumpyDumpty | | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | | 子弹爆炸范围 | 0 | 0 | 1000 | 500 | | 子弹攻击距离 | 1100 | 39000 | 1100 | 2200 | @@ -103,13 +102,14 @@ V4.3 - 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。 - 开启校门所需时间为18秒,开启的进度不清空 - 当**3间**教室的作业完成时,隐藏校门在3-5个刷新点之一随机显现;当只剩1名学生时,隐藏校门自动打开。 +- 从开启的校门或隐藏校门离开是学生终极目标 #### 勉励 -- 当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。 +- 当被勉励程度达到当前损失的毅力值或1500000时,勉励完成,学生毅力增加对应被勉励程度。 - 勉励中断时,被勉励程度保留;遭到攻击时被勉励程度清空 #### 沉迷与唤醒 -- 当学生学习毅力归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 +- 学习毅力归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度 - 唤醒需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。 - 进入沉迷状态时,如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局; - 当学生沉迷程度达到其最大沉迷程度时,从游戏中出局 @@ -128,8 +128,8 @@ V4.3 ### 信息相关 - Bgm (在structures.h/.py中的student类或Tricker类中作为其属性) 1. 不详的感觉(dangerAlert):如果捣蛋鬼进入(学生的警戒半径/捣蛋鬼的隐蔽度)的距离,则学生的dangerAlert=(int)(警戒半径/二者距离) - 2. 期待搞事的感觉(trickDesire):如果有学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)的距离,则捣蛋鬼trickDesire=(警戒半径/可被发觉的最近的学生距离) - 3. 学习的声音(classVolume): 警戒半径内有人学习时,捣蛋鬼classVolume=(警戒半径x学习进度百分比)/二者距离 + 2. 期待搞事的感觉(trickDesire):如果有学生进入(捣蛋鬼的警戒半径/学生的隐蔽度)的距离,则捣蛋鬼trickDesire=(int)(警戒半径/可被发觉的最近的学生距离) + 3. 学习的声音(classVolume): 警戒半径内有人学习时,捣蛋鬼classVolume=(int)((警戒半径x学习进度百分比)/二者距离) - 可以向其他每一个队友发送不超过256字节的信息 ### 可视范围 @@ -137,8 +137,9 @@ V4.3 - 对于在从草地中的物体,物体与玩家连线上均为草地方可见 ### 道具 -- 玩家最多同时拥有三个道具 -- 可以捡起与自己处于同一个格子(cell)的道具,或将道具扔在原地 +- 玩家同时最多拥有三个道具 +- 可以捡起与自己处于同一个格子(cell)的道具 +- 可将道具扔在玩家位置 | 道具 | 对学生增益 | 学生得分条件 | 对搞蛋鬼增益 | 搞蛋鬼得分条件 | | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| @@ -284,61 +285,62 @@ V4.3 ## 细则 ### 特殊说明 -- 不加说明,这里“学生”往往包括职业“教师” + - 不加说明,这里“学生”往往包括职业“教师” ### 移动 - 不鼓励选手面向地图编程,因为移动过程中你可以受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。 ### 人物 -- 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 - EndAllAction()及Move指令调用数总和一帧内不超过10次 ### 初始状态 -- 玩家出生点固定且一定为空地 + - 玩家出生点固定且一定为空地 ### 道具 -- 使用钥匙相当于销毁 + - 使用钥匙相当于销毁 ### 交互 - 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 - 实际上唤醒或勉励不同的人是有效的 + - 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 ### 学习与毕业 -- 隐藏校门与校门对于人有碰撞体积 - 一个校门同时最多可以由一人开启 + - 隐藏校门与校门对于人有碰撞体积 ### 攻击 -- 每次学生受到攻击后会损失对应子弹的攻击力的学习毅力 +- 无论近战远程均产生bullet表示攻击 - 前摇期间攻击被打断时,子弹消失。 -- 此处,前摇指 从播放攻击动作开始 攻击者不能交互 的时间 + - 每次学生受到攻击后会损失对应子弹的攻击力的学习毅力 + - 此处,前摇指 从播放攻击动作开始 攻击者不能交互 的时间 ### 沉迷与唤醒 -- 在被救时沉迷度不增加 - 不能两人同时唤醒一个人 + - 在被救时沉迷度不增加 ### 门 - 每个教学区都有2把钥匙 - 一扇门只允许同时一个人开锁门 -- 开锁门未完成前,门状态表现为原来的状态 + - 开锁门未完成前,门状态表现为原来的状态 - 开锁门进度中断后清空 ### 窗 -- 攻击可以穿过窗,道具可以在窗上 - 翻越窗户是一种交互行为,翻窗一共有两个过程 - 跳上窗:从当前位置到窗边缘中点,位置瞬移,时间=距离/爬窗速度。中断时,停留在原位置 - 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度。中断时,停留在另一侧格子中心 -- 通常情况下捣蛋鬼翻越窗户的速度高于学生。 +- 攻击可以穿过窗,道具可以在窗上 - 有人正在翻越窗户时,其他玩家均不可以翻越该窗户。 + - 通常情况下捣蛋鬼翻越窗户的速度高于学生。 ### 箱子 - 地图上有8个箱子 -- 同一时刻只允许一人进行开启 + - 同一时刻只允许一人进行开启 - 未开启完成的箱子在下一次需要重新开始开启。 -- 箱子开启后其中道具才可以被观测和拿取 + - 箱子开启后其中道具才可以被观测和拿取 - 箱子道具不刷新 ### 得分 -- 眩晕或毅力值归零时无牵制得分 + - 眩晕或毅力值归零时无牵制得分 ### 信息相关 - Bgm在没有符合条件的情况下,值为0。 \ No newline at end of file diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 98a0d37..f17ef0d 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -64,6 +64,29 @@ namespace Gaming } } + public bool TryRemoveBullet(Bullet bullet) + { + bullet.CanMove = false; + if (gameMap.Remove(bullet)) + { + if (bullet.BulletBombRange > 0) + { + BombedBullet bombedBullet = new(bullet); + gameMap.Add(bombedBullet); + new Thread + (() => + { + Thread.Sleep(GameData.frameDuration * 5); + gameMap.RemoveJustFromMap(bombedBullet); + } + ) + { IsBackground = true }.Start(); + } + return true; + } + else return false; + } + private void BulletBomb(Bullet bullet, GameObj? objBeingShot) { #if DEBUG @@ -72,11 +95,10 @@ namespace Gaming else Debugger.Output(bullet, "bombed without objBeingShot"); #endif - bullet.CanMove = false; + if (!TryRemoveBullet(bullet)) return; if (bullet.BulletBombRange == 0) { - gameMap.Remove(bullet); if (objBeingShot == null) { characterManager.BackSwing((Character)bullet.Parent, bullet.Backswing); @@ -88,20 +110,6 @@ namespace Gaming return; } - if (gameMap.Remove(bullet)) - { - BombedBullet bombedBullet = new(bullet); - gameMap.Add(bombedBullet); - new Thread - (() => - { - Thread.Sleep(GameData.frameDuration * 5); - gameMap.RemoveJustFromMap(bombedBullet); - } - ) - { IsBackground = true }.Start(); - } - /*if (objBeingShot != null) { else if (objBeingShot is Bullet) //子弹不能相互引爆,若要更改这一设定,取消注释即可。 @@ -178,24 +186,35 @@ namespace Gaming bullet.CanMove = true; gameMap.Add(bullet); moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms - if (bullet.CastTime > 0) { characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); - if (bullet.IsRemoteAttack) - { - new Thread + + new Thread (() => { - Thread.Sleep(bullet.CastTime); - if (player.PlayerState == PlayerStateType.TryingToAttack) + new FrameRateTaskExecutor( + loopCondition: () => player.PlayerState == PlayerStateType.TryingToAttack && gameMap.Timer.IsGaming, + loopToDo: () => + { + }, + timeInterval: GameData.checkInterval, + finallyReturn: () => 0, + maxTotalDuration: bullet.CastTime + ) + .Start(); + + if (gameMap.Timer.IsGaming) { - characterManager.SetPlayerState(player); + if (player.PlayerState == PlayerStateType.TryingToAttack) + { + characterManager.SetPlayerState(player); + } + else TryRemoveBullet(bullet); } } ) - { IsBackground = true }.Start(); - } + { IsBackground = true }.Start(); } } if (bullet != null)