Browse Source

feat: achieve all rpc services

tags/0.1.0
gsy1519 2 years ago
parent
commit
690c0100c1
22 changed files with 715 additions and 165 deletions
  1. +8
    -1
      CAPI/cpp/API/include/structures.h
  2. +8
    -2
      CAPI/cpp/API/include/utils.hpp
  3. +2
    -0
      CAPI/cpp/API/src/AI.cpp
  4. +1
    -0
      CAPI/cpp/API/src/DebugAPI.cpp
  5. +7
    -1
      CAPI/cpp/API/src/logic.cpp
  6. +31
    -26
      CAPI/cpp/proto/MessageType.pb.cc
  7. +8
    -5
      CAPI/cpp/proto/MessageType.pb.h
  8. +6
    -0
      dependency/proto/Message2Server.proto
  9. +2
    -2
      dependency/proto/py_output.sh
  10. +39
    -16
      installer/Installer/MainWindow.xaml
  11. +194
    -40
      installer/Installer/Model.cs
  12. +333
    -32
      installer/Installer/ViewModel.cs
  13. +13
    -0
      logic/GameClass/GameObj/Character/Character.cs
  14. +11
    -0
      logic/GameClass/GameObj/Character/Skill.cs
  15. +1
    -0
      logic/Gaming/ActionManager.cs
  16. +6
    -6
      logic/Gaming/Game.cs
  17. +10
    -6
      logic/Gaming/PropManager.cs
  18. +2
    -2
      logic/Preparation/Interface/IOccupation.cs
  19. +3
    -2
      logic/Preparation/Utility/EnumType.cs
  20. +1
    -4
      logic/Preparation/Utility/GameData.cs
  21. +2
    -2
      logic/Server/CopyInfo.cs
  22. +27
    -18
      logic/规则Logic.md

+ 8
- 1
CAPI/cpp/API/include/structures.h View File

@@ -51,7 +51,10 @@ namespace THUAI6
Key3 = 1,
Key5 = 2,
Key6 = 3,
PropType4 = 4,
AddSpeed = 4,
AddLifeOrAp = 5,
AddHpOrAp = 6,
ShieldOrSpear = 7,
};

enum class BulletType : unsigned char
@@ -323,6 +326,10 @@ namespace THUAI6
{PropType::Key3, "Key3"},
{PropType::Key5, "Key5"},
{PropType::Key6, "Key6"},
{PropType::AddSpeed, "AddSpeed"},
{PropType::AddLifeOrAp, "AddLifeOrAp"},
{PropType::AddHpOrAp, "AddHpOrAp"},
{PropType::ShieldOrSpear, "ShieldOrSpear"},

};



+ 8
- 2
CAPI/cpp/API/include/utils.hpp View File

@@ -87,7 +87,10 @@ namespace Proto2THUAI6
{protobuf::PropType::KEY3, THUAI6::PropType::Key3},
{protobuf::PropType::KEY5, THUAI6::PropType::Key5},
{protobuf::PropType::KEY6, THUAI6::PropType::Key6},
{protobuf::PropType::PTYPE4, THUAI6::PropType::PropType4},
{protobuf::PropType::ADD_SPEED, THUAI6::PropType::AddSpeed},
{protobuf::PropType::ADD_HP_OR_AP, THUAI6::PropType::AddHpOrAp},
{protobuf::PropType::ADD_LIFE_OR_AP, THUAI6::PropType::AddLifeOrAp},
{protobuf::PropType::SHIELD_OR_SPEAR, THUAI6::PropType::ShieldOrSpear},
};

inline std::map<protobuf::PlayerType, THUAI6::PlayerType> playerTypeDict{
@@ -338,7 +341,10 @@ namespace THUAI62Proto
{THUAI6::PropType::Key3, protobuf::PropType::KEY3},
{THUAI6::PropType::Key5, protobuf::PropType::KEY5},
{THUAI6::PropType::Key6, protobuf::PropType::KEY6},
{THUAI6::PropType::PropType4, protobuf::PropType::PTYPE4},
{THUAI6::PropType::AddHpOrAp, protobuf::PropType::ADD_HP_OR_AP},
{THUAI6::PropType::AddLifeOrAp, protobuf::PropType::ADD_LIFE_OR_AP},
{THUAI6::PropType::AddSpeed, protobuf::PropType::ADD_SPEED},
{THUAI6::PropType::ShieldOrSpear, protobuf::PropType::SHIELD_OR_SPEAR},
};

inline std::map<THUAI6::PlayerType, protobuf::PlayerType> playerTypeDict{


+ 2
- 0
CAPI/cpp/API/src/AI.cpp View File

@@ -18,8 +18,10 @@ extern const THUAI6::StudentType studentType = THUAI6::StudentType::Athlete;
void AI::play(IStudentAPI& api)
{
api.Move(100, 1);
api.PrintSelfInfo();
}

void AI::play(ITrickerAPI& api)
{
api.Move(100, 1);
}

+ 1
- 0
CAPI/cpp/API/src/DebugAPI.cpp View File

@@ -26,6 +26,7 @@ StudentDebugAPI::StudentDebugAPI(ILogic& logic, bool file, bool print, bool warn
if (warnOnly)
printLogger->set_level(spdlog::level::warn);
logger = std::make_unique<spdlog::logger>("apiLogger", spdlog::sinks_init_list{fileLogger, printLogger});
logger->flush_on(spdlog::level::warn);
}

TrickerDebugAPI::TrickerDebugAPI(ILogic& logic, bool file, bool print, bool warnOnly, int64_t playerID) :


+ 7
- 1
CAPI/cpp/API/src/logic.cpp View File

@@ -324,7 +324,13 @@ void Logic::ProcessMessage()
}
bufferState->gameMap = std::move(map);
currentState->gameMap = bufferState->gameMap;
logger->info("Map loaded!");
}
if (currentState->gameMap.empty())
{
logger->error("Map not loaded!");
throw std::runtime_error("Map not loaded!");
}
LoadBuffer(clientMsg);

