Browse Source

feat: add new CharacterType Klee

tags/0.1.0
shangfengh 2 years ago
parent
commit
9a53d0a266
20 changed files with 232 additions and 257 deletions
  1. +10
    -9
      dependency/proto/MessageType.proto
  2. +96
    -5
      logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs
  3. +1
    -1
      logic/GameClass/GameObj/Bullet/Bullet.Student.cs
  4. +9
    -9
      logic/GameClass/GameObj/Bullet/Bullet.cs
  5. +7
    -1
      logic/GameClass/GameObj/Character/Character.Skill.cs
  6. +2
    -1
      logic/GameClass/GameObj/Character/Character.cs
  7. +7
    -3
      logic/GameClass/GameObj/Character/Skill.cs
  8. +6
    -6
      logic/GameClass/GameObj/Prop.cs
  9. +10
    -2
      logic/Gaming/ActionManager.cs
  10. +12
    -9
      logic/Gaming/AttackManager.cs
  11. +2
    -2
      logic/Gaming/PropManager.cs
  12. +7
    -7
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  13. +3
    -0
      logic/Gaming/SkillManager/SkillManager.cs
  14. +2
    -0
      logic/Preparation/Interface/ICharacter.cs
  15. +18
    -18
      logic/Preparation/Interface/IOccupation.cs
  16. +14
    -15
      logic/Preparation/Utility/EnumType.cs
  17. +15
    -6
      logic/Preparation/Utility/GameData.cs
  18. +6
    -2
      logic/Server/CopyInfo.cs
  19. +1
    -1
      logic/cmd/gameServer.cmd
  20. +4
    -160
      logic/规则Logic.md

+ 10
- 9
dependency/proto/MessageType.proto View File

@@ -43,7 +43,7 @@ enum PropType // 地图中的可拾取道具类型
{
NULL_PROP_TYPE = 0;
ADD_SPEED = 1;
ADD_LIFE_OR_AP = 2;
ADD_LIFE_OR_AP = 2;//ADD_LIFE_OR_Clairaudience
ADD_HP_OR_AP = 3;
SHIELD_OR_SPEAR = 4;
KEY3 = 5;
@@ -54,9 +54,9 @@ enum PropType // 地图中的可拾取道具类型
enum StudentBuffType // 人类可用的增益效果类型
{
NULL_SBUFF_TYPE = 0;
SBUFFTYPE1 = 1;
SBUFFTYPE2 = 2;
SBUFFTYPE3 = 3;
SBUFFTYPE1 = 1;//AddSpeed
SBUFFTYPE2 = 2;//AddLIFE
SBUFFTYPE3 = 3;//Shield
SBUFFTYPE4 = 4;
}

@@ -86,10 +86,11 @@ enum PlayerState
enum TrickerBuffType // 屠夫可用的增益效果类型
{
NULL_TBUFF_TYPE = 0;
TBUFFTYPE1 = 1;
TBUFFTYPE2 = 2;
TBUFFTYPE3 = 3;
TBUFFTYPE4 = 4;
TBUFFTYPE1 = 1;//AddSpeed
TBUFFTYPE2 = 2;//Spear
TBUFFTYPE3 = 3;//AddAp
TBUFFTYPE4 = 4;//Clairaudience
INVISIBLE = 5;
}

// 特别说明:由于Student阵营和Tricker阵营有显著的隔离,且暂定职业、主动技能和被动效果相互绑定,故不按照THUAI5的方式区分ActiveSkillType和CharacterType,而是选择了按照阵营来给不同阵营赋予不同的职业(及技能)。
@@ -114,7 +115,7 @@ enum TrickerType
{
NULL_TRICKER_TYPE = 0;
ASSASSIN = 1;
TRICKERTYPE2 = 2;
TRICKERTYPE2 = 2;//KLEE
TRICKERTYPE3 = 3;
TRICKERTYPE4 = 4;
}


+ 96
- 5
logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs View File

@@ -23,9 +23,9 @@ namespace GameClass.GameObj
}
}
public override int Speed => GameData.basicBulletMoveSpeed;
public override bool IsToBomb => false;
public override bool IsRemoteAttack => false;

