Browse Source

build: 🎨 rebuild the skill system

tags/0.1.0
shangfengh 2 years ago
parent
commit
1d145a8db3
17 changed files with 477 additions and 495 deletions
  1. +1
    -2
      logic/GameClass/GameObj/Character/Character.Ghost.cs
  2. +1
    -16
      logic/GameClass/GameObj/Character/Character.Skill.cs
  3. +1
    -16
      logic/GameClass/GameObj/Character/Character.Student.cs
  4. +15
    -1
      logic/GameClass/GameObj/Character/Character.cs
  5. +0
    -227
      logic/GameClass/Skill/ActiveSkill.cs
  6. +0
    -21
      logic/GameClass/Skill/ISkill.cs
  7. +0
    -161
      logic/GameClass/Skill/PassiveSkill.cs
  8. +1
    -1
      logic/Gaming/ActionManager.cs
  9. +14
    -8
      logic/Gaming/Game.cs
  10. +0
    -29
      logic/Gaming/SkillManager.cs
  11. +238
    -0
      logic/Gaming/SkillManager/ActiveSkill.cs
  12. +131
    -0
      logic/Gaming/SkillManager/PassiveSkill.cs
  13. +53
    -0
      logic/Gaming/SkillManager/SkillManager.cs
  14. +7
    -0
      logic/Preparation/Interface/IOccupation.cs
  15. +2
    -1
      logic/Preparation/Utility/EnumType.cs
  16. +3
    -4
      logic/Preparation/Utility/GameData.cs
  17. +10
    -8
      logic/规则Logic.md

+ 1
- 2
logic/GameClass/GameObj/Character/Character.Ghost.cs View File

@@ -1,5 +1,4 @@
using GameClass.Skill;
using Preparation.Interface;
using Preparation.Interface;
using Preparation.Utility;
using System;
using System.Collections.Generic;


+ 1
- 16
logic/GameClass/GameObj/Character/Character.Skill.cs View File

@@ -1,5 +1,4 @@
using GameClass.Skill;
using Preparation.Utility;
using Preparation.Utility;
using Preparation.Interface;
using System.Collections.Generic;
using System;
@@ -37,20 +36,6 @@ namespace GameClass.GameObj
return false;
}

public bool UseActiveSkill(Map map, ActiveSkillType activeSkillType)
{
if (Occupation.ListOfIActiveSkill.Contains(activeSkillType))
return ActiveSkillFactory.FindIActiveSkill(activeSkillType).SkillEffect(map, this);
return false;
}

public void UsePassiveSkill(Map map, PassiveSkillType passiveSkillType)
{
if (Occupation.ListOfIPassiveSkill.Contains(passiveSkillType))
PassiveSkillFactory.FindIPassiveSkill(passiveSkillType).SkillEffect(map, this);
return;
}

public bool IsGhost()
{
return GameData.IsGhost(CharacterType);


+ 1
- 16
logic/GameClass/GameObj/Character/Character.Student.cs View File

@@ -1,5 +1,4 @@
using GameClass.Skill;
using Preparation.Utility;
using Preparation.Utility;
using Preparation.Interface;

namespace GameClass.GameObj
@@ -40,20 +39,6 @@ namespace GameClass.GameObj
}
public int OrgTreatSpeed { get; protected set; } = GameData.basicTreatSpeed;

protected int rescueSpeed = GameData.basicRescueSpeed;
public int RescueSpeed
{
get => rescueSpeed;
set
{
lock (gameObjLock)
{
rescueSpeed = value;
}
}
}
public int OrgRescueSpeed { get; protected set; } = GameData.basicRescueSpeed;

public int MaxGamingAddiction { get; protected set; }
private int gamingAddiction;
public int GamingAddiction


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

@@ -59,7 +59,6 @@ namespace GameClass.GameObj
{
get
{
if (IsResetting) return PlayerStateType.IsDeceased;
if (IsMoving) return PlayerStateType.IsMoving;
return playerState;
}
@@ -214,6 +213,21 @@ namespace GameClass.GameObj
}
}

private int timeOfOpeningOrLocking;
public int TimeOfOpeningOrLocking
{
get => timeOfOpeningOrLocking;
set
{
lock (gameObjLock)
{
timeOfOpeningOrLocking = value;
}
}
}