AILoop = true;
@@ -734,7 +740,6 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool f
if (file)
{
fileLogger->set_level(spdlog::level::trace);
spdlog::flush_every(std::chrono::seconds(1));
}
else
fileLogger->set_level(spdlog::level::off);
@@ -745,6 +750,7 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool f
if (warnOnly)
printLogger->set_level(spdlog::level::warn);
logger = std::make_unique<spdlog::logger>("logicLogger", spdlog::sinks_init_list{fileLogger, printLogger});
logger->flush_on(spdlog::level::warn);

// 打印当前的调试信息
logger->info("*********Basic Info*********");


+ 31
- 26
CAPI/cpp/proto/MessageType.pb.cc View File

@@ -39,36 +39,38 @@ const char descriptor_table_protodef_MessageType_2eproto[] PROTOBUF_SECTION_VARI
"SSROOM\020\004\022\010\n\004GATE\020\005\022\017\n\013HIDDEN_GATE\020\006\022\n\n\006W"
"INDOW\020\007\022\t\n\005DOOR3\020\010\022\t\n\005DOOR5\020\t\022\t\n\005DOOR6\020\n"
"\022\t\n\005CHEST\020\013*8\n\tShapeType\022\023\n\017NULL_SHAPE_T"
"YPE\020\000\022\n\n\006CIRCLE\020\001\022\n\n\006SQUARE\020\002*H\n\010PropTyp"
"e\022\022\n\016NULL_PROP_TYPE\020\000\022\010\n\004KEY3\020\001\022\010\n\004KEY5\020"
"\002\022\010\n\004KEY6\020\003\022\n\n\006PTYPE4\020\004*f\n\017StudentBuffTy"
"pe\022\023\n\017NULL_SBUFF_TYPE\020\000\022\016\n\nSBUFFTYPE1\020\001\022"
"\016\n\nSBUFFTYPE2\020\002\022\016\n\nSBUFFTYPE3\020\003\022\016\n\nSBUFF"
"TYPE4\020\004*\251\002\n\013PlayerState\022\017\n\013NULL_STATUS\020\000"
"\022\010\n\004IDLE\020\001\022\014\n\010LEARNING\020\002\022\014\n\010ADDICTED\020\003\022\010"
"\n\004QUIT\020\004\022\r\n\tGRADUATED\020\005\022\013\n\007TREATED\020\006\022\013\n\007"
"RESCUED\020\007\022\013\n\007STUNNED\020\010\022\014\n\010TREATING\020\t\022\014\n\010"
"RESCUING\020\n\022\014\n\010SWINGING\020\013\022\r\n\tATTACKING\020\014\022"
"\013\n\007LOCKING\020\r\022\r\n\tRUMMAGING\020\016\022\014\n\010CLIMBING\020"
"\017\022\023\n\017OPENING_A_CHEST\020\020\022\027\n\023USING_SPECIAL_"
"SKILL\020\021\022\022\n\016OPENING_A_GATE\020\022*f\n\017TrickerBu"
"ffType\022\023\n\017NULL_TBUFF_TYPE\020\000\022\016\n\nTBUFFTYPE"
"1\020\001\022\016\n\nTBUFFTYPE2\020\002\022\016\n\nTBUFFTYPE3\020\003\022\016\n\nT"
"BUFFTYPE4\020\004*J\n\nPlayerType\022\024\n\020NULL_PLAYER"
"_TYPE\020\000\022\022\n\016STUDENT_PLAYER\020\001\022\022\n\016TRICKER_P"
"LAYER\020\002*g\n\013StudentType\022\025\n\021NULL_STUDENT_T"
"YPE\020\000\022\013\n\007ATHLETE\020\001\022\020\n\014STUDENTTYPE2\020\002\022\020\n\014"
"STUDENTTYPE3\020\003\022\020\n\014STUDENTTYPE4\020\004*h\n\013Tric"
"kerType\022\025\n\021NULL_TRICKER_TYPE\020\000\022\014\n\010ASSASS"
"IN\020\001\022\020\n\014TRICKERTYPE2\020\002\022\020\n\014TRICKERTYPE3\020\003"
"\022\020\n\014TRICKERTYPE4\020\004*P\n\tGameState\022\023\n\017NULL_"
"GAME_STATE\020\000\022\016\n\nGAME_START\020\001\022\020\n\014GAME_RUN"
"NING\020\002\022\014\n\010GAME_END\020\003b\006proto3";
"YPE\020\000\022\n\n\006CIRCLE\020\001\022\n\n\006SQUARE\020\002*\206\001\n\010PropTy"
"pe\022\022\n\016NULL_PROP_TYPE\020\000\022\r\n\tADD_SPEED\020\001\022\022\n"
"\016ADD_LIFE_OR_AP\020\002\022\020\n\014ADD_HP_OR_AP\020\003\022\023\n\017S"
"HIELD_OR_SPEAR\020\004\022\010\n\004KEY3\020\005\022\010\n\004KEY5\020\006\022\010\n\004"
"KEY6\020\007*f\n\017StudentBuffType\022\023\n\017NULL_SBUFF_"
"TYPE\020\000\022\016\n\nSBUFFTYPE1\020\001\022\016\n\nSBUFFTYPE2\020\002\022\016"
"\n\nSBUFFTYPE3\020\003\022\016\n\nSBUFFTYPE4\020\004*\251\002\n\013Playe"
"rState\022\017\n\013NULL_STATUS\020\000\022\010\n\004IDLE\020\001\022\014\n\010LEA"
"RNING\020\002\022\014\n\010ADDICTED\020\003\022\010\n\004QUIT\020\004\022\r\n\tGRADU"
"ATED\020\005\022\013\n\007TREATED\020\006\022\013\n\007RESCUED\020\007\022\013\n\007STUN"
"NED\020\010\022\014\n\010TREATING\020\t\022\014\n\010RESCUING\020\n\022\014\n\010SWI"
"NGING\020\013\022\r\n\tATTACKING\020\014\022\013\n\007LOCKING\020\r\022\r\n\tR"
"UMMAGING\020\016\022\014\n\010CLIMBING\020\017\022\023\n\017OPENING_A_CH"
"EST\020\020\022\027\n\023USING_SPECIAL_SKILL\020\021\022\022\n\016OPENIN"
"G_A_GATE\020\022*f\n\017TrickerBuffType\022\023\n\017NULL_TB"
"UFF_TYPE\020\000\022\016\n\nTBUFFTYPE1\020\001\022\016\n\nTBUFFTYPE2"
"\020\002\022\016\n\nTBUFFTYPE3\020\003\022\016\n\nTBUFFTYPE4\020\004*J\n\nPl"
"ayerType\022\024\n\020NULL_PLAYER_TYPE\020\000\022\022\n\016STUDEN"
"T_PLAYER\020\001\022\022\n\016TRICKER_PLAYER\020\002*g\n\013Studen"
"tType\022\025\n\021NULL_STUDENT_TYPE\020\000\022\013\n\007ATHLETE\020"
"\001\022\020\n\014STUDENTTYPE2\020\002\022\020\n\014STUDENTTYPE3\020\003\022\020\n"
"\014STUDENTTYPE4\020\004*h\n\013TrickerType\022\025\n\021NULL_T"
"RICKER_TYPE\020\000\022\014\n\010ASSASSIN\020\001\022\020\n\014TRICKERTY"
"PE2\020\002\022\020\n\014TRICKERTYPE3\020\003\022\020\n\014TRICKERTYPE4\020"
"\004*P\n\tGameState\022\023\n\017NULL_GAME_STATE\020\000\022\016\n\nG"
"AME_START\020\001\022\020\n\014GAME_RUNNING\020\002\022\014\n\010GAME_EN"
"D\020\003b\006proto3";
static ::_pbi::once_flag descriptor_table_MessageType_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_MessageType_2eproto = {
false,
false,
1348,
1411,
descriptor_table_protodef_MessageType_2eproto,
"MessageType.proto",
&descriptor_table_MessageType_2eproto_once,
@@ -171,6 +173,9 @@ namespace protobuf
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
return true;
default:
return false;


+ 8
- 5
CAPI/cpp/proto/MessageType.pb.h View File

@@ -155,16 +155,19 @@ namespace protobuf
enum PropType : int
{
NULL_PROP_TYPE = 0,
KEY3 = 1,
KEY5 = 2,
KEY6 = 3,
PTYPE4 = 4,
ADD_SPEED = 1,
ADD_LIFE_OR_AP = 2,
ADD_HP_OR_AP = 3,
SHIELD_OR_SPEAR = 4,
KEY3 = 5,
KEY5 = 6,
KEY6 = 7,
PropType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
PropType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
};
bool PropType_IsValid(int value);
constexpr PropType PropType_MIN = NULL_PROP_TYPE;
constexpr PropType PropType_MAX = PTYPE4;
constexpr PropType PropType_MAX = KEY6;
constexpr int PropType_ARRAYSIZE = PropType_MAX + 1;

const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* PropType_descriptor();


+ 6
- 0
dependency/proto/Message2Server.proto View File

@@ -46,6 +46,12 @@ message IDMsg
int64 player_id = 1;
}

