| @@ -836,7 +836,7 @@ namespace Client | |||
| foreach (var skill in occupation.ListOfIActiveSkill) | |||
| { | |||
| var iActiveSkill = SkillFactory.FindActiveSkill(skill); | |||
| coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD; | |||
| coolTime[i, obj.PlayerId] = (int)(iActiveSkill.SkillCD.GetCD()); | |||
| ++i; | |||
| } | |||
| isDataFixed[obj.PlayerId] = true; | |||
| @@ -844,14 +844,14 @@ namespace Client | |||
| } | |||
| foreach (var obj in listOfButcher) | |||
| { | |||
| if (obj.PlayerId < GameData.numOfStudent && !isDataFixed[obj.PlayerId]) | |||
| if (obj.PlayerId < GameData.numOfPeople && !isDataFixed[obj.PlayerId]) | |||
| { | |||
| IGhostType occupation1 = (IGhostType)OccupationFactory.FindIOccupation(Transformation.ToTrickerType(obj.TrickerType)); | |||
| int j = 0; | |||
| foreach (var skill in occupation1.ListOfIActiveSkill) | |||
| { | |||
| var iActiveSkill = SkillFactory.FindActiveSkill(skill); | |||
| coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; | |||
| coolTime[j, GameData.numOfStudent] = (int)(iActiveSkill.SkillCD.GetCD()); | |||
| ++j; | |||
| } | |||
| isDataFixed[obj.PlayerId] = true; | |||
| @@ -513,7 +513,7 @@ namespace Gaming | |||
| { | |||
| if ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) != null) | |||
| return false; | |||
| if (doorToLock.LockDegree.Add(GameData.checkInterval * player.SpeedOfOpeningOrLocking) >= GameData.basicSpeedOfOpeningOrLocking) | |||
| if (doorToLock.LockDegree.Add(GameData.checkInterval * player.SpeedOfOpeningOrLocking) >= GameData.degreeOfLockingOrOpeningTheDoor) | |||
| return false; | |||
| return true; | |||
| }, | |||
| @@ -499,7 +499,7 @@ namespace Gaming | |||
| { | |||
| lock (activeSkill.ActiveSkillUseLock) | |||
| { | |||
| if (activeSkill.StartSkill()) | |||
| if (activeSkill.SkillCD.TryUse()) | |||
| { | |||
| new Thread | |||
| (() => | |||
| @@ -13,7 +13,7 @@ namespace Preparation.Interface | |||
| } | |||
| public interface IActiveSkill : ISkill | |||
| { | |||
| public int SkillCD { get; } | |||
| public LongProgressCoolingDownByCD SkillCD { get; } | |||
| public int DurationTime { get; } //技能持续时间 | |||
| public object ActiveSkillUseLock { get; } | |||
| public bool IsBeingUsed { get; set; } | |||
| @@ -21,7 +21,7 @@ namespace Preparation.Interface | |||
| public abstract class ActiveSkill : IActiveSkill | |||
| { | |||
| public abstract int SkillCD { get; } | |||
| public abstract LongProgressCoolingDownByCD SkillCD { get; } | |||
| public abstract int DurationTime { get; } | |||
| private readonly object activeSkillUseLock = new(); | |||
| @@ -30,28 +30,6 @@ namespace Preparation.Interface | |||
| private readonly object skillLock = new(); | |||
| public object SkillLock => skillLock; | |||
| private long startTime = Environment.TickCount64 - 600000; | |||
| public long StartTime | |||
| { | |||
| get | |||
| { | |||
| lock (skillLock) | |||
| return startTime; | |||
| } | |||
| } | |||
| public bool StartSkill() | |||
| { | |||
| lock (skillLock) | |||
| { | |||
| if (Environment.TickCount64 - startTime >= SkillCD) | |||
| { | |||
| startTime = Environment.TickCount64; | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| public int isBeingUsed = 0;//实为bool | |||
| public bool IsBeingUsed | |||
| { | |||
| @@ -62,79 +40,79 @@ namespace Preparation.Interface | |||
| public class CanBeginToCharge : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 2; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 2); | |||
| public override int DurationTime => GameData.commonSkillTime * 3 / 10; | |||
| } | |||
| public class BecomeInvisible : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 4 / 3; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4 / 3); | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| public class Punish : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 45 / 30; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 45 / 30); | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class HaveTea : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 3; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 3); | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class Rouse : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 4; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4); | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class Encourage : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 4; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4); | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class Inspire : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 4; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4); | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class Howl : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 25 / 30; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 25 / 30); | |||
| public override int DurationTime => 0; | |||
| } | |||
| public class ShowTime : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 8 / 3; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 8 / 3); | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| public class JumpyBomb : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD / 2; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD / 2); | |||
| public override int DurationTime => GameData.commonSkillTime * 3 / 10; | |||
| } | |||
| public class SparksNSplash : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 45 / 30; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 45 / 30); | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| public class UseKnife : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD); | |||
| public override int DurationTime => GameData.commonSkillTime / 10; | |||
| } | |||
| public class UseRobot : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD / 300; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD / 300); | |||
| public override int DurationTime => 0; | |||
| private int nowPlayerID; | |||
| @@ -171,7 +149,7 @@ namespace Preparation.Interface | |||
| public class WriteAnswers : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD); | |||
| public override int DurationTime => 0; | |||
| private AtomicInt degreeOfMeditation = new(0); | |||
| @@ -180,7 +158,7 @@ namespace Preparation.Interface | |||
| public class SummonGolem : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD * 4 / 3; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4 / 3); | |||
| public override int DurationTime => 6000; | |||
| private int[] golemStateArray = new int[GameData.maxSummonedGolemNum] { 0, 0, 0 }; | |||
| @@ -233,7 +211,7 @@ namespace Preparation.Interface | |||
| public class NullSkill : ActiveSkill | |||
| { | |||
| public override int SkillCD => GameData.commonSkillCD; | |||
| public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD); | |||
| public override int DurationTime => GameData.commonSkillTime; | |||
| } | |||
| @@ -504,7 +504,7 @@ namespace Preparation.Utility | |||
| } | |||
| /// <summary> | |||
| /// 一个保证在[0,maxNum],每CDms自动更新的可变int,支持可变的CD、maxNum(请确保大于0) | |||
| /// 一个保证在[0,maxNum],每CDms自动+1的int,支持可变的CD、maxNum(请确保大于0) | |||
| /// </summary> | |||
| public class IntNumUpdateByCD | |||
| { | |||
| @@ -679,4 +679,100 @@ namespace Preparation.Utility | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 一个每CDms自动更新冷却的bool,支持可变的无锁CD,不支持查看当前进度,初始为True | |||
| /// </summary> | |||
| public class BoolCoolingDownByCD | |||
| { | |||
| private long cd; | |||
| private long nextUpdateTime = 0; | |||
| public BoolCoolingDownByCD(int cd) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); | |||
| this.cd = cd; | |||
| } | |||
| public BoolCoolingDownByCD(long cd) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); | |||
| this.cd = cd; | |||
| } | |||
| public BoolCoolingDownByCD(long cd, long startTime) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); | |||
| this.cd = cd; | |||
| this.nextUpdateTime = startTime; | |||
| } | |||
| public long GetCD() => Interlocked.Read(ref cd); | |||
| public bool TryUse() | |||
| { | |||
| long needTime = Interlocked.Exchange(ref nextUpdateTime, long.MaxValue); | |||
| if (needTime <= Environment.TickCount64) | |||
| { | |||
| Interlocked.Exchange(ref nextUpdateTime, Environment.TickCount64 + Interlocked.Read(ref cd)); | |||
| return true; | |||
| } | |||
| Interlocked.Exchange(ref nextUpdateTime, needTime); | |||
| return false; | |||
| } | |||
| public void SetCD(int cd) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:SetReturnOri IntNumUpdateByCD.cd to " + cd.ToString() + "."); | |||
| Interlocked.Exchange(ref this.cd, cd); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 一个每CDms自动更新的进度条,支持可变的CD,初始为满 | |||
| /// </summary> | |||
| public class LongProgressCoolingDownByCD | |||
| { | |||
| private int isusing = 0; | |||
| private long cd; | |||
| private long nextUpdateTime = 0; | |||
| public LongProgressCoolingDownByCD(int cd) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); | |||
| this.cd = cd; | |||
| } | |||
| public LongProgressCoolingDownByCD(long cd) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); | |||
| this.cd = cd; | |||
| } | |||
| public LongProgressCoolingDownByCD(long cd, long startTime) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); | |||
| this.cd = cd; | |||
| this.nextUpdateTime = startTime; | |||
| } | |||
| public long GetRemainingTime() | |||
| { | |||
| long v = Interlocked.Read(ref nextUpdateTime) - Environment.TickCount64; | |||
| return v < 0 ? 0 : v; | |||
| } | |||
| public long GetCD() => Interlocked.Read(ref cd); | |||
| public bool TryUse() | |||
| { | |||
| if (Interlocked.Exchange(ref isusing, 1) == 1) return false; | |||
| long needTime = Interlocked.Read(ref nextUpdateTime); | |||
| if (needTime <= Environment.TickCount64) | |||
| { | |||
| Interlocked.Exchange(ref nextUpdateTime, Environment.TickCount64 + Interlocked.Read(ref cd)); | |||
| Interlocked.Exchange(ref isusing, 0); | |||
| return true; | |||
| } | |||
| Interlocked.Exchange(ref isusing, 0); | |||
| return false; | |||
| } | |||
| public void SetCD(int cd) | |||
| { | |||
| if (cd <= 1) Debugger.Output("Bug:SetReturnOri IntNumUpdateByCD.cd to " + cd.ToString() + "."); | |||
| Interlocked.Exchange(ref this.cd, cd); | |||
| } | |||
| } | |||
| } | |||
| @@ -2,6 +2,7 @@ using Protobuf; | |||
| using GameClass.GameObj; | |||
| using Preparation.Utility; | |||
| using Gaming; | |||
| using Preparation.Interface; | |||
| namespace Server | |||
| { | |||
| @@ -81,10 +82,8 @@ namespace Server | |||
| }; | |||
| foreach (var keyValue in player.ActiveSkillDictionary) | |||
| { | |||
| int progress = (int)((keyValue.Value.StartTime - time) + keyValue.Value.SkillCD); | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(progress < 0 ? 0 : progress); | |||
| } | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(keyValue.Value.SkillCD.GetRemainingTime()); | |||
| for (int i = 0; i < GameData.maxNumOfSkill - player.ActiveSkillDictionary.Count; ++i) | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(-1); | |||
| @@ -124,11 +123,9 @@ namespace Server | |||
| BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer) | |||
| } | |||
| }; | |||
| foreach (var keyValue in player.ActiveSkillDictionary) | |||
| { | |||
| int progress = (int)(keyValue.Value.SkillCD + (keyValue.Value.StartTime - time)); | |||
| msg.TrickerMessage.TimeUntilSkillAvailable.Add(progress < 0 ? 0 : progress); | |||
| } | |||
| msg.TrickerMessage.TimeUntilSkillAvailable.Add(keyValue.Value.SkillCD.GetRemainingTime()); | |||
| for (int i = 0; i < GameData.maxNumOfSkill - player.ActiveSkillDictionary.Count; ++i) | |||
| msg.TrickerMessage.TimeUntilSkillAvailable.Add(-1); | |||