public override int CastTime => GameData.basicCastTime;
public override int CastTime => (int)BulletAttackRange / Speed;
public override int Backswing => GameData.basicBackswing;
public override int RecoveryFromHit => GameData.basicRecoveryFromHit;
public const int cd = GameData.basicBackswing;
@@ -68,11 +68,11 @@ namespace GameClass.GameObj
}
}
public override int Speed => GameData.basicBulletMoveSpeed * 2;
public override bool IsToBomb => false;
public override bool IsRemoteAttack => true;

public override int CastTime => GameData.basicCastTime;
public override int Backswing => GameData.basicBackswing * 2 / 5;
public override int RecoveryFromHit => GameData.basicBackswing * 3 / 4;
public override int Backswing => 0;
public override int RecoveryFromHit => 0;
public const int cd = GameData.basicBackswing * 2 / 5 + 100;
public override int CD => cd;

@@ -94,4 +94,95 @@ namespace GameClass.GameObj
public override BulletType TypeOfBullet => BulletType.FlyingKnife;

}

internal sealed class BombBomb : Bullet
{
public BombBomb(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) :
base(player, radius, placeType, pos)
{
}
public override double BulletBombRange => GameData.basicBulletBombRange;
public override double BulletAttackRange => GameData.basicAttackShortRange;
public int ap = (int)(GameData.basicApOfGhost * 6.0 / 5);
public override int AP
{
get => ap;
set
{
lock (gameObjLock)
ap = value;
}
}
public override int Speed => (int)(GameData.basicBulletMoveSpeed * 0.8);
public override bool IsRemoteAttack => false;

public override int CastTime => (int)BulletAttackRange / Speed;
public override int Backswing => GameData.basicBackswing;
public override int RecoveryFromHit => GameData.basicRecoveryFromHit;
public const int cd = GameData.basicCD;
public override int CD => cd;

public override bool CanAttack(GameObj target)
{
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}
public override bool CanBeBombed(GameObjType gameObjType)
{
switch (gameObjType)
{
case GameObjType.Character:
case GameObjType.Generator:
return true;
default:
return false;
}
}
public override BulletType TypeOfBullet => BulletType.BombBomb;

}
internal sealed class JumpyDumpty : Bullet
{
public JumpyDumpty(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) :
base(player, radius, placeType, pos)
{
}
public override double BulletBombRange => GameData.basicBulletBombRange / 2;
public override double BulletAttackRange => GameData.basicAttackShortRange * 2;
public int ap = (int)(GameData.basicApOfGhost * 0.6);
public override int AP
{
get => ap;
set
{
lock (gameObjLock)
ap = value;
}
}
public override int Speed => (int)(GameData.basicBulletMoveSpeed * 1.2);
public override bool IsRemoteAttack => false;

public override int CastTime => 0;
public override int Backswing => 0;
public override int RecoveryFromHit => 0;
public const int cd = 0;
public override int CD => cd;

public override bool CanAttack(GameObj target)
{
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}
public override bool CanBeBombed(GameObjType gameObjType)
{
switch (gameObjType)
{
case GameObjType.Character:
case GameObjType.Generator:
return true;
default:
return false;
}
}
public override BulletType TypeOfBullet => BulletType.JumpyDumpty;

}
}

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

@@ -12,7 +12,7 @@ namespace GameClass.GameObj
public override double BulletAttackRange => 0;
public override int AP => 7220;
public override int Speed => 0;
public override bool IsToBomb => false;
public override bool IsRemoteAttack => false;
public override int CastTime => 0;
public override int Backswing => 0;
public override int RecoveryFromHit => 0;


+ 9
- 9
logic/GameClass/GameObj/Bullet/Bullet.cs View File

