Browse Source

Merge pull request #550 from shangfengh/new

refactor: 🚧 refactor the skill fuction
tags/v0.1.0
Changli Tang GitHub 2 years ago
parent
commit
a0bbe2f09f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 211 additions and 261 deletions
  1. +2
    -2
      logic/Client/MainWindow.xaml.cs
  2. +10
    -17
      logic/GameClass/GameObj/Character/Character.Skill.cs
  3. +1
    -1
      logic/GameClass/GameObj/GameObj.cs
  4. +6
    -1
      logic/GameClass/GameObj/Map/Door.cs
  5. +2
    -3
      logic/GameClass/GameObj/Map/Map.cs
  6. +3
    -3
      logic/GameClass/GameObj/Moveable.cs
  7. +2
    -2
      logic/GameClass/GameObj/Prop/Gadget.cs
  8. +1
    -1
      logic/GameClass/GameObj/Prop/Item.cs
  9. +11
    -5
      logic/Gaming/ActionManager.cs
  10. +3
    -3
      logic/Gaming/CharacterManager.cs
  11. +1
    -1
      logic/Gaming/PropManager.cs
  12. +40
    -35
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  13. +1
    -1
      logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs
  14. +1
    -1
      logic/Preparation/Interface/IMoveable.cs
  15. +7
    -7
      logic/Preparation/Interface/IOccupation.cs
  16. +108
    -167
      logic/Preparation/Interface/ISkill.cs
  17. +6
    -4
      logic/Preparation/Utility/GameData.cs
  18. +6
    -7
      logic/Server/CopyInfo.cs

+ 2
- 2
logic/Client/MainWindow.xaml.cs View File

@@ -833,7 +833,7 @@ namespace Client
int i = 0; int i = 0;
foreach (var skill in occupation.ListOfIActiveSkill) foreach (var skill in occupation.ListOfIActiveSkill)
{ {
var iActiveSkill = SkillFactory.FindIActiveSkill(skill);
var iActiveSkill = SkillFactory.FindActiveSkill(skill);
coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD; coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD;
++i; ++i;
} }
@@ -848,7 +848,7 @@ namespace Client
int j = 0; int j = 0;
foreach (var skill in occupation1.ListOfIActiveSkill) foreach (var skill in occupation1.ListOfIActiveSkill)
{ {
var iActiveSkill = SkillFactory.FindIActiveSkill(skill);
var iActiveSkill = SkillFactory.FindActiveSkill(skill);
coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD;
++j; ++j;
} }


+ 10
- 17
logic/GameClass/GameObj/Character/Character.Skill.cs View File

@@ -11,37 +11,32 @@ namespace GameClass.GameObj
private readonly IOccupation occupation; private readonly IOccupation occupation;
public IOccupation Occupation => 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)) if (Occupation.ListOfIActiveSkill.Contains(activeSkillType))
{ {
return IActiveSkillDictionary[activeSkillType];
return ActiveSkillDictionary[activeSkillType];
} }
return new NullSkill(); return new NullSkill();
} }


public bool SetTimeUntilActiveSkillAvailable(ActiveSkillType activeSkillType, int timeUntilActiveSkillAvailable) 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 true;
} }
return false; return false;
} }
public bool AddTimeUntilActiveSkillAvailable(ActiveSkillType activeSkillType, int addTimeUntilActiveSkillAvailable) 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 true;
} }
return false; return false;
@@ -72,12 +67,10 @@ namespace GameClass.GameObj


foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) 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!"); Debugger.Output(this, "constructed!");
} }


+ 1
- 1
logic/GameClass/GameObj/GameObj.cs View File