message TreatAndRescueMsg
{
int64 player_id = 1;
int64 to_player_id = 2;
}

message SkillMsg
{
int64 player_id = 1;


+ 2
- 2
dependency/proto/py_output.sh View File

@@ -3,5 +3,5 @@ python3 -m grpc_tools.protoc -I. --python_out=. --pyi_out=. Message2Clients.prot
python3 -m grpc_tools.protoc -I. --python_out=. --pyi_out=. Message2Server.proto
python3 -m grpc_tools.protoc -I. --python_out=. --pyi_out=. --grpc_python_out=. Services.proto
chmod -R 755 ./
mv -f ./*.py ../../PyAPI/proto
mv -f ./*.pyi ../../PyAPI/proto
mv -f ./*.py ../../CAPI/python/proto
mv -f ./*.pyi ../../CAPI/python/proto

+ 39
- 16
installer/Installer/MainWindow.xaml View File

@@ -5,16 +5,17 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Installer"
mc:Ignorable="d"
Title="Installer" Height="450" Width="800">
Title="Installer" Height="200" Window.SizeToContent="Width">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="250" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="25" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
@@ -26,22 +27,44 @@
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="*" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Text="欢迎使用选手包" Visibility="{Binding InstIntroVis}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Text="你已经安装了选手包,请选择你要进行的操作" Visibility="{Binding EditIntroVis}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="5" Text="{Binding Intro}" />

<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="5" Text="{Binding RouteBoxIntro}"/>

<TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="5" Name="RouteTxtBox" Text="{Binding Route}" Visibility="{Binding RouteBoxVis}"/>
<Button Grid.Row="3" Grid.Column="6" Name="GetRouteBtn" Content="Browse..." Command="{Binding ClickBrowseCommand}" Visibility="{Binding RouteBoxVis}" />
<Button Grid.Row="3" Grid.Column="7" Name="SetBtm" Content="Confirm" Command="{Binding ClickConfirmCommand}" Visibility="{Binding RouteBoxVis}"/>
<Button Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" Name="UpdateBtn" Content="{Binding UpdateBtnCont}" Command="{Binding ClickUpdateCommand}" Visibility="{Binding MenuVis}" />

<Button Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="2" Name="MoveBtn" Content="Move" Command="{Binding ClickMoveCommand}" Visibility="{Binding MenuVis}" />

<Button Grid.Row="7" Grid.Column="2" Grid.ColumnSpan="2" Name="UninstBtn" Content="UnInstall" Command="{Binding ClickUninstCommand}" Visibility="{Binding MenuVis}" />

<TextBlock Grid.Row="3" Grid.Column="4" Text="Processing" Grid.ColumnSpan="2" Visibility="{Binding ProgressVis}"/>
<ProgressBar Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="6" Minimum="0" Maximum="100" Name="Progress" Visibility="{Binding ProgressVis}" IsIndeterminate="True"/>

<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Text="将主体程序安装在:" Visibility="{Binding InstIntroVis}"/>
<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Text="将主体程序移动到:" Visibility="{Binding MoveIntroVis}"/>
<TextBlock Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="4" Text="操作完成!你可以继续操作或退出" Visibility="{Binding CompleteVis}"/>
<Button Grid.Row="6" Grid.Column="2" Name="BackBtn" Content="返回" Command="{Binding ClickBackCommand}" Visibility="{Binding CompleteVis}"/>
<Button Grid.Row="6" Grid.Column="4" Grid.ColumnSpan="2" Name="ExitBtn" Content="退出" Command="{Binding ClickExitCommand}" Visibility="{Binding CompleteVis}"/>

<TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" Name="RouteTxtBox" Text="{Binding Route}" Visibility="{Binding RouteBoxVis}"/>
<Button Grid.Row="3" Grid.Column="4" Name="GetRouteBtn" Content="Browse..." Command="{Binding ClickBrowseCommand}" Visibility="{Binding RouteBoxVis}" />
<Button Grid.Row="3" Grid.Column="5" Name="SetBtm" Content="Confirm" Command="{Binding ClickConfirmCommand}" Visibility="{Binding RouteBoxVis}"/>
<Button Grid.Row="3" Grid.Column="2" Name="UpdateBtn" Content="Update" Command="{Binding ClickUpdateCommand}" Visibility="{Binding EditIntroVis}" />
<TextBlock Grid.Row="3" Grid.Column="1" Text="账号:" Visibility="{Binding LoginVis}" />
<TextBlock Grid.Row="5" Grid.Column="1" Text="密码:" Visibility="{Binding LoginVis}" />
<TextBox Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="4" Name="Username" Visibility="{Binding LoginVis}" Text="{Binding Username}" />
<TextBox Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="4" Name="Password" Visibility="{Binding LoginVis}" Text="{Binding Password}" />
<Button Grid.Row="7" Grid.Column="1" Name="Login" Content="登录" Command="{Binding ClickLoginCommand}" Visibility="{Binding LoginVis}"/>
<Button Grid.Row="7" Grid.Column="2" Name="Launch" Content="{Binding LaunchBtnCont}" Command="{Binding ClickLaunchCommand}" Visibility="{Binding LoginVis}"/>
<Button Grid.Row="7" Grid.Column="4" Grid.ColumnSpan="2" Name="Edit" Content="修改文件" Command="{Binding ClickEditCommand}" Visibility="{Binding LoginVis}"/>
<TextBlock Grid.Row="6" Grid.Column="1" Text="用户名或密码错误!" Visibility="{Binding LoginFailVis}"/>

<Button Grid.Row="5" Grid.Column="2" Name="MoveBtn" Content="Move" Command="{Binding ClickMoveCommand}" Visibility="{Binding EditIntroVis}" />
<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Text="你有已完成的比赛!" Visibility="{Binding MatchFinishedVis}"/>
<Button Grid.Row="3" Grid.Column="1" Name ="Upload" Content="上传代码" Command="{Binding ClickUploadCommand}" Visibility="{Binding WebVis}"/>
<Button Grid.Row="5" Grid.Column="1" Name="Download" Content="下载回放" Command="{Binding ClickDownloadCommand}" Visibility="{Binding WebVis}" />
<Button Grid.Row="7" Grid.Column="1" Name="Replay" Content="打开回放" Command="{Binding ClickReplayCommand}" Visibility="{Binding WebVis}" />
<Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" />
<TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="{Binding Enemy}" Visibility="{Binding WebVis}" />
<Button Grid.Row="6" Grid.Column="3" Grid.ColumnSpan="2" Content="退出登录" Command="{Binding ClickLogoutCommand}" Visibility="{Binding WebVis}" />

<Button Grid.Row="7" Grid.Column="2" Name="UninstBtn" Content="UnInst" Command="{Binding ClickUninstCommand}" Visibility="{Binding EditIntroVis}" />
</Grid>
</Window>

+ 194
- 40
installer/Installer/Model.cs View File

@@ -22,6 +22,9 @@ using System.Windows;
using System.Windows.Shapes;
//using System.Windows.Forms;

using MessageBox = System.Windows.MessageBox;
using Downloader;

namespace starter.viewmodel.settings
{
/// <summary>
@@ -32,27 +35,25 @@ namespace starter.viewmodel.settings
/// <summary>
/// downloader function
/// </summary>
private Downloader.Program.Data configData = new Downloader.Program.Data("");
private Downloader.Program.Tencent_cos_download cloud = new Downloader.Program.Tencent_cos_download();
private Data configData = new Data("");
private Tencent_cos_download cloud = new Tencent_cos_download();

private HttpClient client = new HttpClient();
private WebConnect.Web web = new WebConnect.Web();

/// <summary>
/// save settings
/// </summary>
public bool install()
{
if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload())
if (Tencent_cos_download.CheckAlreadyDownload())
{
MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
// ask if abort install, with warning sign, defalut no;
if (repeatOption == MessageBoxResult.Cancel)
if (repeatOption == MessageBoxResult.No)
{
return false; // 回到选择地址界面
}
else if (repeatOption == MessageBoxResult.No)
{
System.Environment.Exit(0);
return false;
}
else
{
Downloader.Program.Tencent_cos_download.MoveProgram(Route);
@@ -61,11 +62,76 @@ namespace starter.viewmodel.settings
}
else
{
Downloader.Program.Data.ResetFilepath(Route);
Downloader.Program.Tencent_cos_download.DownloadAll();
Data.ResetFilepath(Route);
Tencent_cos_download.DownloadAll();
return true;
}
}
public int move()
{
return Tencent_cos_download.MoveProgram(Route);
}
///<summary>
///check for update
/// </summary>
static bool ProfileAvailable
{
get; set;
}
/// <summary>
/// 检查更新
/// </summary>
/// <returns></returns>
public Status checkUpdate()
{
UpdateInfo updateInfo = Tencent_cos_download.Check();
if (updateInfo.newFileCount == -1)
{
if (updateInfo.changedFileCount == -1)
{
return Status.error;
}
else
{
return Status.disconnected;
}
}
else
{
if (updateInfo.changedFileCount != 0 || updateInfo.newFileCount != 0)
{
Updates = "发现新版本" + updateInfo.status;
}
return Status.menu;
}
}

public void Login()
{
_ = web.LoginToEEsast(client, Username, Password);
}
public bool Update()
{
return Tencent_cos_download.Update();
}
public int Uninst()
{
return Tencent_cos_download.DeleteAll();
}

public bool Launch()
{
if (Tencent_cos_download.CheckAlreadyDownload())
{
Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
return true;
}
else
{
MessageBox.Show($"文件还不存在,请安装主体文件", "文件不存在", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
return false;
}
}
/// <summary>
/// Route of files
/// </summary>
@@ -73,24 +139,69 @@ namespace starter.viewmodel.settings
{
get
{
return Downloader.Program.Data.FilePath;
return Data.FilePath;
}
set
{
Downloader.Program.Data.FilePath = value;
Data.FilePath = value;
}
}

public string Username
{
get; set;
}
public string Password
{
get; set;
}
/// <summary>
/// if the route was set or is under editing
/// 关于更新的屏幕显示信息
/// </summary>
public bool EditingRoute
private string updates;
public string Updates
{
get
{
return updates;
}
set
{
updates = value;
}
}
/// <summary>
/// 关于介绍的屏幕显示信息
/// </summary>
public enum Status { newUser, menu, move, working, disconnected, error, successful, login, web };
public Status status
{
get; set;
}
public bool Working
{
get; set;
}
///< summary>
/// if already installed
/// </summary>
public bool installed
/// <summary>
/// if an update is planned
/// </summary>
public bool UpdatePlanned
{
get
{
return Program.UpdatePlanned;
}
}

public bool CombatCompleted
{
get
{
return false;
}
}

public bool LoginFailed
{
get; set;
}
@@ -102,9 +213,21 @@ namespace Downloader
{
static List<string> newFileName = new List<string>(); // 新文件名
static List<string> updateFileName = new List<string>(); // 更新文件名
static string ProgramName = "THUAI6"; // 要运行或下载的程序名称
static string playerFolder = "player"; // 选手代码保存文件夹路径
static string startName = "maintest.exe"; // 启动的程序名
public static string ProgramName = "THUAI6"; // 要运行或下载的程序名称
public static string playerFolder = "player"; // 选手代码保存文件夹路径
public static string startName = "maintest.exe"; // 启动的程序名

public struct UpdateInfo // 更新信息,包括新版本版本号、更改文件数和新文件数
{
public string status;
public int changedFileCount;
public int newFileCount;
}
public static bool UpdatePlanned
{
get; set;
}

static int filenum = 0; // 总文件个数

public class Data
@@ -283,13 +406,14 @@ namespace Downloader
}
}

private static void Check()
public static UpdateInfo Check()
{
string json, MD5, jsonName;
int newFile = 0, updateFile = 0;
newFileName.Clear();
updateFileName.Clear();
jsonName = "hash.json";
UpdateInfo updateInfo;

Tencent_cos_download Downloader = new Tencent_cos_download();
try
@@ -308,14 +432,18 @@ namespace Downloader
catch (CosClientException clientEx)
{
// 请求失败
Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
return;
updateInfo.status = "ClientEx: " + clientEx.ToString();
updateInfo.newFileCount = -1;
updateInfo.changedFileCount = 0;
return updateInfo;
}
catch (CosServerException serverEx)
{
// 请求失败
Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
return;
updateInfo.status = "ServerEx: " + serverEx.ToString();
updateInfo.newFileCount = -1;
updateInfo.changedFileCount = 0;
return updateInfo;
}

using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
@@ -334,22 +462,29 @@ namespace Downloader
newFile = newFileName.Count;
updateFile = updateFileName.Count;
filenum = newFile + updateFile;
Console.WriteLine("----------------------" + Environment.NewLine);
//Console.WriteLine("----------------------" + Environment.NewLine);

if (newFile + updateFile == 0)
{
Console.WriteLine("当前平台已是最新版本!" + Environment.NewLine);
updateInfo.status = "latest";
updateInfo.newFileCount = 0;
updateInfo.changedFileCount = 0;
newFileName.Clear();
updateFileName.Clear();
}
else
{
Console.WriteLine($"发现{newFile}个新文件" + Environment.NewLine);
updateInfo.status = "old";
//TODO:获取版本号
updateInfo.newFileCount = newFile;
/*
foreach (string filename in newFileName)
{
Console.WriteLine(filename);
}
Console.WriteLine(Environment.NewLine + $"发现{updateFile}个文件更新" + Environment.NewLine);
*/
updateInfo.changedFileCount = updateFile;
/*
foreach (string filename in updateFileName)
{
Console.WriteLine(filename);
@@ -359,8 +494,23 @@ namespace Downloader
Console.WriteLine("下载取消!");
else
Download();
*/
UpdatePlanned = true;
}
return updateInfo;
}