@@ -13,7 +13,7 @@ namespace GameClass.GameObj
public abstract double BulletAttackRange { get; }
public abstract int AP { get; set; }
public abstract int Speed { get; }
public abstract bool IsToBomb { get; }
public abstract bool IsRemoteAttack { get; }
public abstract int CastTime { get; }
public abstract int Backswing { get; }
public abstract int RecoveryFromHit { get; }
@@ -63,6 +63,10 @@ namespace GameClass.GameObj
return new FlyingKnife(character, place, pos);
case BulletType.CommonAttackOfGhost:
return new CommonAttackOfGhost(character, place, pos);
case BulletType.JumpyDumpty:
return new JumpyDumpty(character, place, pos);
case BulletType.BombBomb:
return new BombBomb(character, place, pos);
default:
return null;
}
@@ -71,10 +75,6 @@ namespace GameClass.GameObj
{
switch (bulletType)
{
case BulletType.AtomBomb:
case BulletType.LineBullet:
case BulletType.FastBullet:
case BulletType.OrdinaryBullet:
case BulletType.FlyingKnife:
default:
return GameData.bulletRadius;
@@ -88,10 +88,10 @@ namespace GameClass.GameObj
return CommonAttackOfGhost.cd;
case BulletType.FlyingKnife:
return FlyingKnife.cd;
case BulletType.AtomBomb:
case BulletType.LineBullet:
case BulletType.FastBullet:
case BulletType.OrdinaryBullet:
case BulletType.BombBomb:
return BombBomb.cd;
case BulletType.JumpyDumpty:
return JumpyDumpty.cd;
default:
return GameData.basicCD;
}


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

@@ -66,6 +66,12 @@ namespace GameClass.GameObj
case CharacterType.Assassin:
this.occupation = new Assassin();
break;
case CharacterType.Teacher:
this.occupation = new Teacher();
break;
case CharacterType.Klee:
this.occupation = new Klee();
break;
case CharacterType.Athlete:
default:
this.occupation = new Athlete();
@@ -82,7 +88,7 @@ namespace GameClass.GameObj
this.characterType = characterType;
this.SpeedOfOpeningOrLocking = Occupation.TimeOfOpeningOrLocking;
this.SpeedOfClimbingThroughWindows = Occupation.SpeedOfClimbingThroughWindows;
this.SpeedOfOpenChest = Occupation.TimeOfOpenChest;
this.SpeedOfOpenChest = Occupation.SpeedOfOpenChest;

foreach (var activeSkill in this.Occupation.ListOfIActiveSkill)
{


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

@@ -47,7 +47,8 @@ namespace GameClass.GameObj
lock (gameObjLock)
{
bulletOfPlayer = value;
CD = BulletFactory.BulletCD(value);
OrgCD = (BulletFactory.BulletCD(value));
CD = 0;
}
}
}


+ 7
- 3
logic/GameClass/GameObj/Character/Skill.cs View File

@@ -62,10 +62,10 @@ namespace GameClass.GameObj
}
}

public class NuclearWeapon : IActiveSkill // 核武器
public class JumpyBomb : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD * 7 / 3;
public int DurationTime => GameData.commonSkillTime / 10;
public int SkillCD => GameData.commonSkillCD / 30 * 5;
public int DurationTime => GameData.commonSkillTime / 2;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;

@@ -132,6 +132,8 @@ namespace GameClass.GameObj
return new CanBeginToCharge();
case ActiveSkillType.Punish:
return new Punish();
case ActiveSkillType.JumpyBomb:
return new JumpyBomb();
default:
return new NullSkill();
}
@@ -149,6 +151,8 @@ namespace GameClass.GameObj
return ActiveSkillType.CanBeginToCharge;
case Punish:
return ActiveSkillType.Punish;
case JumpyBomb:
return ActiveSkillType.JumpyBomb;
default:
return ActiveSkillType.Null;
}


+ 6
- 6
logic/GameClass/GameObj/Prop.cs View File

@@ -52,13 +52,13 @@ namespace GameClass.GameObj
/// <summary>
/// 复活甲
/// </summary>
public sealed class AddLifeOrAp : Prop
public sealed class AddLifeOrClairaudience : Prop
{
public AddLifeOrAp(XY initPos, PlaceType placeType) :
public AddLifeOrClairaudience(XY initPos, PlaceType placeType) :
base(initPos, placeType)
{
}
public override PropType GetPropType() => PropType.AddLifeOrAp;
public override PropType GetPropType() => PropType.AddLifeOrClairaudience;
}
public sealed class AddHpOrAp : Prop
{
@@ -141,8 +141,8 @@ namespace GameClass.GameObj
{
case PropType.AddSpeed:
return new AddSpeed(pos, place);
case PropType.AddLifeOrAp:
return new AddLifeOrAp(pos, place);
case PropType.AddLifeOrClairaudience:
return new AddLifeOrClairaudience(pos, place);
case PropType.ShieldOrSpear:
return new ShieldOrSpear(pos, place);
case PropType.AddHpOrAp:
@@ -158,4 +158,4 @@ namespace GameClass.GameObj
}
}
}
}
}