/// <summary>
/// 进行一次攻击
/// </summary>


+ 0
- 227
logic/GameClass/Skill/ActiveSkill.cs View File

@@ -1,227 +0,0 @@
using GameClass.GameObj;
using System.Threading;
using Preparation.Interface;
using Preparation.Utility;
using System;
using Timothy.FrameRateTask;

namespace GameClass.Skill
{
public class BecomeVampire : IActiveSkill // 化身吸血鬼
{
public int SkillCD => GameData.commonSkillCD / 3 * 4;
public int DurationTime => GameData.commonSkillTime;

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

public bool SkillEffect(Map map, Character player)
{
return ActiveSkillFactory.SkillEffect(this, player, () =>
{
player.Vampire += 0.5;
Debugger.Output(player, "becomes vampire!");
},
() =>
{
double tempVam = player.Vampire - 0.5;
player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam;
});
}
}

public class BeginToCharge : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD / 3 * 4;
public int DurationTime => GameData.commonSkillTime;

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

public bool SkillEffect(Map map, Character player)
{
return ActiveSkillFactory.SkillEffect(this, player, () =>
{
player.Vampire += 0.5;
Debugger.Output(player, "becomes vampire!");
},
() =>
{
double tempVam = player.Vampire - 0.5;
player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam;
});
}
}
public class BecomeInvisible : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 6;

private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Map map, Character player)
{
return ActiveSkillFactory.SkillEffect(this, player, () =>
{
player.IsInvisible = true;
Debugger.Output(player, "uses atombomb!");
},
() =>
{ player.IsInvisible = false; });
}
}
public class NuclearWeapon : IActiveSkill // 核武器
{
public int SkillCD => GameData.commonSkillCD / 3 * 7;
public int DurationTime => GameData.commonSkillTime / 10;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Map map, Character player)
{
return ActiveSkillFactory.SkillEffect(this, player, () =>
{
player.BulletOfPlayer = BulletType.AtomBomb;
Debugger.Output(player, "uses atombomb!");
},
() =>
{ player.BulletOfPlayer = player.OriBulletOfPlayer; });
}
}
public class UseKnife : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD / 3 * 2;
public int DurationTime => GameData.commonSkillTime / 10;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Map map, Character player)
{
return ActiveSkillFactory.SkillEffect(this, player, () =>
{
player.BulletOfPlayer = BulletType.FlyingKnife;
Debugger.Output(player, "uses flyingknife!");
},
() =>
{ player.BulletOfPlayer = player.OriBulletOfPlayer; });
}
}
public class SuperFast : IActiveSkill // 3倍速
{
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 4;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Map map, Character player)
{
return ActiveSkillFactory.SkillEffect(this, player, () =>
{
player.AddMoveSpeed(this.DurationTime, 3.0);
Debugger.Output(player, "moves very fast!");
},
() =>
{ });
}
}
public class NoCommonSkill : IActiveSkill // 这种情况不该发生,定义着以防意外
{
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Map map, Character player)
{
return false;
}
}

public static class ActiveSkillFactory
{
public static bool SkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill)
{
lock (activeSkill.ActiveSkillLock)
{
ActiveSkillType activeSkillType = FindActiveSkillType(activeSkill);
if (player.TimeUntilActiveSkillAvailable[activeSkillType] == 0)
{

player.SetTimeUntilActiveSkillAvailable(activeSkillType, activeSkill.SkillCD);
new Thread
(() =>
{
startSkill();
new FrameRateTaskExecutor<int>(
() => !player.IsResetting,
() =>
{
player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: (long)(activeSkill.DurationTime)
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
}
.Start();

endSkill();
Debugger.Output(player, "return to normal.");

new FrameRateTaskExecutor<int>(
() => player.TimeUntilActiveSkillAvailable[activeSkillType] > 0 && !player.IsResetting,
() =>
{
player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: (long)(activeSkill.SkillCD - activeSkill.DurationTime)
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
}
.Start();

player.SetTimeUntilActiveSkillAvailable(activeSkillType, 0);
Debugger.Output(player, "CommonSkill is ready.");
}
)
{ IsBackground = true }.Start();

return true;
}
else
{
Debugger.Output(player, "CommonSkill is cooling down!");
return false;
}
}
}
public static IActiveSkill? FindIActiveSkill(ActiveSkillType activeSkillType)
{
switch (activeSkillType)
{
case ActiveSkillType.BecomeInvisible:
return new BecomeInvisible();
default:
return null;
}
}
public static ActiveSkillType FindActiveSkillType(IActiveSkill ActiveSkill)
{
switch (ActiveSkill)
{
case BecomeInvisible:
return ActiveSkillType.BecomeInvisible;
case UseKnife:
return ActiveSkillType.UseKnife;
case BeginToCharge:
return ActiveSkillType.BeginToCharge;
default:
return ActiveSkillType.Null;
}
}
}

}

