refactor: 🚧 refactor the skill fuction
tags/v0.1.0
| @@ -833,7 +833,7 @@ namespace Client | |||
| int i = 0; | |||
| foreach (var skill in occupation.ListOfIActiveSkill) | |||
| { | |||
| var iActiveSkill = SkillFactory.FindIActiveSkill(skill); | |||
| var iActiveSkill = SkillFactory.FindActiveSkill(skill); | |||
| coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD; | |||
| ++i; | |||
| } | |||
| @@ -848,7 +848,7 @@ namespace Client | |||
| int j = 0; | |||
| foreach (var skill in occupation1.ListOfIActiveSkill) | |||
| { | |||
| var iActiveSkill = SkillFactory.FindIActiveSkill(skill); | |||
| var iActiveSkill = SkillFactory.FindActiveSkill(skill); | |||
| coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; | |||
| ++j; | |||
| } | |||
| @@ -11,37 +11,32 @@ namespace GameClass.GameObj | |||
| private readonly IOccupation occupation; | |||
| public IOccupation Occupation => occupation; | |||
| private Dictionary<ActiveSkillType, int> timeUntilActiveSkillAvailable = new(); | |||
| public Dictionary<ActiveSkillType, int> TimeUntilActiveSkillAvailable => timeUntilActiveSkillAvailable; | |||
| private Dictionary<ActiveSkillType, ActiveSkill> activeSkillDictionary = new(); | |||
| public Dictionary<ActiveSkillType, ActiveSkill> ActiveSkillDictionary => activeSkillDictionary; | |||
| private Dictionary<ActiveSkillType, IActiveSkill> iActiveSkillDictionary = new(); | |||
| public Dictionary<ActiveSkillType, IActiveSkill> IActiveSkillDictionary => iActiveSkillDictionary; | |||
| public IActiveSkill FindIActiveSkill(ActiveSkillType activeSkillType) | |||
| public ActiveSkill FindActiveSkill(ActiveSkillType activeSkillType) | |||
| { | |||
| if (Occupation.ListOfIActiveSkill.Contains(activeSkillType)) | |||
| { | |||
| return IActiveSkillDictionary[activeSkillType]; | |||
| return ActiveSkillDictionary[activeSkillType]; | |||
| } | |||
| return new NullSkill(); | |||
| } | |||
| public bool SetTimeUntilActiveSkillAvailable(ActiveSkillType activeSkillType, int timeUntilActiveSkillAvailable) | |||
| { | |||
| if (TimeUntilActiveSkillAvailable.ContainsKey(activeSkillType)) | |||
| if (Occupation.ListOfIActiveSkill.Contains(activeSkillType)) | |||
| { | |||
| lock (gameObjLock) | |||
| this.timeUntilActiveSkillAvailable[activeSkillType] = (timeUntilActiveSkillAvailable > 0) ? timeUntilActiveSkillAvailable : 0; | |||
| ActiveSkillDictionary[activeSkillType].TimeUntilActiveSkillAvailable = (timeUntilActiveSkillAvailable > 0) ? timeUntilActiveSkillAvailable : 0; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| public bool AddTimeUntilActiveSkillAvailable(ActiveSkillType activeSkillType, int addTimeUntilActiveSkillAvailable) | |||
| { | |||
| if (TimeUntilActiveSkillAvailable.ContainsKey(activeSkillType)) | |||
| if (Occupation.ListOfIActiveSkill.Contains(activeSkillType)) | |||
| { | |||
| lock (gameObjLock) | |||
| this.timeUntilActiveSkillAvailable[activeSkillType] = (timeUntilActiveSkillAvailable[activeSkillType] + addTimeUntilActiveSkillAvailable > 0) ? timeUntilActiveSkillAvailable[activeSkillType] + addTimeUntilActiveSkillAvailable : 0; | |||
| ActiveSkillDictionary[activeSkillType].TimeUntilActiveSkillAvailable += addTimeUntilActiveSkillAvailable; | |||
| return true; | |||
| } | |||
| return false; | |||
| @@ -72,12 +67,10 @@ namespace GameClass.GameObj | |||
| foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) | |||
| { | |||
| this.IActiveSkillDictionary.Add(activeSkill, SkillFactory.FindIActiveSkill(activeSkill)); | |||
| this.TimeUntilActiveSkillAvailable.Add(activeSkill, 0); | |||
| this.ActiveSkillDictionary.Add(activeSkill, SkillFactory.FindActiveSkill(activeSkill)); | |||
| } | |||
| // UsePassiveSkill(); //创建player时开始被动技能,这一过程也可以放到gamestart时进行 | |||
| // 这可以放在AddPlayer中做 | |||
| // UsePassiveSkill(); //这一过程放到gamestart时进行 | |||
| Debugger.Output(this, "constructed!"); | |||
| } | |||
| @@ -9,7 +9,7 @@ namespace GameClass.GameObj | |||
| /// </summary> | |||
| public abstract class GameObj : IGameObj | |||
| { | |||
| private ReaderWriterLockSlim gameObjReaderWriterLock = new(); | |||
| private readonly ReaderWriterLockSlim gameObjReaderWriterLock = new(); | |||
| public ReaderWriterLockSlim GameObjReaderWriterLock => gameObjReaderWriterLock; | |||
| protected readonly object gameObjLock = new(); | |||
| public object GameLock => gameObjLock; | |||
| @@ -150,7 +150,12 @@ namespace GameClass.GameObj | |||
| whoLockOrOpen = null; | |||
| isOpen = true; | |||
| } | |||
| if (character != null) character.SetPlayerState(); | |||
| if (character != null) | |||
| { | |||
| lock (character.ActionLock) | |||
| if (character.PlayerState == PlayerStateType.OpeningTheDoor) | |||
| character.SetPlayerState(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -193,13 +193,12 @@ namespace GameClass.GameObj | |||
| { | |||
| if (playerID == person.ID) | |||
| { | |||
| if (person.CharacterType == CharacterType.TechOtaku && person.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed) | |||
| if (person.CharacterType == CharacterType.TechOtaku) | |||
| { | |||
| Debugger.Output(person, person.PlayerID.ToString()); | |||
| foreach (Character character in gameObjDict[GameObjType.Character]) | |||
| { | |||
| Debugger.Output(character, character.PlayerID.ToString()); | |||
| if (person.PlayerID + GameData.numOfPeople == character.PlayerID) | |||
| if (((UseRobot)person.FindActiveSkill(ActiveSkillType.UseRobot)).NowPlayerID == character.PlayerID) | |||
| { | |||
| player = character; | |||
| break; | |||
| @@ -162,13 +162,13 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| protected long moveSpeed; | |||
| protected int moveSpeed; | |||
| /// <summary> | |||
| /// 移动速度 | |||
| /// </summary> | |||
| public long MoveSpeed | |||
| public int MoveSpeed | |||
| { | |||
| get => Interlocked.Read(ref moveSpeed); | |||
| get => Interlocked.CompareExchange(ref moveSpeed, 0, 1); | |||
| set => Interlocked.Exchange(ref moveSpeed, value); | |||
| } | |||
| /// <summary> | |||
| @@ -21,11 +21,11 @@ namespace GameClass.GameObj | |||
| public abstract bool IsUsable(); | |||
| public abstract PropType GetPropType(); | |||
| public Gadget(XY initPos, int radius = GameData.PropRadius) : | |||
| public Gadget(XY initPos, int radius = GameData.propRadius) : | |||
| base(initPos, radius, GameObjType.Gadget) | |||
| { | |||
| this.canMove = false; | |||
| this.MoveSpeed = GameData.PropMoveSpeed; | |||
| this.MoveSpeed = GameData.propMoveSpeed; | |||
| } | |||
| } | |||
| public abstract class Tool : Gadget | |||
| @@ -13,7 +13,7 @@ namespace GameClass.GameObj | |||
| public abstract PropType GetPropType(); | |||
| public Item(XY initPos, int radius = GameData.PropRadius) : | |||
| public Item(XY initPos, int radius = GameData.propRadius) : | |||
| base(initPos, radius, GameObjType.Item) | |||
| { | |||
| this.canMove = false; | |||
| @@ -26,7 +26,7 @@ namespace Gaming | |||
| gameMap.Remove((GameObj)collisionObj); | |||
| } | |||
| } | |||
| if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | |||
| if (player.FindActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed == 1 && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | |||
| { | |||
| if (characterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge) > 0) | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); | |||
| @@ -117,7 +117,7 @@ namespace Gaming | |||
| if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) | |||
| gameMap.NumOfRepairedGenerators++; | |||
| if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) | |||
| player.SetPlayerState(); | |||
| player.SetPlayerState();//Num == player.StateNum | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0 | |||
| @@ -215,7 +215,7 @@ namespace Gaming | |||
| loopToDo: () => | |||
| { | |||
| if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) | |||
| playerTreated.SetPlayerState(); | |||
| playerTreated.SetPlayerState();// | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0 | |||
| @@ -426,7 +426,10 @@ namespace Gaming | |||
| if (!doorToLock.TryLock(player)) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.SetPlayerState(); | |||
| lock (player.ActionLock) | |||
| { | |||
| if (stateNum == player.StateNum) player.SetPlayerState(); | |||
| } | |||
| player.ThreadNum.Release(); | |||
| } | |||
| else | |||
| @@ -495,7 +498,10 @@ namespace Gaming | |||
| if (!doorToLock.TryOpen(player)) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.SetPlayerState(); | |||
| lock (player.ActionLock) | |||
| { | |||
| if (stateNum == player.StateNum) player.SetPlayerState(); | |||
| } | |||
| player.ThreadNum.Release(); | |||
| } | |||
| else | |||
| @@ -284,7 +284,7 @@ namespace Gaming | |||
| if (student.CharacterType == CharacterType.StraightAStudent) | |||
| { | |||
| ((WriteAnswers)student.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0; | |||
| ((WriteAnswers)student.FindActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0; | |||
| } | |||
| student.SetDegreeOfTreatment0(); | |||
| @@ -382,8 +382,8 @@ namespace Gaming | |||
| var parent = ((Golem)player).Parent; | |||
| if (parent != null && parent.CharacterType == CharacterType.TechOtaku) | |||
| { | |||
| ((SummonGolem)(parent.FindIActiveSkill(ActiveSkillType.SummonGolem))).GolemSummoned = null; | |||
| player.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false; | |||
| ((SummonGolem)(parent.FindActiveSkill(ActiveSkillType.SummonGolem))).DeleteGolem((int)(player.PlayerID - parent.PlayerID) / GameData.numOfPeople - 1); | |||
| //player.FindActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false; | |||
| } | |||
| return; | |||
| } | |||
| @@ -107,7 +107,7 @@ namespace Gaming | |||
| if (pickProp.GetPropType() != PropType.Null) | |||
| { | |||
| gameMap.Remove(pickProp); | |||
| gameMap.RemoveJustFromMap(pickProp); | |||
| //gameMap.Add(new Item(pickProp)); | |||
| return true; | |||
| } | |||
| @@ -15,7 +15,7 @@ namespace Gaming | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge); | |||
| ActiveSkill skill = player.FindActiveSkill(ActiveSkillType.CanBeginToCharge); | |||
| Debugger.Output(player, "can begin to charge!"); | |||
| @@ -31,7 +31,7 @@ namespace Gaming | |||
| public bool ShowTime(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime); | |||
| ActiveSkill skill = player.FindActiveSkill(ActiveSkillType.ShowTime); | |||
| return ActiveSkillEffect(skill, player, () => | |||
| { | |||
| @@ -93,7 +93,7 @@ namespace Gaming | |||
| public static bool BecomeInvisible(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.BecomeInvisible); | |||
| ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.BecomeInvisible); | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| player.AddScore(GameData.ScoreBecomeInvisible); | |||
| @@ -106,20 +106,21 @@ namespace Gaming | |||
| public bool UseRobot(Character player) | |||
| { | |||
| IGolem? golem = (IGolem?)(((SummonGolem)player.FindIActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned); | |||
| if ((!player.Commandable()) || ((SummonGolem)player.FindIActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned == null) return false; | |||
| /* | |||
| IGolem? golem = (IGolem?)(((SummonGolem)player.FindActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned); | |||
| if ((!player.Commandable()) || ((SummonGolem)player.FindActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned == null) return false; | |||
| Debugger.Output(player, "use robot!"); | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.UseRobot); | |||
| IActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.UseRobot); | |||
| activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true; | |||
| if (activeSkill.IsBeingUsed) player.SetPlayerState(PlayerStateType.UsingSkill); | |||
| else player.SetPlayerState(); | |||
| else player.SetPlayerState();*/ | |||
| return true; | |||
| } | |||
| public static bool JumpyBomb(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.JumpyBomb), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.JumpyBomb), player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.BombBomb; | |||
| Debugger.Output(player, "uses jumpybomb!"); | |||
| @@ -131,7 +132,7 @@ namespace Gaming | |||
| public bool WriteAnswers(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.WriteAnswers); | |||
| ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.WriteAnswers); | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| Generator? generator = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); | |||
| @@ -149,25 +150,30 @@ namespace Gaming | |||
| public bool SummonGolem(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.SummonGolem); | |||
| if (((SummonGolem)activeSkill).GolemSummoned != null) return false; | |||
| XY res = player.Position + new XY(player.FacingDirection, player.Radius * 2); | |||
| if (actionManager.moveEngine.CheckCollision(player, res) != null) | |||
| return false; | |||
| Golem? golem = (Golem?)characterManager.AddPlayer(res, player.TeamID, player.PlayerID + GameData.numOfPeople, CharacterType.Robot, player); | |||
| if (golem == null) return false; | |||
| ((SummonGolem)activeSkill).GolemSummoned = golem; | |||
| ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.SummonGolem); | |||
| long num = ((SummonGolem)activeSkill).AddGolem(); | |||
| if (num >= GameData.maxSummonedGolemNum) return false; | |||
| num = (num + 1) * GameData.numOfPeople + player.PlayerID; | |||
| /* if ((!player.Commandable())) return false; | |||
| XY res = player.Position + new XY(player.FacingDirection, player.Radius * 2); | |||
| if (actionManager.moveEngine.CheckCollision(player, res) != null) | |||
| return false; | |||
| Golem? golem = (Golem?)characterManager.AddPlayer(res, player.TeamID, player.PlayerID + GameData.numOfPeople, CharacterType.Robot, player); | |||
| if (golem == null) return false; | |||
| ((SummonGolem)activeSkill).GolemSummoned = golem; | |||
| */ | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| }, | |||
| () => | |||
| { }); | |||
| } | |||
| public static bool UseKnife(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.UseKnife), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.UseKnife), player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.FlyingKnife; | |||
| Debugger.Output(player, "uses flyingknife!"); | |||
| @@ -179,7 +185,7 @@ namespace Gaming | |||
| public bool Howl(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Howl), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Howl), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| @@ -207,7 +213,7 @@ namespace Gaming | |||
| public bool Punish(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Punish), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Punish), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| @@ -240,7 +246,7 @@ namespace Gaming | |||
| public bool Rouse(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Rouse), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Rouse), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| @@ -270,7 +276,7 @@ namespace Gaming | |||
| public bool Encourage(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Encourage), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Encourage), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| @@ -299,7 +305,7 @@ namespace Gaming | |||
| public bool Inspire(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Inspire), player, () => | |||
| return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Inspire), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| @@ -323,24 +329,23 @@ namespace Gaming | |||
| { }); | |||
| } | |||
| public static bool ActiveSkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill) | |||
| public static bool ActiveSkillEffect(ActiveSkill activeSkill, Character player, Action startSkill, Action endSkill) | |||
| { | |||
| lock (activeSkill.ActiveSkillLock) | |||
| lock (activeSkill.ActiveSkillUseLock) | |||
| { | |||
| ActiveSkillType activeSkillType = SkillFactory.FindActiveSkillType(activeSkill); | |||
| if (player.TimeUntilActiveSkillAvailable[activeSkillType] == 0) | |||
| if (activeSkill.TimeUntilActiveSkillAvailable == 0) | |||
| { | |||
| player.SetTimeUntilActiveSkillAvailable(activeSkillType, activeSkill.SkillCD); | |||
| activeSkill.TimeUntilActiveSkillAvailable = activeSkill.SkillCD; | |||
| new Thread | |||
| (() => | |||
| { | |||
| startSkill(); | |||
| activeSkill.IsBeingUsed = true; | |||
| activeSkill.IsBeingUsed = 1; | |||
| new FrameRateTaskExecutor<int>( | |||
| () => !player.IsRemoved, | |||
| () => | |||
| { | |||
| player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration); | |||
| activeSkill.TimeUntilActiveSkillAvailable -= (int)GameData.frameDuration; | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| @@ -353,14 +358,14 @@ namespace Gaming | |||
| .Start(); | |||
| endSkill(); | |||
| activeSkill.IsBeingUsed = false; | |||
| activeSkill.IsBeingUsed = 0; | |||
| Debugger.Output(player, "return to normal."); | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => player.TimeUntilActiveSkillAvailable[activeSkillType] > 0 && !player.IsRemoved, | |||
| loopCondition: () => activeSkill.TimeUntilActiveSkillAvailable > 0, | |||
| loopToDo: () => | |||
| { | |||
| player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration); | |||
| activeSkill.TimeUntilActiveSkillAvailable -= (int)GameData.frameDuration; | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0 | |||
| @@ -371,7 +376,7 @@ namespace Gaming | |||
| } | |||
| .Start(); | |||
| player.SetTimeUntilActiveSkillAvailable(activeSkillType, 0); | |||
| activeSkill.TimeUntilActiveSkillAvailable = 0; | |||
| Debugger.Output(player, "ActiveSkill is ready."); | |||
| } | |||
| ) | |||
| @@ -15,7 +15,7 @@ namespace Gaming // 被动技能开局时就释放,持续到游戏结束 | |||
| public void Meditate(Character player) | |||
| { | |||
| const int learningDegree = GameData.basicFixSpeed / 4; | |||
| WriteAnswers activeSkill = (WriteAnswers)player.FindIActiveSkill(ActiveSkillType.WriteAnswers); | |||
| WriteAnswers activeSkill = (WriteAnswers)player.FindActiveSkill(ActiveSkillType.WriteAnswers); | |||
| new Thread | |||
| ( | |||
| () => | |||
| @@ -7,7 +7,7 @@ namespace Preparation.Interface | |||
| public interface IMoveable : IGameObj | |||
| { | |||
| object ActionLock { get; } | |||
| public long MoveSpeed { get; } | |||
| public int MoveSpeed { get; } | |||
| public bool IsMoving { get; set; } | |||
| public bool IsRemoved { get; } | |||
| public bool IsAvailableForMove { get; } | |||
| @@ -315,13 +315,13 @@ namespace Preparation.Interface | |||
| } | |||
| public class TechOtaku : IStudentType | |||
| { | |||
| private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 0.75); | |||
| private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 288 / 300); | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = (int)(GameData.basicHp * 0.9); | |||
| public int MaxHp => maxHp; | |||
| private const int maxGamingAddiction = (int)(GameData.basicMaxGamingAddiction * 1.1); | |||
| private const int maxGamingAddiction = (int)(GameData.basicMaxGamingAddiction); | |||
| public int MaxGamingAddiction => maxGamingAddiction; | |||
| public BulletType InitBullet => BulletType.Null; | |||
| @@ -329,13 +329,13 @@ namespace Preparation.Interface | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.SummonGolem, ActiveSkillType.UseRobot }); | |||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); | |||
| public const int fixSpeed = (int)(GameData.basicFixSpeed * 1.1); | |||
| public const int fixSpeed = (int)(GameData.basicFixSpeed * 110 / 123); | |||
| public int FixSpeed => fixSpeed; | |||
| public const int treatSpeed = GameData.basicTreatSpeed * 9 / 10; | |||
| public const int treatSpeed = GameData.basicTreatSpeed; | |||
| public int TreatSpeed => treatSpeed; | |||
| public const double concealment = GameData.basicConcealment; | |||
| public const double concealment = GameData.basicConcealment * 1.1; | |||
| public double Concealment => concealment; | |||
| public const int alertnessRadius = (int)(GameData.basicStudentAlertnessRadius); | |||
| @@ -347,10 +347,10 @@ namespace Preparation.Interface | |||
| public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; | |||
| public int SpeedOfOpeningOrLocking => speedOfOpeningOrLocking; | |||
| public int speedOfClimbingThroughWindows = (int)(GameData.basicStudentSpeedOfClimbingThroughWindows * 3 / 4); | |||
| public int speedOfClimbingThroughWindows = (int)(GameData.basicStudentSpeedOfClimbingThroughWindows * 1100 / 1222); | |||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | |||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest * 1100 / 1250; | |||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||
| } | |||
| public class Sunshine : IStudentType | |||
| @@ -1,5 +1,6 @@ | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System.Threading; | |||
| namespace Preparation.Interface | |||
| { | |||
| @@ -13,241 +14,181 @@ namespace Preparation.Interface | |||
| { | |||
| public int SkillCD { get; } | |||
| public int DurationTime { get; } //技能持续时间 | |||
| public object ActiveSkillLock { get; } | |||
| public bool IsBeingUsed { get; set; } | |||
| public object ActiveSkillUseLock { get; } | |||
| public int IsBeingUsed { get; set; } | |||
| } | |||
| public class CanBeginToCharge : IActiveSkill | |||
| public abstract class ActiveSkill : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 2; | |||
| public int DurationTime => GameData.commonSkillTime * 3 / 10; | |||
| public abstract int SkillCD { get; } | |||
| public abstract int DurationTime { get; } | |||
| private readonly object activeSkillUseLock = new(); | |||
| public object ActiveSkillUseLock => activeSkillUseLock; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| private readonly object skillLock = new(); | |||
| public object SkillLock => skillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| private int timeUntilActiveSkillAvailable = 0; | |||
| public int TimeUntilActiveSkillAvailable | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| get => Interlocked.CompareExchange(ref timeUntilActiveSkillAvailable, 0, 1); | |||
| set | |||
| { | |||
| if (value < 0) value = 0; | |||
| else if (value > SkillCD) value = SkillCD; | |||
| Interlocked.Exchange(ref timeUntilActiveSkillAvailable, value); | |||
| } | |||
| } | |||
| } | |||
| public class BecomeInvisible : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 4 / 3; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| public int isBeingUsed = 0;//实为bool | |||
| public int IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| get => Interlocked.CompareExchange(ref isBeingUsed, 0, 1); | |||
| set => Interlocked.Exchange(ref isBeingUsed, value); | |||
| } | |||
| } | |||
| public class Punish : IActiveSkill | |||
| public class CanBeginToCharge : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public override int SkillCD => GameData.commonSkillCD * 2; | |||
| public override int DurationTime => GameData.commonSkillTime * 3 / 10; | |||
| } | |||
| public class Rouse : IActiveSkill | |||
| public class BecomeInvisible : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 4; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public override int SkillCD => GameData.commonSkillCD * 4 / 3; | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| public class Encourage : IActiveSkill | |||
| public class Punish : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 4; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class Inspire : IActiveSkill | |||
| public class Rouse : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 4; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public override int SkillCD => GameData.commonSkillCD * 4; | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class Howl : IActiveSkill | |||
| public class Encourage : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 25 / 30; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public override int SkillCD => GameData.commonSkillCD * 4; | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class ShowTime : IActiveSkill | |||
| public class Inspire : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 8 / 3; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| public override int SkillCD => GameData.commonSkillCD * 4; | |||
| public override int DurationTime => 0; | |||
| } | |||
| private readonly object commonSkillLock = new(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public class Howl : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 25 / 30; | |||
| public override int DurationTime => 0; | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public class ShowTime : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 8 / 3; | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| public class JumpyBomb : IActiveSkill | |||
| public class JumpyBomb : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 2; | |||
| public int DurationTime => GameData.commonSkillTime * 3 / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public override int SkillCD => GameData.commonSkillCD / 2; | |||
| public override int DurationTime => GameData.commonSkillTime * 3 / 10; | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| public class UseKnife : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override int DurationTime => GameData.commonSkillTime / 10; | |||
| } | |||
| public class UseKnife : IActiveSkill | |||
| public class UseRobot : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public override int SkillCD => GameData.commonSkillCD / 300; | |||
| public override int DurationTime => 0; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| private int nowPlayerID; | |||
| public int NowPlayerID | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| get => Interlocked.CompareExchange(ref nowPlayerID, 0, 1); | |||
| set => Interlocked.Exchange(ref nowPlayerID, value); | |||
| } | |||
| } | |||
| public class UseRobot : IActiveSkill | |||
| public class WriteAnswers : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 300; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override int DurationTime => 0; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| private int degreeOfMeditation = 0; | |||
| public int DegreeOfMeditation | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| get => Interlocked.CompareExchange(ref degreeOfMeditation, 0, 1); | |||
| set => Interlocked.Exchange(ref degreeOfMeditation, value); | |||
| } | |||
| } | |||
| public class WriteAnswers : IActiveSkill | |||
| public class SummonGolem : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public override int SkillCD => GameData.commonSkillCD * 4 / 3; | |||
| public override int DurationTime => 6; | |||
| private int degreeOfMeditation = 0; | |||
| public int DegreeOfMeditation | |||
| private bool[] golemIDArray = new bool[GameData.maxSummonedGolemNum] { false, false, false }; | |||
| public bool[] GolemIDArray | |||
| { | |||
| get => degreeOfMeditation; | |||
| set | |||
| get | |||
| { | |||
| lock (commonSkillLock) | |||
| { | |||
| degreeOfMeditation = value; | |||
| } | |||
| lock (SkillLock) { return golemIDArray; } | |||
| } | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| private int nowPtr = 0; | |||
| public int NowPtr | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| get | |||
| { | |||
| lock (SkillLock) { return nowPtr; } | |||
| } | |||
| } | |||
| } | |||
| public class SummonGolem : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD * 4 / 3; | |||
| public int DurationTime => 6; | |||
| private readonly object commonSkillLock = new(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| private IGolem? golemSummoned = null; | |||
| public IGolem? GolemSummoned | |||
| public int AddGolem() | |||
| { | |||
| get => golemSummoned; | |||
| set | |||
| lock (SkillLock) | |||
| { | |||
| lock (commonSkillLock) | |||
| { | |||
| golemSummoned = value; | |||
| } | |||
| if (nowPtr == GameData.maxSummonedGolemNum) return GameData.maxSummonedGolemNum; | |||
| int num = nowPtr; | |||
| golemIDArray[nowPtr] = true; | |||
| while ((++nowPtr) < GameData.maxSummonedGolemNum && golemIDArray[nowPtr]) ; | |||
| return num; | |||
| } | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| public void DeleteGolem(int num) | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| lock (SkillLock) | |||
| { | |||
| golemIDArray[num] = false; | |||
| if (num < nowPtr) | |||
| { | |||
| nowPtr = num; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| public class NullSkill : IActiveSkill | |||
| public class NullSkill : ActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| 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 = false; | |||
| } | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| public static class SkillFactory | |||
| { | |||
| public static IActiveSkill FindIActiveSkill(ActiveSkillType activeSkillType) | |||
| public static ActiveSkill FindActiveSkill(ActiveSkillType activeSkillType) | |||
| { | |||
| switch (activeSkillType) | |||
| { | |||
| @@ -92,10 +92,10 @@ namespace Preparation.Utility | |||
| public const int basicTreatSpeed = 100; | |||
| public const int basicFixSpeed = 123; | |||
| public const int basicSpeedOfOpeningOrLocking = 4000; | |||
| public const int basicSpeedOfOpeningOrLocking = 5000; | |||
| public const int basicStudentSpeedOfClimbingThroughWindows = 1222; | |||
| public const int basicGhostSpeedOfClimbingThroughWindows = 2540; | |||
| public const int basicSpeedOfOpenChest = 1000; | |||
| public const int basicSpeedOfOpenChest = 1250; | |||
| public const int basicHp = 3000000; // 初始血量 | |||
| public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间 | |||
| @@ -228,10 +228,12 @@ namespace Preparation.Utility | |||
| public const int checkIntervalWhenShowTime = 200; | |||
| public const int addAddictionPer100msWhenShowTime = 300; | |||
| public const int maxSummonedGolemNum = 3; | |||
| #endregion | |||
| #region 道具相关 | |||
| public const int PropRadius = numOfPosGridPerCell / 2; | |||
| public const int PropMoveSpeed = 3000; | |||
| public const int propRadius = characterRadius; | |||
| public const int propMoveSpeed = 3000; | |||
| public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell; | |||
| public const long PropProduceTime = 20000; | |||
| public const int PropDuration = 10000; | |||
| @@ -80,9 +80,9 @@ namespace Server | |||
| } | |||
| }; | |||
| foreach (var keyValue in player.TimeUntilActiveSkillAvailable) | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(keyValue.Value); | |||
| for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count; ++i) | |||
| foreach (var keyValue in player.ActiveSkillDictionary) | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(keyValue.Value.TimeUntilActiveSkillAvailable); | |||
| for (int i = 0; i < GameData.maxNumOfSkill - player.ActiveSkillDictionary.Count; ++i) | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(-1); | |||
| foreach (var value in player.PropInventory) | |||
| @@ -121,10 +121,9 @@ namespace Server | |||
| BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer) | |||
| } | |||
| }; | |||
| foreach (var keyValue in player.TimeUntilActiveSkillAvailable) | |||
| msg.TrickerMessage.TimeUntilSkillAvailable.Add(keyValue.Value); | |||
| for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count; ++i) | |||
| foreach (var keyValue in player.ActiveSkillDictionary) | |||
| msg.TrickerMessage.TimeUntilSkillAvailable.Add(keyValue.Value.TimeUntilActiveSkillAvailable); | |||
| for (int i = 0; i < GameData.maxNumOfSkill - player.ActiveSkillDictionary.Count; ++i) | |||
| msg.TrickerMessage.TimeUntilSkillAvailable.Add(-1); | |||
| foreach (var value in player.PropInventory) | |||