+ 10
- 2
logic/Gaming/ActionManager.cs View File

@@ -17,8 +17,16 @@ namespace Gaming
{

// 人物移动
private void SkillWhenMove(Character player, IGameObj collisionObj)
private static void SkillWhenColliding(Character player, IGameObj collisionObj)
{
if (collisionObj.Type == GameObjType.Bullet)
{
if (((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty)
{
if (AttackManager.BeStunned((Character)collisionObj, ((Bullet)collisionObj).AP / GameData.timeFactorOfGhostFainting))
player.AddScore(GameData.StudentScoreTrickerBeStunned(((Bullet)collisionObj).AP / GameData.timeFactorOfGhostFainting));
}
}
if (player.UseIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost())
{
if (AttackManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge))
@@ -495,7 +503,7 @@ namespace Gaming
gameMap: gameMap,
OnCollision: (obj, collisionObj, moveVec) =>
{
SkillWhenMove((Character)obj, collisionObj);
SkillWhenColliding((Character)obj, collisionObj);
//if (collisionObj is Mine)
//{
// ActivateMine((Character)obj, (Mine)collisionObj);


+ 12
- 9
logic/Gaming/AttackManager.cs View File

@@ -33,7 +33,7 @@ namespace Gaming
Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64);

#endif
if (obj.CanMove)
if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty)
BulletBomb((Bullet)obj, null);
}
);
@@ -124,10 +124,6 @@ namespace Gaming
gameMap.GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock();
}
}

// player.Reset();
// ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分

}

private void BombObj(Bullet bullet, GameObj objBeingShot)
@@ -174,10 +170,10 @@ namespace Gaming
#endif
bullet.CanMove = false;

if (gameMap.Remove(bullet) && bullet.IsToBomb)
if (gameMap.Remove(bullet) && bullet.BulletBombRange > 0)
gameMap.Add(new BombedBullet(bullet));

if (!bullet.IsToBomb)
if (bullet.BulletBombRange == 0)
{
if (objBeingShot == null)
{
@@ -201,7 +197,14 @@ namespace Gaming
return;
}


if (bullet.TypeOfBullet == BulletType.BombBomb)
{
bullet.Parent.BulletOfPlayer = BulletType.JumpyDumpty;
Attack((Character)bullet.Parent, 0.0);
Attack((Character)bullet.Parent, Math.PI);
Attack((Character)bullet.Parent, Math.PI / 2.0);
Attack((Character)bullet.Parent, Math.PI * 3.0 / 2.0);
}
BombObj(bullet, objBeingShot);
if (bullet.RecoveryFromHit > 0)
{
@@ -304,7 +307,7 @@ namespace Gaming
beAttackedList.Clear();
}

public bool Attack(Character? player, double angle) // 射出去的子弹泼出去的水(狗头)
public bool Attack(Character? player, double angle)
{ // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange
if (player == null)
{


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

@@ -31,10 +31,10 @@ namespace Gaming
player.AddSpear(GameData.PropDuration);
else player.AddShield(GameData.PropDuration);
break;
case PropType.AddLifeOrAp:
case PropType.AddLifeOrClairaudience:
if (!player.IsGhost())
player.AddLIFE(GameData.PropDuration);
else player.AddAp(GameData.PropDuration);
else player.AddClairaudience(GameData.PropDuration);
break;
case PropType.AddSpeed:
player.AddMoveSpeed(GameData.PropDuration);


+ 7
- 7
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -36,7 +36,7 @@ namespace Gaming
return ActiveSkillEffect(skill, player, () =>
{
player.AddMoveSpeed(skill.DurationTime, 3.0);
//See SkillWhenMove in ActionManager
//See SkillWhenColliding in ActionManager
},
() =>
{ });
@@ -55,12 +55,12 @@ namespace Gaming
{ });
}

public bool NuclearWeapon(Character player)
public bool JumpyBomb(Character player)
{
return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.NuclearWeapon), player, () =>
return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.JumpyBomb), player, () =>
{
player.BulletOfPlayer = BulletType.AtomBomb;
Debugger.Output(player, "uses atombomb!");
player.BulletOfPlayer = BulletType.BombBomb;
Debugger.Output(player, "uses jumpybomb!");
},
() =>
{ player.BulletOfPlayer = player.OriBulletOfPlayer; });
@@ -92,8 +92,8 @@ namespace Gaming
|| player.PlayerState == PlayerStateType.UsingSkill || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || player.PlayerState == PlayerStateType.OpeningTheChest)
&& gameMap.CanSee(player, character))
{
if (AttackManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.TimeFactorOfGhostFainting))
player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.TimeFactorOfGhostFainting));
if (AttackManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.timeFactorOfGhostFainting))
player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.timeFactorOfGhostFainting));
break;
}
}


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