@@ -9,7 +9,7 @@ namespace GameClass.GameObj
/// </summary> /// </summary>
public abstract class GameObj : IGameObj public abstract class GameObj : IGameObj
{ {
private ReaderWriterLockSlim gameObjReaderWriterLock = new();
private readonly ReaderWriterLockSlim gameObjReaderWriterLock = new();
public ReaderWriterLockSlim GameObjReaderWriterLock => gameObjReaderWriterLock; public ReaderWriterLockSlim GameObjReaderWriterLock => gameObjReaderWriterLock;
protected readonly object gameObjLock = new(); protected readonly object gameObjLock = new();
public object GameLock => gameObjLock; public object GameLock => gameObjLock;


+ 6
- 1
logic/GameClass/GameObj/Map/Door.cs View File

@@ -150,7 +150,12 @@ namespace GameClass.GameObj
whoLockOrOpen = null; whoLockOrOpen = null;
isOpen = true; isOpen = true;
} }
if (character != null) character.SetPlayerState();
if (character != null)
{
lock (character.ActionLock)
if (character.PlayerState == PlayerStateType.OpeningTheDoor)
character.SetPlayerState();
}
} }
} }
} }

+ 2
- 3
logic/GameClass/GameObj/Map/Map.cs View File

@@ -193,13 +193,12 @@ namespace GameClass.GameObj
{ {
if (playerID == person.ID) 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()); Debugger.Output(person, person.PlayerID.ToString());
foreach (Character character in gameObjDict[GameObjType.Character]) 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; player = character;
break; break;


+ 3
- 3
logic/GameClass/GameObj/Moveable.cs View File

@@ -162,13 +162,13 @@ namespace GameClass.GameObj
} }
} }


protected long moveSpeed;
protected int moveSpeed;
/// <summary> /// <summary>
/// 移动速度 /// 移动速度
/// </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); set => Interlocked.Exchange(ref moveSpeed, value);
} }
/// <summary> /// <summary>


+ 2
- 2
logic/GameClass/GameObj/Prop/Gadget.cs View File

@@ -21,11 +21,11 @@ namespace GameClass.GameObj
public abstract bool IsUsable(); public abstract bool IsUsable();
public abstract PropType GetPropType(); 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) base(initPos, radius, GameObjType.Gadget)
{ {
this.canMove = false; this.canMove = false;
this.MoveSpeed = GameData.PropMoveSpeed;
this.MoveSpeed = GameData.propMoveSpeed;
} }
} }
public abstract class Tool : Gadget public abstract class Tool : Gadget


+ 1
- 1
logic/GameClass/GameObj/Prop/Item.cs View File

@@ -13,7 +13,7 @@ namespace GameClass.GameObj


public abstract PropType GetPropType(); 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) base(initPos, radius, GameObjType.Item)
{ {
this.canMove = false; this.canMove = false;


+ 11
- 5
logic/Gaming/ActionManager.cs View File

@@ -26,7 +26,7 @@ namespace Gaming
gameMap.Remove((GameObj)collisionObj); 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) if (characterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge) > 0)
player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge));
@@ -117,7 +117,7 @@ namespace Gaming
if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player))
gameMap.NumOfRepairedGenerators++; gameMap.NumOfRepairedGenerators++;
if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator)
player.SetPlayerState();
player.SetPlayerState();//Num == player.StateNum
}, },
timeInterval: GameData.frameDuration, timeInterval: GameData.frameDuration,
finallyReturn: () => 0 finallyReturn: () => 0
@@ -215,7 +215,7 @@ namespace Gaming
loopToDo: () => loopToDo: () =>
{ {
if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player))
playerTreated.SetPlayerState();
playerTreated.SetPlayerState();//
}, },
timeInterval: GameData.frameDuration, timeInterval: GameData.frameDuration,
finallyReturn: () => 0 finallyReturn: () => 0
@@ -426,7 +426,10 @@ namespace Gaming
if (!doorToLock.TryLock(player)) if (!doorToLock.TryLock(player))
{ {
player.ReleaseTool(propType); player.ReleaseTool(propType);
player.SetPlayerState();
lock (player.ActionLock)
{
if (stateNum == player.StateNum) player.SetPlayerState();
}
player.ThreadNum.Release(); player.ThreadNum.Release();
} }
else else
@@ -495,7 +498,10 @@ namespace Gaming
if (!doorToLock.TryOpen(player)) if (!doorToLock.TryOpen(player))
{ {
player.ReleaseTool(propType); player.ReleaseTool(propType);
player.SetPlayerState();
lock (player.ActionLock)
{
if (stateNum == player.StateNum) player.SetPlayerState();
}
player.ThreadNum.Release(); player.ThreadNum.Release();
} }
else else