public static bool Update()
{
if (UpdatePlanned)
{
Download();
UpdatePlanned = false;
return true;
}
return false;
}

private static void Download()
{
Tencent_cos_download Downloader = new Tencent_cos_download();
@@ -592,7 +742,7 @@ namespace Downloader
}
}

public static void DeleteAll()
public static int DeleteAll()
{
DirectoryInfo di = new DirectoryInfo(Data.FilePath);
DirectoryInfo player = new DirectoryInfo(System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder)));
@@ -619,17 +769,17 @@ namespace Downloader
catch (UnauthorizedAccessException)
{
Console.WriteLine("权限不足,无法删除!");
return;
return -2;
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
return;
return -3;
}
catch (IOException)
{
Console.WriteLine("文件已经打开,请关闭后再删除");
return;
return -1;
}

string json2;
@@ -665,19 +815,20 @@ namespace Downloader
catch (UnauthorizedAccessException)
{
Console.WriteLine("权限不足,无法删除!");
return;
return -2;
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
return;
return -3;
}
catch (IOException)
{
Console.WriteLine("文件已经打开,请关闭后再删除");
return;
return -1;
}
Console.WriteLine($"删除成功!player文件夹中的文件已经放在{ProgramName}的根目录下");
return 0;
}

public static void OverwriteHash(Dictionary<string, string> jsonDict)
@@ -687,7 +838,7 @@ namespace Downloader
File.WriteAllText(@System.IO.Path.Combine(Data.FilePath, "hash.json"), Contentjson);
}