+ 0
- 21
logic/GameClass/Skill/ISkill.cs View File

@@ -1,21 +0,0 @@
using Preparation.Utility;
using GameClass.GameObj;
using System.Collections.Generic;

namespace GameClass.Skill
{
public interface ISkill
{
}
public interface IPassiveSkill : ISkill
{
public void SkillEffect(Map map, Character player);
}
public interface IActiveSkill : ISkill
{
public int SkillCD { get; }
public int DurationTime { get; } //技能持续时间
public object ActiveSkillLock { get; }
public bool SkillEffect(Map map, Character player);
}
}

+ 0
- 161
logic/GameClass/Skill/PassiveSkill.cs View File

@@ -1,161 +0,0 @@
using System;
using System.Threading;
using GameClass.GameObj;
using Preparation.Interface;
using Preparation.Utility;
using Timothy.FrameRateTask;

namespace GameClass.Skill // 被动技能开局时就释放,持续到游戏结束
{
public class RecoverAfterBattle : IPassiveSkill // 脱战回血,普通子弹
{
public void SkillEffect(Map map, Character player)
{
const int recoverDegree = 5; // 每帧回复血量
int nowHP = player.HP;
int lastHP = nowHP;
long waitTime = 0;
const long interval = 10000; // 每隔interval时间不受伤害,角色即开始回血
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>
(
() => true,
() =>
{
lastHP = nowHP; // lastHP等于上一帧的HP
nowHP = player.HP; // nowHP更新为这一帧的HP
if (lastHP > nowHP) // 这一帧扣血了
{
waitTime = 0;
}
else if (waitTime < interval)
{
waitTime += GameData.frameDuration;
}

if (waitTime >= interval) // 回复时,每帧(50ms)回复5,即1s回复100。
player.TryAddHp(recoverDegree);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: GameData.gameDuration
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: passive skill time exceeds for once.");
}
#endif
}
}.Start();
}
)
{ IsBackground = true }.Start();
}
}
public class SpeedUpWhenLeavingGrass : IPassiveSkill // 3倍速
{
public void SkillEffect(Map map, Character player)
{
PlaceType nowPlace = map.GetPlaceType(player.Position);
PlaceType lastPlace = nowPlace;
bool speedup = false;
const int SpeedUpTime = 2000; // 加速时间:2s
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>
(
() => true,
() =>
{
lastPlace = nowPlace;
nowPlace = map.GetPlaceType(player.Position);
if ((lastPlace == PlaceType.Grass) && nowPlace == PlaceType.Null)
{
if (!speedup)
{
new Thread(() =>
{
speedup = true;
player.AddMoveSpeed(SpeedUpTime, 3.0);
speedup = false;
})
{ IsBackground = true }.Start();
}
}
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: GameData.gameDuration
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: passive skill time exceeds for once.");
}
#endif
}
}.Start();
}
)
{ IsBackground = true }.Start();
}
}
public class Vampire : IPassiveSkill // 被动就是吸血,普通子弹
{
public void SkillEffect(Map map, Character player)
{
player.OriVampire = 0.5;
player.Vampire = player.OriVampire;
}
}

public class NoPassiveSkill : IPassiveSkill // 没技能,这种情况不应该发生,先定义着以防意外
{
public void SkillEffect(Map map, Character player)
{
}
}


public static class PassiveSkillFactory
{
public static IPassiveSkill? FindIPassiveSkill(PassiveSkillType passiveSkillType)
{
switch (passiveSkillType)
{
default:
return null;
}
}
public static PassiveSkillType FindpassiveSkillType(IPassiveSkill passiveSkill)
{
switch (passiveSkill)
{
default:
return PassiveSkillType.Null;
}
}
}
}

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