+ 3
- 3
logic/Gaming/CharacterManager.cs View File

@@ -284,7 +284,7 @@ namespace Gaming


if (student.CharacterType == CharacterType.StraightAStudent) if (student.CharacterType == CharacterType.StraightAStudent)
{ {
((WriteAnswers)student.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0;
((WriteAnswers)student.FindActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0;
} }
student.SetDegreeOfTreatment0(); student.SetDegreeOfTreatment0();


@@ -382,8 +382,8 @@ namespace Gaming
var parent = ((Golem)player).Parent; var parent = ((Golem)player).Parent;
if (parent != null && parent.CharacterType == CharacterType.TechOtaku) 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; return;
} }


+ 1
- 1
logic/Gaming/PropManager.cs View File

@@ -107,7 +107,7 @@ namespace Gaming


if (pickProp.GetPropType() != PropType.Null) if (pickProp.GetPropType() != PropType.Null)
{ {
gameMap.Remove(pickProp);
gameMap.RemoveJustFromMap(pickProp);
//gameMap.Add(new Item(pickProp)); //gameMap.Add(new Item(pickProp));
return true; return true;
} }


+ 40
- 35
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -15,7 +15,7 @@ namespace Gaming
{ {


if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge);
ActiveSkill skill = player.FindActiveSkill(ActiveSkillType.CanBeginToCharge);
Debugger.Output(player, "can begin to charge!"); Debugger.Output(player, "can begin to charge!");




@@ -31,7 +31,7 @@ namespace Gaming
public bool ShowTime(Character player) public bool ShowTime(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime);
ActiveSkill skill = player.FindActiveSkill(ActiveSkillType.ShowTime);


return ActiveSkillEffect(skill, player, () => return ActiveSkillEffect(skill, player, () =>
{ {
@@ -93,7 +93,7 @@ namespace Gaming
public static bool BecomeInvisible(Character player) public static bool BecomeInvisible(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.BecomeInvisible);
ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.BecomeInvisible);
return ActiveSkillEffect(activeSkill, player, () => return ActiveSkillEffect(activeSkill, player, () =>
{ {
player.AddScore(GameData.ScoreBecomeInvisible); player.AddScore(GameData.ScoreBecomeInvisible);
@@ -106,20 +106,21 @@ namespace Gaming


public bool UseRobot(Character player) 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!"); Debugger.Output(player, "use robot!");
IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.UseRobot);
IActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.UseRobot);
activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true; activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true;
if (activeSkill.IsBeingUsed) player.SetPlayerState(PlayerStateType.UsingSkill); if (activeSkill.IsBeingUsed) player.SetPlayerState(PlayerStateType.UsingSkill);
else player.SetPlayerState();
else player.SetPlayerState();*/
return true; return true;
} }


public static bool JumpyBomb(Character player) public static bool JumpyBomb(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.JumpyBomb), player, () =>
return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.JumpyBomb), player, () =>
{ {
player.BulletOfPlayer = BulletType.BombBomb; player.BulletOfPlayer = BulletType.BombBomb;
Debugger.Output(player, "uses jumpybomb!"); Debugger.Output(player, "uses jumpybomb!");
@@ -131,7 +132,7 @@ namespace Gaming
public bool WriteAnswers(Character player) public bool WriteAnswers(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.WriteAnswers);
ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.WriteAnswers);
return ActiveSkillEffect(activeSkill, player, () => return ActiveSkillEffect(activeSkill, player, () =>
{ {
Generator? generator = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); Generator? generator = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator);
@@ -149,25 +150,30 @@ namespace Gaming


public bool SummonGolem(Character player) 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, () => return ActiveSkillEffect(activeSkill, player, () =>
{ {
}, },
() => () =>
{ }); { });

} }


public static bool UseKnife(Character 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; player.BulletOfPlayer = BulletType.FlyingKnife;
Debugger.Output(player, "uses flyingknife!"); Debugger.Output(player, "uses flyingknife!");
@@ -179,7 +185,7 @@ namespace Gaming
public bool Howl(Character player) public bool Howl(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Howl), player, () =>
return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Howl), player, () =>
{ {
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try try
@@ -207,7 +213,7 @@ namespace Gaming
public bool Punish(Character player) public bool Punish(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Punish), player, () =>
return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Punish), player, () =>
{ {
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try try
@@ -240,7 +246,7 @@ namespace Gaming
public bool Rouse(Character player) public bool Rouse(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Rouse), player, () =>
return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Rouse), player, () =>
{ {
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try try
@@ -270,7 +276,7 @@ namespace Gaming
public bool Encourage(Character player) public bool Encourage(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Encourage), player, () =>
return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Encourage), player, () =>
{ {
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try try
@@ -299,7 +305,7 @@ namespace Gaming
public bool Inspire(Character player) public bool Inspire(Character player)
{ {
if ((!player.Commandable())) return false; if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Inspire), player, () =>
return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.Inspire), player, () =>
{ {
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try 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 new Thread
(() => (() =>
{ {
startSkill(); startSkill();
activeSkill.IsBeingUsed = true;
activeSkill.IsBeingUsed = 1;
new FrameRateTaskExecutor<int>( new FrameRateTaskExecutor<int>(
() => !player.IsRemoved, () => !player.IsRemoved,
() => () =>
{ {
player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration);
activeSkill.TimeUntilActiveSkillAvailable -= (int)GameData.frameDuration;
}, },
timeInterval: GameData.frameDuration, timeInterval: GameData.frameDuration,
() => 0, () => 0,
@@ -353,14 +358,14 @@ namespace Gaming
.Start(); .Start();


endSkill(); endSkill();
activeSkill.IsBeingUsed = false;
activeSkill.IsBeingUsed = 0;
Debugger.Output(player, "return to normal."); Debugger.Output(player, "return to normal.");


new FrameRateTaskExecutor<int>( new FrameRateTaskExecutor<int>(
loopCondition: () => player.TimeUntilActiveSkillAvailable[activeSkillType] > 0 && !player.IsRemoved,
loopCondition: () => activeSkill.TimeUntilActiveSkillAvailable > 0,
loopToDo: () => loopToDo: () =>
{ {
player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration);
activeSkill.TimeUntilActiveSkillAvailable -= (int)GameData.frameDuration;
}, },
timeInterval: GameData.frameDuration, timeInterval: GameData.frameDuration,
finallyReturn: () => 0 finallyReturn: () => 0
@@ -371,7 +376,7 @@ namespace Gaming
} }
.Start(); .Start();


player.SetTimeUntilActiveSkillAvailable(activeSkillType, 0);
activeSkill.TimeUntilActiveSkillAvailable = 0;
Debugger.Output(player, "ActiveSkill is ready."); Debugger.Output(player, "ActiveSkill is ready.");
} }
) )


+ 1
- 1
logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs View File

@@ -15,7 +15,7 @@ namespace Gaming // 被动技能开局时就释放,持续到游戏结束
public void Meditate(Character player) public void Meditate(Character player)
{ {
const int learningDegree = GameData.basicFixSpeed / 4; const int learningDegree = GameData.basicFixSpeed / 4;
WriteAnswers activeSkill = (WriteAnswers)player.FindIActiveSkill(ActiveSkillType.WriteAnswers);
WriteAnswers activeSkill = (WriteAnswers)player.FindActiveSkill(ActiveSkillType.WriteAnswers);
new Thread new Thread
( (
() => () =>


+ 1
- 1
logic/Preparation/Interface/IMoveable.cs View File

@@ -7,7 +7,7 @@ namespace Preparation.Interface
public interface IMoveable : IGameObj public interface IMoveable : IGameObj
{ {
object ActionLock { get; } object ActionLock { get; }
public long MoveSpeed { get; }
public int MoveSpeed { get; }
public bool IsMoving { get; set; } public bool IsMoving { get; set; }
public bool IsRemoved { get; } public bool IsRemoved { get; }
public bool IsAvailableForMove { get; } public bool IsAvailableForMove { get; }


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

@@ -315,13 +315,13 @@ namespace Preparation.Interface
} }
public class TechOtaku : IStudentType 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; public int MoveSpeed => moveSpeed;


private const int maxHp = (int)(GameData.basicHp * 0.9); private const int maxHp = (int)(GameData.basicHp * 0.9);
public int MaxHp => maxHp; 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 int MaxGamingAddiction => maxGamingAddiction;


public BulletType InitBullet => BulletType.Null; 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<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.SummonGolem, ActiveSkillType.UseRobot });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); 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 int FixSpeed => fixSpeed;


public const int treatSpeed = GameData.basicTreatSpeed * 9 / 10;
public const int treatSpeed = GameData.basicTreatSpeed;
public int TreatSpeed => treatSpeed; public int TreatSpeed => treatSpeed;


public const double concealment = GameData.basicConcealment;
public const double concealment = GameData.basicConcealment * 1.1;
public double Concealment => concealment; public double Concealment => concealment;


public const int alertnessRadius = (int)(GameData.basicStudentAlertnessRadius); public const int alertnessRadius = (int)(GameData.basicStudentAlertnessRadius);
@@ -347,10 +347,10 @@ namespace Preparation.Interface
public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking;
public int SpeedOfOpeningOrLocking => speedOfOpeningOrLocking; 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 SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows;


public int speedOfOpenChest = GameData.basicSpeedOfOpenChest;
public int speedOfOpenChest = GameData.basicSpeedOfOpenChest * 1100 / 1250;
public int SpeedOfOpenChest => speedOfOpenChest; public int SpeedOfOpenChest => speedOfOpenChest;
} }
public class Sunshine : IStudentType public class Sunshine : IStudentType


+ 108
- 167
logic/Preparation/Interface/ISkill.cs View File

@@ -1,5 +1,6 @@
using Preparation.Interface; using Preparation.Interface;
using Preparation.Utility; using Preparation.Utility;
using System.Threading;


namespace Preparation.Interface namespace Preparation.Interface
{ {
@@ -13,241 +14,181 @@ namespace Preparation.Interface
{ {
public int SkillCD { get; } public int SkillCD { get; }
public int DurationTime { 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 class SkillFactory
{ {
public static IActiveSkill FindIActiveSkill(ActiveSkillType activeSkillType)
public static ActiveSkill FindActiveSkill(ActiveSkillType activeSkillType)
{ {
switch (activeSkillType) switch (activeSkillType)
{ {


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

@@ -92,10 +92,10 @@ namespace Preparation.Utility


public const int basicTreatSpeed = 100; public const int basicTreatSpeed = 100;
public const int basicFixSpeed = 123; public const int basicFixSpeed = 123;
public const int basicSpeedOfOpeningOrLocking = 4000;
public const int basicSpeedOfOpeningOrLocking = 5000;
public const int basicStudentSpeedOfClimbingThroughWindows = 1222; public const int basicStudentSpeedOfClimbingThroughWindows = 1222;
public const int basicGhostSpeedOfClimbingThroughWindows = 2540; public const int basicGhostSpeedOfClimbingThroughWindows = 2540;
public const int basicSpeedOfOpenChest = 1000;
public const int basicSpeedOfOpenChest = 1250;


public const int basicHp = 3000000; // 初始血量 public const int basicHp = 3000000; // 初始血量
public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间 public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间
@@ -228,10 +228,12 @@ namespace Preparation.Utility


public const int checkIntervalWhenShowTime = 200; public const int checkIntervalWhenShowTime = 200;
public const int addAddictionPer100msWhenShowTime = 300; public const int addAddictionPer100msWhenShowTime = 300;

public const int maxSummonedGolemNum = 3;
#endregion #endregion
#region 道具相关 #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 int PropMaxMoveDistance = 15 * numOfPosGridPerCell;
public const long PropProduceTime = 20000; public const long PropProduceTime = 20000;
public const int PropDuration = 10000; public const int PropDuration = 10000;


+ 6
- 7
logic/Server/CopyInfo.cs View File

@@ -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); msg.StudentMessage.TimeUntilSkillAvailable.Add(-1);


foreach (var value in player.PropInventory) foreach (var value in player.PropInventory)
@@ -121,10 +121,9 @@ namespace Server
BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer) 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); msg.TrickerMessage.TimeUntilSkillAvailable.Add(-1);


foreach (var value in player.PropInventory) foreach (var value in player.PropInventory)


Loading…
Cancel
Save