public static void MoveProgram(string newPath)
public static int MoveProgram(string newPath)
{
DirectoryInfo newdi = new DirectoryInfo(newPath);
DirectoryInfo olddi = new DirectoryInfo(Data.FilePath);
@@ -714,6 +865,7 @@ namespace Downloader
file.MoveTo(System.IO.Path.Combine(Data.FilePath, file.Name));
}
Console.WriteLine("移动失败!");
return -2;
}
catch (IOException)
{
@@ -727,9 +879,11 @@ namespace Downloader
file.MoveTo(System.IO.Path.Combine(Data.FilePath, file.Name));
}
Console.WriteLine("移动失败!");
return -1;
}
Data.ResetFilepath(newPath);
Console.WriteLine("更改路径成功!");
return 0;
}
public static async Task main(string[] args)
{


+ 333
- 32
installer/Installer/ViewModel.cs View File

@@ -3,6 +3,9 @@ using starter.viewmodel.common;
using System;
using System.Windows;
using System.Windows.Forms;
using Downloader;
using MessageBox = System.Windows.MessageBox;
using System.Configuration;

namespace starter.viewmodel.settings
{
@@ -19,12 +22,111 @@ namespace starter.viewmodel.settings
{
if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload())
{
Installed = true;
obj.checkUpdate();
Status = SettingsModel.Status.login;
this.RaisePropertyChanged("WindowWidth");
//TODO:在启动时立刻检查更新,确保选手启动最新版选手包
//TODO:若有更新,将启动键改为更新键;
//TODO:相应地,使用login界面启动;
//TODO:结构:上方为登录框架,下方有“修改选手包”按钮
}
else
{
Route = Environment.GetEnvironmentVariable("USERPROFILE") + "\\THUAI6";
EditingRoute = true;
Status = SettingsModel.Status.newUser;
this.RaisePropertyChanged("WindowWidth");
}
}

//TODO:参赛界面:包括上传参赛代码、申请对战
//TODO:界面中应包含上次对战完成提示及下载回放按钮

public int ExtraColumn
{
get
{
if (Status == SettingsModel.Status.newUser || Status == SettingsModel.Status.move)
return 75;
else
return 0;
}
}
public int WindowWidth
{
get
{
switch (Status)
{
case SettingsModel.Status.newUser:
return 505;
case SettingsModel.Status.move:
return 505;
case SettingsModel.Status.working:
return 435;
case SettingsModel.Status.successful:
return 435;
default:
return 355;
}
}
}

public SettingsModel.Status Status
{
get
{
return obj.status;
}
set
{
obj.status = value;
this.RaisePropertyChanged("ExtraColumn");
this.RaisePropertyChanged("Intro");
this.RaisePropertyChanged("RouteBoxIntro");
this.RaisePropertyChanged("LoginVis");
this.RaisePropertyChanged("MenuVis");
this.RaisePropertyChanged("RouteBoxVis");
this.RaisePropertyChanged("ProgressVis");
this.RaisePropertyChanged("CompleteVis");
}
}
public string Intro
{
get
{
switch (Status)
{
case SettingsModel.Status.newUser:
return "欢迎使用选手包,请选择你想要安装选手包的位置:";
case SettingsModel.Status.menu:
return "你已经安装了选手包,请选择想要进行的操作:";
case SettingsModel.Status.login:
return "使用EESAST账号登录";
case SettingsModel.Status.web:
return "THUAI6 赛场:";
case SettingsModel.Status.disconnected:
return "你可能没有连接到网络,无法下载/更新选手包";
case SettingsModel.Status.error:
return "我们遇到了一些问题,请向[]反馈";
default:
return "";
}
}
}
public string RouteBoxIntro
{
get
{
switch (Status)
{

case SettingsModel.Status.newUser:
return "将主体程序安装在:";
case SettingsModel.Status.move:
return "将主体程序移动到:";
default:
return "";
}
}
}

@@ -40,67 +142,106 @@ namespace starter.viewmodel.settings
this.RaisePropertyChanged("Route");
}
}
public bool Installed
public string Username
{
get
{
return obj.installed;
return obj.Username;
}
set
{
obj.installed = value;
this.RaisePropertyChanged("Installed");
this.RaisePropertyChanged("InstIntroVis");
this.RaisePropertyChanged("EditIntroVis");
this.RaisePropertyChanged("MoveIntroVis");
obj.Username = value;
this.RaisePropertyChanged("Username");
}
}
public bool EditingRoute
public string Password
{
get { return obj.Password; }
set
{
obj.Password = value;
this.RaisePropertyChanged("Password");
}
}
public Visibility MenuVis
{
get
{
return obj.EditingRoute;
return Status == SettingsModel.Status.menu ? Visibility.Visible : Visibility.Collapsed;
}
set
}
public Visibility RouteBoxVis
{
get
{
obj.EditingRoute = value;
this.RaisePropertyChanged("EditingRoute");
this.RaisePropertyChanged("MoveIntroVis");
this.RaisePropertyChanged("RouteBoxVis");
return (Status == SettingsModel.Status.newUser || Status == SettingsModel.Status.move) ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility RouteBoxVis // if the route editing textbox is visible
public Visibility LoginVis
{
get
{
return obj.EditingRoute ? Visibility.Visible : Visibility.Collapsed;
return Status == SettingsModel.Status.login ? Visibility.Visible : Visibility.Collapsed;
}
}
/// <summary>
/// if the install/edit instruction can be seen
/// </summary>
public Visibility InstIntroVis
public Visibility ProgressVis
{
get
{
return Status == SettingsModel.Status.working ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility CompleteVis
{
get
{
return obj.installed ? Visibility.Collapsed : Visibility.Visible;
return Status == SettingsModel.Status.successful ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility EditIntroVis
public Visibility WebVis
{
get
{
return obj.installed ? Visibility.Visible : Visibility.Collapsed;
return Status == SettingsModel.Status.web ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility MoveIntroVis
public Visibility LoginFailVis
{
get
{
if (obj.installed == true && obj.EditingRoute == true)
return Visibility.Visible;
return obj.LoginFailed ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility MatchFinishedVis
{
get
{
return obj.CombatCompleted ? Visibility.Visible : Visibility.Collapsed;
}
}

public string UpdateBtnCont
{
get
{
return obj.UpdatePlanned ? "Update" : "Check Updates";
}
}
public string UpdateInfo
{
get
{
if (obj.UpdatePlanned)
return obj.Updates;
else
return Visibility.Collapsed;
return "";
}
}
public string LaunchBtnCont
{
get
{
return obj.UpdatePlanned ? "更新" : "启动";
}
}

@@ -133,15 +274,175 @@ namespace starter.viewmodel.settings
{
clickConfirmCommand = new BaseCommand(new Action<object>(o =>
{
if (obj.install())
if (Status == SettingsModel.Status.newUser)
{
EditingRoute = false;
Installed = true;
Status = SettingsModel.Status.working;
if (obj.install())
{
Status = SettingsModel.Status.menu;
}

}
else if (Status == SettingsModel.Status.move)
{
Status = SettingsModel.Status.working;
switch (obj.move())
{
case -1:
MessageBox.Show("文件已打开或者目标路径下有同名文件!", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
break;
case -2:
Status = SettingsModel.Status.error;
break;
}
}
}));
}
return clickConfirmCommand;
}
}
private BaseCommand clickUpdateCommand;
public BaseCommand ClickUpdateCommand
{
get
{
if (clickUpdateCommand == null)
{
clickUpdateCommand = new BaseCommand(new Action<object>(o =>
{
if (obj.UpdatePlanned)
{
Status = SettingsModel.Status.working;
if (obj.Update())
{

Status = SettingsModel.Status.successful;
this.RaisePropertyChanged("UpdateButtonCont");

}
else
Status = SettingsModel.Status.error;
}
else
{
Status = SettingsModel.Status.working;
Status = obj.checkUpdate();
this.RaisePropertyChanged("UpdateButtonCont");
}
}));
}
return clickUpdateCommand;
}
}
private BaseCommand clickMoveCommand;
public BaseCommand ClickMoveCommand
{
get
{
if (clickMoveCommand == null)
{
clickMoveCommand = new BaseCommand(new Action<object>(o =>
{
Status = SettingsModel.Status.move;
}));
}
return clickMoveCommand;
}
}
private BaseCommand clickUninstCommand;
public BaseCommand ClickUninstCommand
{
get
{
if (clickUninstCommand == null)
{
clickUninstCommand = new BaseCommand(new Action<object>(o =>
{
Status = SettingsModel.Status.working;
switch (obj.Uninst())
{
case -1:
Status = SettingsModel.Status.menu;
MessageBox.Show("文件已经打开,请关闭后再删除", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
break;
case 0:
Status = SettingsModel.Status.successful;
break;
default:
Status = SettingsModel.Status.error;
break;

}
}));
}
return clickUninstCommand;
}
}

private BaseCommand clickLoginCommand;
public BaseCommand ClickLoginCommand
{
get
{
if (clickLoginCommand == null)
{
clickLoginCommand = new BaseCommand(new Action<object>(o =>
{
obj.Login();
this.RaisePropertyChanged("LoginFailVis");
}));
}
return clickLoginCommand;
}
}

private BaseCommand clickLaunchCommand;
public BaseCommand ClickLaunchCommand
{
get
{
if (clickLaunchCommand == null)
{
clickLaunchCommand = new BaseCommand(new Action<object>(o =>
{
if (!obj.Launch())
{
Status = SettingsModel.Status.menu;
}
}));
}
return clickLaunchCommand;
}
}
private BaseCommand clickEditCommand;
public BaseCommand ClickEditCommand
{
get
{
if (clickEditCommand == null)
{
clickEditCommand = new BaseCommand(new Action<object>(o =>
{
Status = SettingsModel.Status.menu;
}));
}
return clickEditCommand;
}
}
private BaseCommand clickLogoutCommand;
public BaseCommand ClickLogoutCommand
{
get
{
if (clickLogoutCommand == null)
{
clickLogoutCommand = new BaseCommand(new Action<object>(o =>
{
Status = SettingsModel.Status.login;
}));
}
return clickLogoutCommand;
}
}
}
}

+ 13
- 0
logic/GameClass/GameObj/Character/Character.cs View File

@@ -460,6 +460,19 @@ namespace GameClass.GameObj
}
}

public Prop UseProp(PropType propType)
{
lock (gameObjLock)
{
foreach (Prop prop in propInventory)
{
if (prop.GetPropType() == propType)
return prop;
}
return new NullProp();
}
}

/// <summary>
/// 如果indexing==GameData.maxNumOfPropInPropInventory表明道具栏为满
/// </summary>


+ 11
- 0
logic/GameClass/GameObj/Character/Skill.cs View File

@@ -29,6 +29,15 @@ namespace GameClass.GameObj
public object ActiveSkillLock => commonSkillLock;
}

public class Punish : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 6;

private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
}

public class NuclearWeapon : IActiveSkill // 核武器
{
public int SkillCD => GameData.commonSkillCD / 3 * 7;
@@ -86,6 +95,8 @@ namespace GameClass.GameObj
return ActiveSkillType.UseKnife;
case CanBeginToCharge:
return ActiveSkillType.CanBeginToCharge;
case Punish:
return ActiveSkillType.Publish;
default:
return ActiveSkillType.Null;
}


+ 1
- 0
logic/Gaming/ActionManager.cs View File

@@ -18,6 +18,7 @@ namespace Gaming
public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection)
{
if (!playerToMove.Commandable()) return false;
playerToMove.PlayerState = PlayerStateType.Moving;
moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection);
return true;
}


+ 6
- 6
logic/Gaming/Game.cs View File

@@ -341,24 +341,24 @@ namespace Gaming
_ = attackManager.Attack(player, angle);
}
}
public void UseProp(long playerID, int indexing)
public void UseProp(long playerID, PropType propType)
{
if (!gameMap.Timer.IsGaming)
return;
Character? player = gameMap.FindPlayer(playerID);
if (player != null)
{
propManager.UseProp(player, indexing);
propManager.UseProp(player, propType);
}
}
public void ThrowProp(long playerID, int indexing)
public void ThrowProp(long playerID, PropType propType)
{
if (!gameMap.Timer.IsGaming)
return;
Character? player = gameMap.FindPlayer(playerID);
if (player != null)
{
propManager.ThrowProp(player, indexing);
propManager.ThrowProp(player, propType);
}
}
public bool PickProp(long playerID, PropType propType = PropType.Null)
@@ -373,14 +373,14 @@ namespace Gaming
return false;
}