@@ -28,6 +28,9 @@ namespace Gaming
case ActiveSkillType.Punish:
Punish(character);
break;
case ActiveSkillType.JumpyBomb:
JumpyBomb(character);
break;
default:
return false;
}


+ 2
- 0
logic/Preparation/Interface/ICharacter.cs View File

@@ -11,6 +11,8 @@ namespace Preparation.Interface
public void AddScore(int add);
public double Vampire { get; }
public PlayerStateType PlayerState { get; set; }
public BulletType BulletOfPlayer { get; set; }

public bool IsGhost();
}
}

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

@@ -16,7 +16,7 @@ namespace Preparation.Interface
public int ViewRange { get; }
public int TimeOfOpeningOrLocking { get; }
public int SpeedOfClimbingThroughWindows { get; }
public int TimeOfOpenChest { get; }
public int SpeedOfOpenChest { get; }
}

public interface IGhost : IOccupation
@@ -32,7 +32,7 @@ namespace Preparation.Interface

public class Assassin : IGhost
{
private const int moveSpeed = GameData.basicMoveSpeed * 473 / 380;
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 473.0 / 380);
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp;
@@ -61,12 +61,12 @@ namespace Preparation.Interface
public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows;
public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows;

public int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
public int TimeOfOpenChest => timeOfOpenChest;
public int speedOfOpenChest = GameData.basicSpeedOfOpenChest;
public int SpeedOfOpenChest => speedOfOpenChest;
}
public class HoD : IGhost
public class Klee : IGhost
{
private const int moveSpeed = GameData.basicMoveSpeed * 473 / 380;
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 155 / 127);
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp;
@@ -77,26 +77,26 @@ namespace Preparation.Interface

public BulletType InitBullet => BulletType.CommonAttackOfGhost;

public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.BecomeInvisible, ActiveSkillType.UseKnife });
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

public double concealment = GameData.basicConcealment * 1.5;
public double concealment = GameData.basicConcealment;
public double Concealment => concealment;

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

public int viewRange = (int)(GameData.basicViewRange * 1.3);
public int viewRange = (int)(GameData.basicViewRange * 1.1);
public int ViewRange => viewRange;

public int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking;
public int timeOfOpeningOrLocking = (int)(GameData.basicSpeedOfOpeningOrLocking / 1.1);
public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking;

public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows;
public int speedOfClimbingThroughWindows = (int)(GameData.basicGhostSpeedOfClimbingThroughWindows / 1.1);
public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows;

public int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
public int TimeOfOpenChest => timeOfOpenChest;
public int speedOfOpenChest = (int)(GameData.basicSpeedOfOpenChest * 1.1);
public int SpeedOfOpenChest => speedOfOpenChest;
}
public class Teacher : IStudent
{
@@ -138,8 +138,8 @@ namespace Preparation.Interface
public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows / 2;
public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows;

public int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
public int TimeOfOpenChest => timeOfOpenChest;
public int speedOfOpenChest = GameData.basicSpeedOfOpenChest;
public int SpeedOfOpenChest => speedOfOpenChest;
}
public class Athlete : IStudent
{
@@ -181,7 +181,7 @@ namespace Preparation.Interface
public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 12 / 10;
public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows;

public int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
public int TimeOfOpenChest => timeOfOpenChest;
public int speedOfOpenChest = GameData.basicSpeedOfOpenChest;
public int SpeedOfOpenChest => speedOfOpenChest;
}
}