@@ -28,7 +28,7 @@ namespace Gaming
if (player.PlayerState == PlayerStateType.IsRescuing || player.PlayerState == PlayerStateType.IsRescued
|| player.PlayerState == PlayerStateType.IsFixing || player.PlayerState == PlayerStateType.IsMoving
|| player.PlayerState == PlayerStateType.IsTreated || player.PlayerState == PlayerStateType.IsTreating
|| player.PlayerState == PlayerStateType.IsRummagingInTheDrawer || player.PlayerState == PlayerStateType.IsLockingTheDoor
|| player.PlayerState == PlayerStateType.IsRummagingInTheChest || player.PlayerState == PlayerStateType.IsLockingTheDoor
|| player.PlayerState == PlayerStateType.IsClimbingThroughWindows)
{
player.PlayerState = PlayerStateType.Null;


+ 14
- 8
logic/Gaming/Game.cs View File

@@ -150,7 +150,7 @@ namespace Gaming

finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock();
}
},
timeInterval: GameData.checkInterval,
@@ -179,11 +179,17 @@ namespace Gaming

propManager.StartProducing();

// 开始游戏
if (!gameMap.Timer.StartGame(milliSeconds))
return false;
new Thread
(
() =>
{
if (!gameMap.Timer.StartGame(milliSeconds))
return;

EndGame(); // 游戏结束时要做的事
EndGame(); // 游戏结束时要做的事
}
)
{ IsBackground = true }.Start();

return true;
}
@@ -333,7 +339,7 @@ namespace Gaming
Character? player = gameMap.FindPlayer(playerID);
if (player != null)
{
return skillManager.UseActiveSkill(this.GameMap, player, activeSkillType);
return skillManager.UseActiveSkill(player, activeSkillType);
}
else
return false;
@@ -348,7 +354,7 @@ namespace Gaming
{
foreach (Character player in gameMap.GameObjDict[GameObjType.Character])
{
skillManager.UseAllPassiveSkill(this.GameMap, player);
skillManager.UseAllPassiveSkill(player);
}
}
finally
@@ -439,10 +445,10 @@ namespace Gaming
teamList.Add(new Team());
}

skillManager = new SkillManager();
attackManager = new AttackManager(gameMap);
actionManager = new ActionManager(gameMap);
propManager = new PropManager(gameMap);
skillManager = new SkillManager(gameMap, actionManager, attackManager, propManager);
}
}
}

+ 0
- 29
logic/Gaming/SkillManager.cs View File

@@ -1,29 +0,0 @@
using System;
using Preparation.Utility;
using GameClass.GameObj;
using System.Reflection;
using GameClass.Skill;

namespace Gaming
{
public partial class Game
{
readonly SkillManager skillManager;
private class SkillManager
{
public bool UseActiveSkill(Map gamemap, Character character, ActiveSkillType activeSkillType)
{
return character.UseActiveSkill(gamemap, activeSkillType);
}
public void UsePassiveSkill(Map gamemap, Character character, PassiveSkillType passiveSkillType)
{
character.UsePassiveSkill(gamemap, passiveSkillType);
}
public void UseAllPassiveSkill(Map gamemap, Character character)
{
foreach (var passiveSkill in character.Occupation.ListOfIPassiveSkill)
character.UsePassiveSkill(gamemap, passiveSkill);
}
}
}
}

+ 238
- 0
logic/Gaming/SkillManager/ActiveSkill.cs View File

@@ -0,0 +1,238 @@
using GameClass.GameObj;
using System.Threading;
using Preparation.Interface;
using Preparation.Utility;
using System;
using Timothy.FrameRateTask;