public bool UseActiveSkill(long playerID, ActiveSkillType activeSkillType)
public bool UseActiveSkill(long playerID, int skillNum)
{
if (!gameMap.Timer.IsGaming)
return false;
Character? player = gameMap.FindPlayer(playerID);
if (player != null)
{
return skillManager.UseActiveSkill(player, activeSkillType);
return skillManager.UseActiveSkill(player, player.Occupation.ListOfIActiveSkill[skillNum]);
}
else
return false;


+ 10
- 6
logic/Gaming/PropManager.cs View File

@@ -21,11 +21,11 @@ namespace Gaming

private readonly List<XY> availableCellForGenerateProp;

public void UseProp(Character player, int indexing)
public void UseProp(Character player, PropType propType)
{
if (player.IsResetting)
return;
Prop prop = player.UseProp(indexing);
Prop prop = player.UseProp(propType);
switch (prop.GetPropType())
{
case PropType.ShieldOrSpear:
@@ -43,8 +43,12 @@ namespace Gaming
break;
case PropType.AddHpOrAp:
if (!player.IsGhost())
player.HP += GameData.basicTreatmentDegree;
else player.AddAp(GameData.PropDuration);
if (player.HP < player.MaxHp)
{
player.HP += GameData.basicTreatmentDegree;
player.AddScore(GameData.ScorePropAddHp);
}
else player.AddAp(GameData.PropDuration);
break;
default:
break;
@@ -102,11 +106,11 @@ namespace Gaming
return false;
}

public void ThrowProp(Character player, int indexing)
public void ThrowProp(Character player, PropType propType)
{
if (!gameMap.Timer.IsGaming || player.IsResetting)
return;
Prop prop = player.UseProp(indexing);
Prop prop = player.UseProp(propType);
if (prop.GetPropType() == PropType.Null)
return;



+ 2
- 2
logic/Preparation/Interface/IOccupation.cs View File

@@ -76,7 +76,7 @@ namespace Preparation.Interface

public BulletType InitBullet => BulletType.Null;

public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.CanBeginToCharge });
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Publish });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