+ 14
- 15
logic/Preparation/Utility/EnumType.cs View File

@@ -53,31 +53,30 @@ namespace Preparation.Utility
public enum BulletType // 子弹类型
{
Null = 0,
OrdinaryBullet = 1, // 普通子弹
AtomBomb = 2, // 原子弹
FastBullet = 3, // 快速子弹
LineBullet = 4, // 直线子弹
FlyingKnife = 5, //飞刀
CommonAttackOfGhost = 6,
FlyingKnife = 1, //飞刀
CommonAttackOfGhost = 2,
JumpyDumpty = 3,
BombBomb = 4,
// Ram = 7,
}
public enum PropType // 道具类型
{
Null = 0,
AddSpeed = 1,
AddLifeOrAp = 2,
AddHpOrAp = 3,
ShieldOrSpear = 4,
Key3 = 5,
Key5 = 6,
Key6 = 7,
Key3 = 1,
Key5 = 2,
Key6 = 3,
AddSpeed = 4,
AddLifeOrClairaudience = 5,
AddHpOrAp = 6,
ShieldOrSpear = 7,
RecoveryFromDizziness = 8,
}
public enum CharacterType // 职业
{
Null = 0,
Assassin = 1,
Athlete = 2,
RecoverAfterBattle = 3,
Klee = 3,
SpeedUpWhenLeavingGrass = 4,
Teacher = 5,
PSkill5 = 6
@@ -87,7 +86,7 @@ namespace Preparation.Utility
Null = 0,
BecomeInvisible = 1,
BecomeVampire = 2,
NuclearWeapon = 3,
JumpyBomb = 3,
SuperFast = 4,
UseKnife = 5,
CanBeginToCharge = 6,


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

@@ -35,6 +35,14 @@ namespace Preparation.Utility
{
return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass && gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window && gameObjType != GameObjType.Wall;
}
/* public static bool Collide(GameObjType gameObjType)
{
return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass
&& gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window
&& gameObjType != GameObjType.Bullet&&gameObjType != GameObjType.Prop
&&gameObjType != GameObjType.PickedProp&&gameObjType != GameObjType.BombedBullet
&&gameObjType != GameObjType.EmergencyExit&&gameObjType != GameObjType.Doorway;
}*/

public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标
{
@@ -106,6 +114,7 @@ namespace Preparation.Utility
return characterType switch
{
CharacterType.Assassin => true,
CharacterType.Klee=> true,
_ => false,
};
}
@@ -161,13 +170,13 @@ namespace Preparation.Utility
public const int basicCD = 3000; // 初始子弹冷却
public const int basicCastTime = 500;//基本前摇时间
public const int basicBackswing = 818;//基本后摇时间
public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长
public const int basicRecoveryFromHit = 3700;//基本命中攻击恢复时长
public const int basicStunnedTimeOfStudent = 4130;

public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1
public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围
public const double basicAttackShortRange = 2700; // 基本近程攻击范围
public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围
public const int basicBulletMoveSpeed = 1800; // 基本子弹移动速度,单位:s-1
public const double basicRemoteAttackRange = 3000; // 基本远程攻击范围
public const double basicAttackShortRange = 900; // 基本近程攻击范围
public const double basicBulletBombRange = 1000; // 基本子弹爆炸范围
#endregion
#region 技能相关
public const int maxNumOfSkill = 3;
@@ -183,7 +192,7 @@ namespace Preparation.Utility
/// Punish
/// </summary>
public const int TimeOfGhostFaintingWhenPunish = 3070;
public const int TimeFactorOfGhostFainting = 1000;
public const int timeFactorOfGhostFainting = 250;
#endregion
#region 道具相关
public const int MinPropTypeNum = 1;


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

@@ -50,7 +50,7 @@ namespace Server
{
case Preparation.Utility.PropType.AddSpeed:
return Protobuf.PropType.AddSpeed;
case Preparation.Utility.PropType.AddLifeOrAp:
case Preparation.Utility.PropType.AddLifeOrClairaudience:
return Protobuf.PropType.AddLifeOrAp;
case Preparation.Utility.PropType.AddHpOrAp:
return Protobuf.PropType.AddHpOrAp;
@@ -74,7 +74,7 @@ namespace Server
case Protobuf.PropType.AddSpeed:
return Preparation.Utility.PropType.AddSpeed;
case Protobuf.PropType.AddLifeOrAp:
return Preparation.Utility.PropType.AddLifeOrAp;
return Preparation.Utility.PropType.AddLifeOrClairaudience;
case Protobuf.PropType.AddHpOrAp:
return Preparation.Utility.PropType.AddHpOrAp;
case Protobuf.PropType.ShieldOrSpear:
@@ -195,6 +195,8 @@ namespace Server
{
case Preparation.Utility.CharacterType.Assassin:
return Protobuf.TrickerType.Assassin;
case Preparation.Utility.CharacterType.Klee:
return Protobuf.TrickerType._2;
default:
return Protobuf.TrickerType.NullTrickerType;
}
@@ -206,6 +208,8 @@ namespace Server
{
case Protobuf.TrickerType.Assassin:
return Preparation.Utility.CharacterType.Assassin;
case Protobuf.TrickerType._2:
return Preparation.Utility.CharacterType.Klee;
default:
return Preparation.Utility.CharacterType.Null;
}


+ 1
- 1
logic/cmd/gameServer.cmd View File

@@ -4,7 +4,7 @@ start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --s

ping -n 2 127.0.0.1 > NUL

start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 1
start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 2

ping -n 2 127.0.0.1 > NUL



+ 4
- 160
logic/规则Logic.md View File

@@ -154,7 +154,7 @@
- 子弹爆炸范围
- 子弹攻击力
- 是否可以穿墙
- 是否可以爆炸
- 是否为远程攻击
- 移动速度
- 子弹类型

@@ -347,7 +347,7 @@
| 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] |
| :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------|
| AddSpeed | 提高移动速度,持续10s |不得分| 提高移动速度,持续10s |不得分|
| AddLifeOrAp |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? |
| AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? |
| AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? |
| ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生|
| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分|
@@ -494,165 +494,9 @@
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => 0;
~~~
使用瞬间,在视范围内的捣蛋鬼会被眩晕(3070+ 玩家损失的血量 / 1000)ms,
使用瞬间,在视范围内的使用技能状态中、攻击前后摇、开锁门、开箱的捣蛋鬼会被眩晕(3070+ 玩家损失的血量 / 1000)ms,

## 游戏数据

### 基本常数
~~~csharp
public const int numOfStepPerSecond = 20; // 每秒行走的步数
public const int frameDuration = 50; // 每帧时长
public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长

public const long gameDuration = 600000; // 游戏时长600000ms = 10min

public const int MinSpeed = 1; // 最小速度
public const int MaxSpeed = int.MaxValue; // 最大速度
#endregion
#region 地图相关
public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数
public const int lengthOfMap = 50000; // 地图长度
public const int rows = 50; // 行数
public const int cols = 50; // 列数

public const int numOfBirthPoint = 5;
public const int numOfGenerator = 9;
public const int numOfChest = 8;

public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标
{
XY ret = new(x * numOfPosGridPerCell + numOfPosGridPerCell / 2, y * numOfPosGridPerCell + numOfPosGridPerCell / 2);
return ret;
}
public static int PosGridToCellX(XY pos) // 求坐标所在的格子的x坐标
{
return pos.x / numOfPosGridPerCell;
}
public static int PosGridToCellY(XY pos) // 求坐标所在的格子的y坐标
{
return pos.y / numOfPosGridPerCell;
}
public static XY PosGridToCellXY(XY pos) // 求坐标所在的格子的Xy坐标
{
return new XY(pos.x / numOfPosGridPerCell, pos.y / numOfPosGridPerCell);
}
~~~

### 角色相关
~~~csharp
public const int numOfStudent = 4;
public const int characterRadius = numOfPosGridPerCell / 2 / 5 * 4; // 人物半径

public const int basicTreatSpeed = 100;
public const int basicFixSpeed = 100;
public const int basicSpeedOfOpeningOrLocking = 3280;
public const int basicStudentSpeedOfClimbingThroughWindows = 611;
public const int basicGhostSpeedOfClimbingThroughWindows = 1270;
public const int basicSpeedOfOpenChest = 1000;

public const int basicHp = 3000000; // 初始血量
public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间
public const int BeginGamingAddiction = 10003;
public const int MidGamingAddiction = 30000;
public const int basicTreatmentDegree = 1500000;
public const int basicTimeOfRescue = 1000;

public const int basicMoveSpeed = 1270; // 基本移动速度,单位:s-1
public const int characterMaxSpeed = 12000; // 最大速度
public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1

public const double basicConcealment = 1.0;
public const int basicAlertnessRadius = 10700;
public const int basicViewRange = 5 * numOfPosGridPerCell;
public const int maxNumOfPropInPropInventory = 3;
~~~

### 得分相关
~~~csharp
public static int TrickerScoreAttackStudent(int damage)
{
return damage * 100 / basicApOfGhost;
}
public const int TrickerScoreStudentBeAddicted = 50;
public const int TrickerScoreStudentBeStunned = 25;
public const int TrickerScoreStudentDie = 1000;

public static int StudentScoreFix(int degreeOfFix)
{
return degreeOfFix;
}
public const int StudentScoreFixed = 25;
public static int StudentScorePinDown(int timeOfPiningDown)
{
return 0;
}
public const int StudentScoreTrickerBeStunned = 25;
public const int StudentScoreRescue = 100;
public static int StudentScoreTreat(int degree)
{
return degree;
}
public const int StudentScoreEscape = 1000;
public const int ScorePropRemainHp = 20;
public const int ScorePropUseShield = 20;
public const int ScorePropUseSpear = 20;
public const int ScorePropAddAp = 10;
public const int ScorePropAddHp = 50;

~~~
### 攻击与子弹相关
~~~csharp
public const int basicApOfGhost = 1500000; // 捣蛋鬼攻击力
public const int MinAP = 0; // 最小攻击力
public const int MaxAP = int.MaxValue; // 最大攻击力

public const int factorDamageGenerator = 2;//子弹对电机的破坏=factorDamageGenerator*AP;
public const int bulletRadius = 200; // 默认子弹半径
public const int basicBulletNum = 3; // 基本初始子弹量

public const int basicCD = 3000; // 初始子弹冷却
public const int basicCastTime = 500;//基本前摇时间
public const int basicBackswing = 818;//基本后摇时间
public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长
public const int basicStunnedTimeOfStudent = 4130;

public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1
public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围
public const double basicAttackShortRange = 2700; // 基本近程攻击范围
public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围
~~~

### 技能相关
~~~csharp
public const int maxNumOfSkill = 3;
public const int commonSkillCD = 30000; // 普通技能标准冷却时间
public const int commonSkillTime = 10000; // 普通技能标准持续时间
~~~
### 道具相关
~~~csharp
public const int MinPropTypeNum = 1;
public const int MaxPropTypeNum = 10;
public const int PropRadius = numOfPosGridPerCell / 2;
public const int PropMoveSpeed = 3000;
public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell;
public const long PropProduceTime = 20000;
public const int PropDuration = 10000;

public const int ApPropAdd = basicApOfGhost * 12 / 10;
public const int ApSpearAdd = basicApOfGhost * 6 / 10;
public const int RemainHpWhenAddLife = 100;

public const int numOfKeyEachArea = 2;
public const int numOfPropTypeNotKey = 4;
public const int numOfTeachingBuilding = 3;
~~~
### 物体相关
~~~csharp
public const int degreeOfFixedGenerator = 10300000;
public const int degreeOfLockingOrOpeningTheDoor = 10000;
public const int degreeOfOpeningChest = 10000;
public const int degreeOfOpenedDoorway = 18000;
public const int maxNumOfPropInChest = 2;
public const int numOfGeneratorRequiredForRepair = 7;
public const int numOfGeneratorRequiredForEmergencyExit = 3;
~~~
请自行查看Logic/Preparation/Utility/GameData.cs

Loading…
Cancel
Save