namespace Gaming
{
public partial class Game
{
private partial class SkillManager
{
public interface IActiveSkill
{
public int SkillCD { get; }
public int DurationTime { get; } //技能持续时间
public object ActiveSkillLock { get; }
public bool SkillEffect(Character player);
}
public class BecomeVampire : IActiveSkill // 化身吸血鬼
{
public int SkillCD => GameData.commonSkillCD / 3 * 4;
public int DurationTime => GameData.commonSkillTime;

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

public bool SkillEffect(Character player)
{
return ActiveSkillEffect(this, player, () =>
{
player.Vampire += 0.5;
Debugger.Output(player, "becomes vampire!");
},
() =>
{
double tempVam = player.Vampire - 0.5;
player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam;
});
}
}
private IActiveSkill becomeVampire = new BecomeVampire();

public class BeginToCharge : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD / 3 * 4;
public int DurationTime => GameData.commonSkillTime;

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

public bool SkillEffect(Character player)
{
return ActiveSkillEffect(this, player, () =>
{
player.Vampire += 0.5;
Debugger.Output(player, "becomes vampire!");
},
() =>
{
double tempVam = player.Vampire - 0.5;
player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam;
});
}
}
private IActiveSkill beginToCharge = new BeginToCharge();

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

private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return ActiveSkillEffect(this, player, () =>
{
player.IsInvisible = true;
Debugger.Output(player, "become invisible!");
},
() =>
{ player.IsInvisible = false; });
}
}
private IActiveSkill becomeInvisible = new BecomeInvisible();

public class NuclearWeapon : IActiveSkill // 核武器
{
public int SkillCD => GameData.commonSkillCD / 3 * 7;
public int DurationTime => GameData.commonSkillTime / 10;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return ActiveSkillEffect(this, player, () =>
{
player.BulletOfPlayer = BulletType.AtomBomb;
Debugger.Output(player, "uses atombomb!");
},
() =>
{ player.BulletOfPlayer = player.OriBulletOfPlayer; });
}
}
private IActiveSkill nuclearWeapon = new NuclearWeapon();

public class UseKnife : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD / 3 * 2;
public int DurationTime => GameData.commonSkillTime / 10;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return ActiveSkillEffect(this, player, () =>
{
player.BulletOfPlayer = BulletType.FlyingKnife;
Debugger.Output(player, "uses flyingknife!");
},
() =>
{ player.BulletOfPlayer = player.OriBulletOfPlayer; });
}
}
private IActiveSkill useKnife = new UseKnife();

public class SuperFast : IActiveSkill // 3倍速
{
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 4;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return ActiveSkillEffect(this, player, () =>
{
player.AddMoveSpeed(this.DurationTime, 3.0);
Debugger.Output(player, "moves very fast!");
},
() =>
{ });
}
}
private IActiveSkill superFast = new SuperFast();

public IActiveSkill? FindIActiveSkill(ActiveSkillType activeSkillType)
{
switch (activeSkillType)
{
case ActiveSkillType.BecomeInvisible:
return this.becomeInvisible;
default:
return null;
}
}
public static ActiveSkillType FindActiveSkillType(IActiveSkill ActiveSkill)
{
switch (ActiveSkill)
{
case BecomeInvisible:
return ActiveSkillType.BecomeInvisible;
case UseKnife:
return ActiveSkillType.UseKnife;
case BeginToCharge:
return ActiveSkillType.BeginToCharge;
default:
return ActiveSkillType.Null;
}
}

public static bool ActiveSkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill)
{
lock (activeSkill.ActiveSkillLock)
{
ActiveSkillType activeSkillType = FindActiveSkillType(activeSkill);
if (player.TimeUntilActiveSkillAvailable[activeSkillType] == 0)
{

player.SetTimeUntilActiveSkillAvailable(activeSkillType, activeSkill.SkillCD);
new Thread
(() =>
{
startSkill();
new FrameRateTaskExecutor<int>(
() => !player.IsResetting,
() =>
{
player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: (long)(activeSkill.DurationTime)
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
}
.Start();

endSkill();
Debugger.Output(player, "return to normal.");

new FrameRateTaskExecutor<int>(
() => player.TimeUntilActiveSkillAvailable[activeSkillType] > 0 && !player.IsResetting,
() =>
{
player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: (long)(activeSkill.SkillCD - activeSkill.DurationTime)
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
}
.Start();

player.SetTimeUntilActiveSkillAvailable(activeSkillType, 0);
Debugger.Output(player, "ActiveSkill is ready.");
}
)
{ IsBackground = true }.Start();

return true;
}
else
{
Debugger.Output(player, "CommonSkill is cooling down!");
return false;
}
}
}

}

}
}

+ 131
- 0
logic/Gaming/SkillManager/PassiveSkill.cs View File