public const int fixSpeed = 0;
@@ -116,7 +116,7 @@ namespace Preparation.Interface

public BulletType InitBullet => BulletType.Null;

public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { });
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.CanBeginToCharge });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

public const int fixSpeed = GameData.basicFixSpeed * 6 / 10;


+ 3
- 2
logic/Preparation/Utility/EnumType.cs View File

@@ -79,7 +79,7 @@ namespace Preparation.Utility
Athlete = 2,
RecoverAfterBattle = 3,
SpeedUpWhenLeavingGrass = 4,
PSkill4 = 5,
Teacher = 5,
PSkill5 = 6
}
public enum ActiveSkillType // 主动技能
@@ -90,7 +90,8 @@ namespace Preparation.Utility
NuclearWeapon = 3,
SuperFast = 4,
UseKnife = 5,
CanBeginToCharge = 6
CanBeginToCharge = 6,
Publish = 7,
}
public enum PassiveSkillType
{


+ 1
- 4
logic/Preparation/Utility/GameData.cs View File

@@ -128,11 +128,8 @@ namespace Preparation.Utility
public const int ScorePropUseShield = 20;
public const int ScorePropUseSpear = 20;
public const int ScorePropAddAp = 10;
public const int ScorePropAddHp = 50;

public static int ScoreUseProp(PropType prop, bool IsGhost)
{
return 0;
}
public static int ScoreUseSkill(ActiveSkillType activeSkillType)
{
return 0;


+ 2
- 2
logic/Server/CopyInfo.cs View File

@@ -305,11 +305,11 @@ namespace Server
foreach (var keyValue in player.TimeUntilActiveSkillAvailable)
msg.TrickerMessage.TimeUntilSkillAvailable.Add(keyValue.Value);
for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count(); ++i)
msg.StudentMessage.TimeUntilSkillAvailable.Add(-1);
msg.TrickerMessage.TimeUntilSkillAvailable.Add(-1);

msg.TrickerMessage.Place = ToPlaceType(player.Place);
foreach (var value in player.PropInventory)
msg.StudentMessage.Prop.Add(ToPropType(value.GetPropType()));
msg.TrickerMessage.Prop.Add(ToPropType(value.GetPropType()));

msg.TrickerMessage.TrickerType = ToTrickerType(player.CharacterType);
msg.TrickerMessage.Guid = player.ID;


+ 27
- 18
logic/规则Logic.md View File

@@ -262,23 +262,6 @@
- [箱子不可被关闭]
- [箱子内道具最多两个]

### 道具
- 每次玩家试图捡起道具时,需要确保道具栏有空位
- indexing指道具栏数组下标从0开始
- 扔道具
- Logic内实现
~~~csharp
public void ThrowProp(long playerID, int indexing)
~~~
- 对应下标出现空位,不会对数组进行重新排序
- 使用道具
- Logic内实现
~~~csharp
public void UseProp(long playerID,int indexing)
~~~
- 对应下标出现空位,不会对数组进行重新排序


### 治疗
- 可行动的求生者可以对受伤的其他求生者进行治疗,治疗完成后会回复被治疗程度的血量。
- 治疗时每毫秒增加相当于治疗者治疗速度的被治疗程度
@@ -343,4 +326,30 @@

#### ~~解除眩晕~~

#### ~~自愈~~
#### ~~自愈~~

## 道具
- 每次玩家试图捡起道具时,需要确保道具栏有空位
- indexing指道具栏数组下标从0开始
- 扔道具
- Logic内实现
~~~csharp
public void ThrowProp(long playerID, int indexing)
~~~
- 对应下标出现空位,不会对数组进行重新排序
- 使用道具
- Logic内实现
~~~csharp
public void UseProp(long playerID,int indexing)
~~~
- 对应下标出现空位,不会对数组进行重新排序

| 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] |
| :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------|
| AddSpeed | 提高移动速度,持续10s |不得分| 提高移动速度,持续10s |不得分|
| AddLifeOrAp |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? |
| AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? |
| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生|
| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分|
| Key5 | 能开启5教的门 |不得分| 能开启3教的门 |不得分|
| Key6 | 能开启6教的门 |不得分| 能开启3教的门 |不得分|

Loading…
Cancel
Save