| @@ -108,7 +108,7 @@ enum StudentType | |||
| NULL_STUDENT_TYPE = 0; | |||
| ATHLETE = 1; | |||
| STUDENTTYPE2 = 2;//Teacher | |||
| STUDENTTYPE3 = 3; | |||
| STUDENTTYPE3 = 3;//StraightAStudent | |||
| STUDENTTYPE4 = 4; | |||
| } | |||
| @@ -110,7 +110,7 @@ namespace GameClass.GameObj | |||
| case BulletType.JumpyDumpty: | |||
| return JumpyDumpty.maxBulletNum; | |||
| default: | |||
| return GameData.basicCD; | |||
| return 1; | |||
| } | |||
| } | |||
| } | |||
| @@ -19,7 +19,7 @@ namespace GameClass.GameObj | |||
| private Dictionary<ActiveSkillType, IActiveSkill> iActiveSkillDictionary = new(); | |||
| public Dictionary<ActiveSkillType, IActiveSkill> IActiveSkillDictionary => iActiveSkillDictionary; | |||
| public IActiveSkill UseIActiveSkill(ActiveSkillType activeSkillType) | |||
| public IActiveSkill FindIActiveSkill(ActiveSkillType activeSkillType) | |||
| { | |||
| if (Occupation.ListOfIActiveSkill.Contains(activeSkillType)) | |||
| { | |||
| @@ -72,6 +72,9 @@ namespace GameClass.GameObj | |||
| case CharacterType.Klee: | |||
| this.occupation = new Klee(); | |||
| break; | |||
| case CharacterType.StraightAStudent: | |||
| this.occupation = new StraightAStudent(); | |||
| break; | |||
| case CharacterType.Athlete: | |||
| default: | |||
| this.occupation = new Athlete(); | |||
| @@ -104,6 +104,33 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| public class WriteAnswers : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| private int degreeOfMeditation = 0; | |||
| public int DegreeOfMeditation | |||
| { | |||
| get => degreeOfMeditation; | |||
| set | |||
| { | |||
| lock (commonSkillLock) | |||
| { | |||
| degreeOfMeditation = value; | |||
| } | |||
| } | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| } | |||
| public class NullSkill : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| @@ -134,6 +161,8 @@ namespace GameClass.GameObj | |||
| return new Punish(); | |||
| case ActiveSkillType.JumpyBomb: | |||
| return new JumpyBomb(); | |||
| case ActiveSkillType.WriteAnswers: | |||
| return new WriteAnswers(); | |||
| default: | |||
| return new NullSkill(); | |||
| } | |||
| @@ -153,6 +182,8 @@ namespace GameClass.GameObj | |||
| return ActiveSkillType.Punish; | |||
| case JumpyBomb: | |||
| return ActiveSkillType.JumpyBomb; | |||
| case WriteAnswers: | |||
| return ActiveSkillType.WriteAnswers; | |||
| default: | |||
| return ActiveSkillType.Null; | |||
| } | |||
| @@ -21,14 +21,14 @@ namespace Gaming | |||
| { | |||
| if (collisionObj.Type == GameObjType.Bullet) | |||
| { | |||
| if (((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) | |||
| if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) | |||
| { | |||
| if (AttackManager.BeStunned((Character)player, ((Bullet)collisionObj).AP / GameData.timeFactorOfGhostFainting)) | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(((Bullet)collisionObj).AP / GameData.timeFactorOfGhostFainting)); | |||
| gameMap.Remove((GameObj)collisionObj); | |||
| } | |||
| } | |||
| if (player.UseIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | |||
| if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | |||
| { | |||
| if (AttackManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenCharge)); | |||
| @@ -138,6 +138,10 @@ namespace Gaming | |||
| if ((!(((Character)objBeingShot).IsGhost())) && bullet.Parent.IsGhost()) | |||
| { | |||
| Student whoBeAttacked = (Student)objBeingShot; | |||
| if (whoBeAttacked.CharacterType == CharacterType.StraightAStudent) | |||
| { | |||
| ((WriteAnswers)whoBeAttacked.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0; | |||
| } | |||
| if (whoBeAttacked.BeAttacked(bullet)) | |||
| { | |||
| BeAddictedToGame(whoBeAttacked, (Ghost)bullet.Parent); | |||
| @@ -13,7 +13,7 @@ namespace Gaming | |||
| { | |||
| public bool BecomeVampire(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.BecomeVampire), player, () => | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.BecomeVampire), player, () => | |||
| { | |||
| player.Vampire += 0.5; | |||
| Debugger.Output(player, "becomes vampire!"); | |||
| @@ -29,7 +29,7 @@ namespace Gaming | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill skill = player.UseIActiveSkill(ActiveSkillType.CanBeginToCharge); | |||
| IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge); | |||
| Debugger.Output(player, "can begin to charge!"); | |||
| @@ -45,7 +45,7 @@ namespace Gaming | |||
| public static bool BecomeInvisible(Character player) | |||
| { | |||
| IActiveSkill activeSkill = player.UseIActiveSkill(ActiveSkillType.BecomeInvisible); | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.BecomeInvisible); | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| player.AddInvisible(activeSkill.DurationTime); | |||
| @@ -57,7 +57,7 @@ namespace Gaming | |||
| public bool JumpyBomb(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.JumpyBomb), player, () => | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.JumpyBomb), player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.BombBomb; | |||
| Debugger.Output(player, "uses jumpybomb!"); | |||
| @@ -66,10 +66,27 @@ namespace Gaming | |||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||
| } | |||
| public bool WriteAnswers(Character player) | |||
| { | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.WriteAnswers); | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| Generator? generator = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); | |||
| if (generator != null) | |||
| { | |||
| generator.Repair(((WriteAnswers)activeSkill).DegreeOfMeditation); | |||
| Debugger.Output(player, "uses WriteAnswers in" + generator.ToString() + "with " + (((WriteAnswers)activeSkill).DegreeOfMeditation).ToString()); | |||
| ((WriteAnswers)activeSkill).DegreeOfMeditation = 0; | |||
| } | |||
| }, | |||
| () => | |||
| { }); | |||
| } | |||
| public static bool UseKnife(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.UseKnife), player, () => | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.UseKnife), player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.FlyingKnife; | |||
| Debugger.Output(player, "uses flyingknife!"); | |||
| @@ -80,7 +97,7 @@ namespace Gaming | |||
| public bool Punish(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.Punish), player, () => | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Punish), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| @@ -110,9 +127,9 @@ namespace Gaming | |||
| public bool SuperFast(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.SuperFast), player, () => | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.SuperFast), player, () => | |||
| { | |||
| player.AddMoveSpeed(player.UseIActiveSkill(ActiveSkillType.SuperFast).DurationTime, 3.0); | |||
| player.AddMoveSpeed(player.FindIActiveSkill(ActiveSkillType.SuperFast).DurationTime, 3.0); | |||
| Debugger.Output(player, "moves very fast!"); | |||
| }, | |||
| () => | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using System.Reflection.Emit; | |||
| using System.Threading; | |||
| using GameClass.GameObj; | |||
| using Preparation.Interface; | |||
| @@ -11,6 +12,48 @@ namespace Gaming // 被动技能开局时就释放,持续到游戏结束 | |||
| { | |||
| private partial class SkillManager | |||
| { | |||
| public void Meditate(Character player) | |||
| { | |||
| const int learningDegree = GameData.basicFixSpeed / 4; | |||
| WriteAnswers activeSkill = (WriteAnswers)player.FindIActiveSkill(ActiveSkillType.WriteAnswers); | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => gameMap.Timer.IsGaming && !player.IsResetting, | |||
| () => | |||
| { | |||
| if (player.Commandable()) activeSkill.DegreeOfMeditation += learningDegree; | |||
| else activeSkill.DegreeOfMeditation = 0; | |||
| Debugger.Output(player, "with " + (((WriteAnswers)activeSkill).DegreeOfMeditation).ToString()); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: GameData.gameDuration | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||
| #if DEBUG | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||
| } | |||
| #endif | |||
| } | |||
| }.Start(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public void RecoverAfterBattle(Character player) | |||
| { | |||
| const int recoverDegree = 5; // 每帧回复血量 | |||
| @@ -31,6 +31,9 @@ namespace Gaming | |||
| case ActiveSkillType.JumpyBomb: | |||
| JumpyBomb(character); | |||
| break; | |||
| case ActiveSkillType.WriteAnswers: | |||
| WriteAnswers(character); | |||
| break; | |||
| default: | |||
| return false; | |||
| } | |||
| @@ -41,6 +44,9 @@ namespace Gaming | |||
| if (character.Occupation.ListOfIPassiveSkill.Contains(passiveSkillType)) | |||
| switch (passiveSkillType) | |||
| { | |||
| case PassiveSkillType.Meditate: | |||
| Meditate(character); | |||
| break; | |||
| default: | |||
| return; | |||
| } | |||
| @@ -51,6 +57,9 @@ namespace Gaming | |||
| foreach (var passiveSkill in character.Occupation.ListOfIPassiveSkill) | |||
| switch (passiveSkill) | |||
| { | |||
| case PassiveSkillType.Meditate: | |||
| Meditate(character); | |||
| break; | |||
| default: | |||
| return; | |||
| } | |||
| @@ -184,4 +184,48 @@ namespace Preparation.Interface | |||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||
| } | |||
| public class StraightAStudent : IStudent | |||
| { | |||
| private const int moveSpeed = (int)(GameData.basicMoveSpeed * 0.8); | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = (int)(GameData.basicHp * 1.1); | |||
| public int MaxHp => maxHp; | |||
| private const int maxGamingAddiction = (int)(GameData.basicMaxGamingAddiction * 1.5); | |||
| public int MaxGamingAddiction => maxGamingAddiction; | |||
| public const int maxBulletNum = 0; | |||
| public int MaxBulletNum => maxBulletNum; | |||
| public BulletType InitBullet => BulletType.Null; | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.WriteAnswers }); | |||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { PassiveSkillType.Meditate }); | |||
| public const int fixSpeed = GameData.basicFixSpeed * 13 / 10; | |||
| public int FixSpeed => fixSpeed; | |||
| public const int treatSpeed = GameData.basicTreatSpeed * 8 / 10; | |||
| public int TreatSpeed => treatSpeed; | |||
| public const double concealment = GameData.basicConcealment * 0.9; | |||
| public double Concealment => concealment; | |||
| public const int alertnessRadius = (int)(GameData.basicAlertnessRadius * 0.9); | |||
| public int AlertnessRadius => alertnessRadius; | |||
| public int viewRange = GameData.basicViewRange; | |||
| public int ViewRange => viewRange; | |||
| public int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; | |||
| public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking; | |||
| public int speedOfClimbingThroughWindows = (int)(GameData.basicStudentSpeedOfClimbingThroughWindows * 10 / 12.0); | |||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | |||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||
| } | |||
| } | |||
| @@ -79,7 +79,7 @@ namespace Preparation.Utility | |||
| Klee = 3, | |||
| SpeedUpWhenLeavingGrass = 4, | |||
| Teacher = 5, | |||
| PSkill5 = 6 | |||
| StraightAStudent = 6 | |||
| } | |||
| public enum ActiveSkillType // 主动技能 | |||
| { | |||
| @@ -91,6 +91,7 @@ namespace Preparation.Utility | |||
| UseKnife = 5, | |||
| CanBeginToCharge = 6, | |||
| Punish = 7, | |||
| WriteAnswers = 8, | |||
| } | |||
| public enum PassiveSkillType | |||
| { | |||
| @@ -99,7 +100,7 @@ namespace Preparation.Utility | |||
| BecomeVampire = 2, | |||
| NuclearWeapon = 3, | |||
| SuperFast = 4, | |||
| ASkill4 = 5, | |||
| Meditate = 5, | |||
| ASkill5 = 6 | |||
| } | |||
| public enum BuffType // buff | |||
| @@ -176,6 +176,8 @@ namespace Server | |||
| return Protobuf.StudentType.Athlete; | |||
| case Preparation.Utility.CharacterType.Teacher: | |||
| return StudentType._2; | |||
| case CharacterType.StraightAStudent: | |||
| return StudentType._3; | |||
| default: | |||
| return Protobuf.StudentType.NullStudentType; | |||
| } | |||
| @@ -189,6 +191,8 @@ namespace Server | |||
| return Preparation.Utility.CharacterType.Athlete; | |||
| case StudentType._2: | |||
| return Preparation.Utility.CharacterType.Teacher; | |||
| case StudentType._3: | |||
| return CharacterType.StraightAStudent; | |||
| default: | |||
| return Preparation.Utility.CharacterType.Null; | |||
| } | |||
| @@ -12,6 +12,6 @@ start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --ch | |||
| ping -n 2 127.0.0.1 > NUL | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 1 --type 1 --occupation 1 | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 1 --type 1 --occupation 3 | |||
| ping -n 2 127.0.0.1 > NUL | |||