@@ -0,0 +1,131 @@
using System;
using System.Threading;
using GameClass.GameObj;
using Preparation.Interface;
using Preparation.Utility;
using Timothy.FrameRateTask;

namespace Gaming // 被动技能开局时就释放,持续到游戏结束
{
public partial class Game
{
private partial class SkillManager
{
public void RecoverAfterBattle(Character player)
{
const int recoverDegree = 5; // 每帧回复血量
int nowHP = player.HP;
int lastHP = nowHP;
long waitTime = 0;
const long interval = 10000; // 每隔interval时间不受伤害,角色即开始回血
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>
(
() => true,
() =>
{
lastHP = nowHP; // lastHP等于上一帧的HP
nowHP = player.HP; // nowHP更新为这一帧的HP
if (lastHP > nowHP) // 这一帧扣血了
{
waitTime = 0;
}
else if (waitTime < interval)
{
waitTime += GameData.frameDuration;
}

if (waitTime >= interval) // 回复时,每帧(50ms)回复5,即1s回复100。
player.TryAddHp(recoverDegree);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: GameData.gameDuration
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: passive skill time exceeds for once.");
}
#endif
}
}.Start();
}
)
{ IsBackground = true }.Start();
}
public void SpeedUpWhenLeavingGrass(Character player)
{
PlaceType nowPlace = gameMap.GetPlaceType(player.Position);
PlaceType lastPlace = nowPlace;
bool speedup = false;
const int SpeedUpTime = 2000; // 加速时间:2s
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>
(
() => true,
() =>
{
lastPlace = nowPlace;
nowPlace = gameMap.GetPlaceType(player.Position);
if ((lastPlace == PlaceType.Grass) && nowPlace == PlaceType.Null)
{
if (!speedup)
{
new Thread(() =>
{
speedup = true;
player.AddMoveSpeed(SpeedUpTime, 3.0);
speedup = false;
})
{ IsBackground = true }.Start();
}
}
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: GameData.gameDuration
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: passive skill time exceeds for once.");
}
#endif
}
}.Start();
}
)
{ IsBackground = true }.Start();
}

public void Vampire(Character player)
{
player.OriVampire = 0.5;
player.Vampire = player.OriVampire;
}
}
}
}

+ 53
- 0
logic/Gaming/SkillManager/SkillManager.cs View File

@@ -0,0 +1,53 @@
using System;
using Preparation.Utility;
using GameClass.GameObj;
using System.Reflection;
using GameEngine;

namespace Gaming
{
public partial class Game
{
readonly SkillManager skillManager;
private partial class SkillManager
{
public bool UseActiveSkill(Character character, ActiveSkillType activeSkillType)
{
if (character.Occupation.ListOfIActiveSkill.Contains(activeSkillType))
return FindIActiveSkill(activeSkillType).SkillEffect(character);
return false;
}
public void UsePassiveSkill(Character character, PassiveSkillType passiveSkillType)
{
if (character.Occupation.ListOfIPassiveSkill.Contains(passiveSkillType))
switch (passiveSkillType)
{
default:
return;
}
return;
}
public void UseAllPassiveSkill(Character character)
{
foreach (var passiveSkill in character.Occupation.ListOfIPassiveSkill)
switch (passiveSkill)
{
default:
return;
}
}

private readonly Map gameMap;
private readonly ActionManager actionManager;
private readonly AttackManager attackManager;
private readonly PropManager propManager;
public SkillManager(Map gameMap, ActionManager action, AttackManager attack, PropManager prop)
{
this.gameMap = gameMap;
this.actionManager = action;
this.propManager = prop;
this.attackManager = attack;
}
}
}
}

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

@@ -14,6 +14,7 @@ namespace Preparation.Interface
public List<PassiveSkillType> ListOfIPassiveSkill { get; }
public double Concealment { get; }
public int AlertnessRadius { get; }
public int TimeOfOpeningOrLocking { get; }
}

public interface IGhost : IOccupation
@@ -49,6 +50,9 @@ namespace Preparation.Interface

public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.3);
public int AlertnessRadius => alertnessRadius;

public int timeOfOpeningOrLocking = GameData.basicTimeOfOpeningOrLocking;
public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking;
}
public class Athlete : IStudent
{
@@ -77,5 +81,8 @@ namespace Preparation.Interface

public const int alertnessRadius = (int)(GameData.basicAlertnessRadius * 0.9);
public int AlertnessRadius => alertnessRadius;

public int timeOfOpeningOrLocking = GameData.basicTimeOfOpeningOrLocking;
public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking;
}
}

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

@@ -20,7 +20,7 @@ namespace Preparation.Utility
IsStunned = 11,
IsTryingToAttack = 12,//指前摇
IsLockingTheDoor = 13,
IsRummagingInTheDrawer = 14,
IsRummagingInTheChest = 14,
IsClimbingThroughWindows = 15,
}
public enum GameObjType
@@ -120,6 +120,7 @@ namespace Preparation.Utility
EmergencyExit = 10,
Window = 11,
Door = 12,
Chest = 13,
}
public enum BgmType
{


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

@@ -56,7 +56,6 @@ namespace Preparation.Utility
public const int basicApOfGhost = 1500000; // 攻击力
public const int basicTreatSpeed = 100;
public const int basicFixSpeed = 100;
public const int basicRescueSpeed = 100;
public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间
public const int BeginGamingAddiction = 10003;
public const int MidGamingAddiction = 30000;
@@ -73,11 +72,12 @@ namespace Preparation.Utility
public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围
public const double basicAttackShortRange = 2700; // 基本近程攻击范围
public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围
public const int basicMoveSpeed = 3800; // 基本移动速度,单位:s-1
public const int basicBulletMoveSpeed = 5400; // 基本子弹移动速度,单位:s-1
public const int basicMoveSpeed = 1260; // 基本移动速度,单位:s-1
public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1
public const int characterMaxSpeed = 12000; // 最大速度
public const double basicConcealment = 1.0;
public const int basicAlertnessRadius = 30700;
public const int basicTimeOfOpeningOrLocking = 3000;
public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分
public const int commonSkillCD = 30000; // 普通技能标准冷却时间
public const int commonSkillTime = 10000; // 普通技能标准持续时间
@@ -106,7 +106,6 @@ namespace Preparation.Utility
public const long PropProduceTime = 10000;
public const int PropDuration = 10000;
#endregion

#region 物体相关
public const int degreeOfFixedGenerator = 10300000;
#endregion


+ 10
- 8
logic/规则Logic.md View File

@@ -5,6 +5,7 @@
- 该规则直接服务于Sever,并非选手版本
- *斜体表示Logic底层尚未(完全)实现*
- []表示待决定
- ~~表示暂不实现~~

## 游戏简介
- 1位监管者对抗4位求生者的非对称竞技模式
@@ -90,11 +91,11 @@
IsStunned = 11,
IsTryingToAttack = 12,//指前摇
IsLockingTheDoor = 13,
IsRummagingInTheDrawer = 14,
IsRummagingInTheChest = 14,
IsClimbingThroughWindows = 15,
}
~~~
- *Bgm(字典)*
- Bgm(字典)
- 得分
- ~~回血率/原始回血率~~
- 当前子弹类型
@@ -108,15 +109,15 @@
- 拥有的被动技能(列表)
- 拥有的主动技能(列表)
- 各个主动技能CD(字典)
- *警戒半径*
- *double 隐蔽度*
- *翻墙速度*
- *开锁门速度*
- 警戒半径
- double 隐蔽度
- *翻窗时间*
- 开锁门时间

### 学生:人物
- 修理电机速度
- 治疗速度
- 救人速度
- ~~救人速度~~
- ~~自愈次数~~
- 沉迷游戏程度
- 最大沉迷游戏程度
@@ -171,6 +172,7 @@

### 箱子:物体
- *里面的道具*
- *是否开启*

### 门:物体
- *属于那个教学区*
@@ -225,7 +227,7 @@
- *翻越窗户是一种交互行为,执行时,实质是限定方向的减速运动*

### 箱子
- *监管者和求生者都能与箱子交互*
- *监管者和求生者都能与箱子交互,同一时刻就允许一人进行翻找*
- *开启箱子有不同概率获得不同道具。*
- *搜寻物品的基础持续时间为10秒。*
- *未搜寻完成的箱子在下一次需要重新开始搜寻。*


Loading…
Cancel
Save