| @@ -400,5 +400,3 @@ FodyWeavers.xsd | |||
| #THUAI playback file | |||
| *.thuaipb | |||
| Client/ | |||
| CSharpInterface/ | |||
| @@ -0,0 +1,20 @@ | |||
| using Preparation.Utility; | |||
| namespace GameClass.GameObj | |||
| { | |||
| // 为方便界面组做子弹爆炸特效,现引入“爆炸中的子弹”,在每帧发送给界面组 | |||
| public sealed class BombedBullet : GameObj | |||
| { | |||
| public override ShapeType Shape => ShapeType.Circle; | |||
| public override bool IsRigid => false; | |||
| public long MappingID { get; } | |||
| public Bullet bulletHasBombed; | |||
| public BombedBullet(Bullet bullet) : | |||
| base(bullet.Position, bullet.Radius, bullet.Place, GameObjType.BombedBullet) | |||
| { | |||
| this.bulletHasBombed = bullet; | |||
| this.MappingID = bullet.ID; | |||
| this.FacingDirection = bullet.FacingDirection; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,238 @@ | |||
| using Preparation.GameData; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public abstract class Bullet : ObjOfCharacter | |||
| { | |||
| /// <summary> | |||
| /// //攻击力 | |||
| /// </summary> | |||
| public abstract int AP { get; } | |||
| public abstract int Speed { get; } | |||
| private readonly bool hasSpear; | |||
| /// <summary> | |||
| /// 是否有矛 | |||
| /// </summary> | |||
| public bool HasSpear => hasSpear; | |||
| /// <summary> | |||
| /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target | |||
| /// </summary> | |||
| /// <param name="target">被尝试攻击者</param> | |||
| /// <returns>是否可以攻击到</returns> | |||
| public abstract bool CanAttack(GameObj target); | |||
| protected override bool IgnoreCollideExecutor(IGameObj targetObj) | |||
| { | |||
| if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) | |||
| return true; | |||
| return false; | |||
| } | |||
| public Bullet(Character player, int radius) : | |||
| base(player.Position, radius, PlaceType.Null, GameObjType.Bullet) | |||
| { | |||
| this.CanMove = true; | |||
| this.moveSpeed = this.Speed; | |||
| this.hasSpear = player.HasSpear; | |||
| this.Parent = player; | |||
| } | |||
| public override bool IsRigid => true; // 默认为true | |||
| public override ShapeType Shape => ShapeType.Circle; // 默认为圆形 | |||
| public abstract BulletType TypeOfBullet { get; } | |||
| } | |||
| internal sealed class AtomBomb : Bullet | |||
| { | |||
| public AtomBomb(Character player, int radius = GameData.bulletRadius) : | |||
| base(player, radius) | |||
| { | |||
| } | |||
| public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 7; | |||
| public const double BulletAttackRange = GameData.basicAttackRange / 9 * 7; | |||
| public override int AP => GameData.basicAp / 3 * 7; | |||
| public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| // 圆形攻击范围 | |||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.AtomBomb; | |||
| } | |||
| internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速 | |||
| { | |||
| public OrdinaryBullet(Character player, int radius = GameData.bulletRadius) : | |||
| base(player, radius) | |||
| { | |||
| } | |||
| public const double BulletBombRange = GameData.basicBulletBombRange / 6 * 5; | |||
| public const double BulletAttackRange = GameData.basicAttackRange / 2; | |||
| public override int AP => GameData.basicAp / 6 * 5; | |||
| public override int Speed => GameData.basicBulletMoveSpeed / 6 * 5; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| // 圆形攻击范围 | |||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.OrdinaryBullet; | |||
| } | |||
| internal sealed class FastBullet : Bullet // 1倍攻击范围,0.2倍攻击力,2倍速 | |||
| { | |||
| public FastBullet(Character player, int radius = GameData.bulletRadius) : | |||
| base(player, radius) | |||
| { | |||
| } | |||
| public const double BulletBombRange = GameData.basicBulletBombRange / 4 * 2; | |||
| public const double BulletAttackRange = GameData.basicAttackRange; | |||
| public override int AP => (int)(0.5 * GameData.basicAp); | |||
| public override int Speed => 5 * GameData.basicBulletMoveSpeed / 3; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| // 圆形攻击范围 | |||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.FastBullet; | |||
| } | |||
| internal sealed class LineBullet : Bullet // 直线爆炸,宽度1格,长度为2倍爆炸范围 | |||
| { | |||
| public LineBullet(Character player, int radius = GameData.bulletRadius) : | |||
| base(player, radius) | |||
| { | |||
| } | |||
| public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 4; | |||
| public const double BulletAttackRange = 0.1 * GameData.basicAttackRange; | |||
| public override int AP => GameData.basicAp / 3 * 2; | |||
| public override int Speed => GameData.basicBulletMoveSpeed / 3; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| double FacingAngle = Math.Atan2(this.FacingDirection.y, this.FacingDirection.x); | |||
| if (Math.Abs(FacingAngle - Math.PI / 2) < 1e-2) | |||
| { | |||
| if (target.Position.y - this.Position.y > BulletBombRange) | |||
| return false; | |||
| if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| else if (Math.Abs(FacingAngle - Math.PI * 3 / 2) < 1e-2) | |||
| { | |||
| if (target.Position.y - this.Position.y < -BulletBombRange) | |||
| return false; | |||
| if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| else if (Math.Abs(FacingAngle) < 1e-2) | |||
| { | |||
| if (target.Position.x - this.Position.x > BulletBombRange) | |||
| return false; | |||
| if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| else if (Math.Abs(FacingAngle - Math.PI) < 1e-2) | |||
| { | |||
| if (target.Position.x - this.Position.x < -BulletBombRange) | |||
| return false; | |||
| if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| double vertical = Math.Tan(FacingAngle + Math.PI / 2); | |||
| bool posValue = vertical * Math.Cos(FacingAngle) - Math.Sin(FacingAngle) > 0; | |||
| double dist; | |||
| dist = vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y) / Math.Sqrt(1 + vertical * vertical); | |||
| if (Math.Abs(dist) > BulletBombRange) | |||
| return false; | |||
| else if (dist < 0 && posValue) // 位于直线两侧 | |||
| return false; | |||
| vertical = Math.Tan(FacingAngle); | |||
| dist = Math.Abs(vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y)) / Math.Sqrt(1 + vertical * vertical); | |||
| if (dist > GameData.numOfPosGridPerCell / 2) | |||
| return false; | |||
| return true; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.LineBullet; | |||
| } | |||
| public static class BulletFactory | |||
| { | |||
| public static Bullet? GetBullet(Character character) | |||
| { | |||
| Bullet? newBullet = null; | |||
| switch (character.BulletOfPlayer) | |||
| { | |||
| case BulletType.AtomBomb: | |||
| newBullet = new AtomBomb(character); | |||
| break; | |||
| case BulletType.LineBullet: | |||
| newBullet = new LineBullet(character); | |||
| break; | |||
| case BulletType.FastBullet: | |||
| newBullet = new FastBullet(character); | |||
| break; | |||
| case BulletType.OrdinaryBullet: | |||
| newBullet = new OrdinaryBullet(character); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return newBullet; | |||
| } | |||
| public static int BulletRadius(BulletType bulletType) | |||
| { | |||
| switch (bulletType) | |||
| { | |||
| case BulletType.AtomBomb: | |||
| case BulletType.LineBullet: | |||
| case BulletType.FastBullet: | |||
| case BulletType.OrdinaryBullet: | |||
| default: | |||
| return GameData.bulletRadius; | |||
| } | |||
| } | |||
| public static double BulletAttackRange(BulletType bulletType) | |||
| { | |||
| switch (bulletType) | |||
| { | |||
| case BulletType.AtomBomb: | |||
| return AtomBomb.BulletAttackRange; | |||
| case BulletType.LineBullet: | |||
| return LineBullet.BulletAttackRange; | |||
| case BulletType.FastBullet: | |||
| return FastBullet.BulletAttackRange; | |||
| case BulletType.OrdinaryBullet: | |||
| return OrdinaryBullet.BulletAttackRange; | |||
| default: | |||
| return 0; | |||
| } | |||
| } | |||
| public static double BulletBombRange(BulletType bulletType) | |||
| { | |||
| switch (bulletType) | |||
| { | |||
| case BulletType.AtomBomb: | |||
| return AtomBomb.BulletBombRange; | |||
| case BulletType.LineBullet: | |||
| return LineBullet.BulletBombRange; | |||
| case BulletType.FastBullet: | |||
| return FastBullet.BulletBombRange; | |||
| case BulletType.OrdinaryBullet: | |||
| return OrdinaryBullet.BulletBombRange; | |||
| default: | |||
| return 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,172 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.InteropServices; | |||
| using System.Threading; | |||
| using Preparation.Utility; | |||
| using Preparation.GameData; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public partial class Character | |||
| { | |||
| private readonly BuffManeger buffManeger; | |||
| /// <summary> | |||
| /// 角色携带的buff管理器 | |||
| /// </summary> | |||
| private class BuffManeger | |||
| { | |||
| [StructLayout(LayoutKind.Explicit, Size = 8)] | |||
| private struct BuffValue // buff参数联合体类型,可能是int或double | |||
| { | |||
| [FieldOffset(0)] | |||
| public int iValue; | |||
| [FieldOffset(0)] | |||
| public double lfValue; | |||
| public BuffValue(int intValue) | |||
| { | |||
| this.lfValue = 0.0; | |||
| this.iValue = intValue; | |||
| } | |||
| public BuffValue(double longFloatValue) | |||
| { | |||
| this.iValue = 0; | |||
| this.lfValue = longFloatValue; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// buff列表 | |||
| /// </summary> | |||
| private readonly LinkedList<BuffValue>[] buffList; | |||
| private readonly object[] buffListLock; | |||
| private void AddBuff(BuffValue bf, int buffTime, BuffType buffType, Action ReCalculateFunc) | |||
| { | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| LinkedListNode<BuffValue> buffNode; | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| buffNode = buffList[(int)buffType].AddLast(bf); | |||
| } | |||
| ReCalculateFunc(); | |||
| Thread.Sleep(buffTime); | |||
| try | |||
| { | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| buffList[(int)buffType].Remove(buffNode); | |||
| } | |||
| } | |||
| catch | |||
| { | |||
| } | |||
| ReCalculateFunc(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| private int ReCalculateFloatBuff(BuffType buffType, int orgVal, int maxVal, int minVal) | |||
| { | |||
| double times = 1.0; | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| foreach (var add in buffList[(int)buffType]) | |||
| { | |||
| times *= add.lfValue; | |||
| } | |||
| } | |||
| return Math.Max(Math.Min((int)Math.Round(orgVal * times), maxVal), minVal); | |||
| } | |||
| public void AddMoveSpeed(double add, int buffTime, Action<int> SetNewMoveSpeed, int orgMoveSpeed) => AddBuff(new BuffValue(add), buffTime, BuffType.AddSpeed, () => SetNewMoveSpeed(ReCalculateFloatBuff(BuffType.AddSpeed, orgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed))); | |||
| public bool HasFasterSpeed | |||
| { | |||
| get { | |||
| lock (buffListLock[(int)BuffType.AddSpeed]) | |||
| { | |||
| return buffList[(int)BuffType.AddSpeed].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public void AddShield(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Shield, () => | |||
| {}); | |||
| public bool HasShield | |||
| { | |||
| get { | |||
| lock (buffListLock[(int)BuffType.Shield]) | |||
| { | |||
| return buffList[(int)BuffType.Shield].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public void AddLIFE(int totelTime) => AddBuff(new BuffValue(), totelTime, BuffType.AddLIFE, () => | |||
| {}); | |||
| public bool HasLIFE | |||
| { | |||
| get { | |||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||
| { | |||
| return buffList[(int)BuffType.AddLIFE].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public bool TryActivatingLIFE() | |||
| { | |||
| if (HasLIFE) | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||
| { | |||
| buffList[(int)BuffType.AddLIFE].Clear(); | |||
| } | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| public void AddSpear(int spearTime) => AddBuff(new BuffValue(), spearTime, BuffType.Spear, () => | |||
| {}); | |||
| public bool HasSpear | |||
| { | |||
| get { | |||
| lock (buffListLock[(int)BuffType.Spear]) | |||
| { | |||
| return buffList[(int)BuffType.Spear].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 清除所有buff | |||
| /// </summary> | |||
| public void ClearAll() | |||
| { | |||
| for (int i = 0; i < buffList.Length; ++i) | |||
| { | |||
| lock (buffListLock[i]) | |||
| { | |||
| buffList[i].Clear(); | |||
| } | |||
| } | |||
| } | |||
| public BuffManeger() | |||
| { | |||
| var buffTypeArray = Enum.GetValues(typeof(BuffType)); | |||
| buffList = new LinkedList<BuffValue>[buffTypeArray.Length]; | |||
| buffListLock = new object[buffList.Length]; | |||
| int i = 0; | |||
| foreach (BuffType type in buffTypeArray) | |||
| { | |||
| buffList[i] = new LinkedList<BuffValue>(); | |||
| buffListLock[i++] = new object(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,51 +0,0 @@ | |||
| using Preparation.Utility; | |||
| using System.Collections.Generic; | |||
| using System; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public partial class Character | |||
| { | |||
| private delegate bool CharacterActiveSkill(Character player); // 返回值:是否成功释放了技能 | |||
| private delegate void CharacterPassiveSkill(Character player); | |||
| private readonly CharacterActiveSkill commonSkill; | |||
| private readonly ActiveSkillType commonSkillType; | |||
| public ActiveSkillType CommonSkillType => commonSkillType; | |||
| private readonly CharacterType passiveSkillType; | |||
| public CharacterType PassiveSkillType => passiveSkillType; | |||
| public bool UseCommonSkill() | |||
| { | |||
| return commonSkill(this); | |||
| } | |||
| private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能 | |||
| public int TimeUntilCommonSkillAvailable | |||
| { | |||
| get => timeUntilCommonSkillAvailable; | |||
| set { | |||
| lock (gameObjLock) | |||
| timeUntilCommonSkillAvailable = value < 0 ? 0 : value; | |||
| } | |||
| } | |||
| readonly CharacterPassiveSkill passiveSkill; | |||
| public void UsePassiveSkill() | |||
| { | |||
| passiveSkill(this); | |||
| return; | |||
| } | |||
| public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType passiveSkillType, ActiveSkillType commonSkillType) : | |||
| base(initPos, initRadius, initPlace, GameObjType.Character) | |||
| { | |||
| this.CanMove = true; | |||
| this.score = 0; | |||
| this.propInventory = null; | |||
| this.buffManeger = new BuffManeger(); | |||
| // UsePassiveSkill(); //创建player时开始被动技能,这一过程也可以放到gamestart时进行 | |||
| // 这可以放在AddPlayer中做 | |||
| Debugger.Output(this, "constructed!"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,176 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.InteropServices; | |||
| using System.Threading; | |||
| using Preparation.Utility; | |||
| using Preparation.GameData; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public partial class Character | |||
| { | |||
| private readonly BuffManeger buffManeger; | |||
| /// <summary> | |||
| /// 角色携带的buff管理器 | |||
| /// </summary> | |||
| private class BuffManeger | |||
| { | |||
| [StructLayout(LayoutKind.Explicit, Size = 8)] | |||
| private struct BuffValue // buff参数联合体类型,可能是int或double | |||
| { | |||
| [FieldOffset(0)] | |||
| public int iValue; | |||
| [FieldOffset(0)] | |||
| public double lfValue; | |||
| public BuffValue(int intValue) | |||
| { | |||
| this.lfValue = 0.0; | |||
| this.iValue = intValue; | |||
| } | |||
| public BuffValue(double longFloatValue) | |||
| { | |||
| this.iValue = 0; | |||
| this.lfValue = longFloatValue; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// buff列表 | |||
| /// </summary> | |||
| private readonly LinkedList<BuffValue>[] buffList; | |||
| private readonly object[] buffListLock; | |||
| private void AddBuff(BuffValue bf, int buffTime, BuffType buffType, Action ReCalculateFunc) | |||
| { | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| LinkedListNode<BuffValue> buffNode; | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| buffNode = buffList[(int)buffType].AddLast(bf); | |||
| } | |||
| ReCalculateFunc(); | |||
| Thread.Sleep(buffTime); | |||
| try | |||
| { | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| buffList[(int)buffType].Remove(buffNode); | |||
| } | |||
| } | |||
| catch | |||
| { | |||
| } | |||
| ReCalculateFunc(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| private int ReCalculateFloatBuff(BuffType buffType, int orgVal, int maxVal, int minVal) | |||
| { | |||
| double times = 1.0; | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| foreach (var add in buffList[(int)buffType]) | |||
| { | |||
| times *= add.lfValue; | |||
| } | |||
| } | |||
| return Math.Max(Math.Min((int)Math.Round(orgVal * times), maxVal), minVal); | |||
| } | |||
| public void AddMoveSpeed(double add, int buffTime, Action<int> SetNewMoveSpeed, int orgMoveSpeed) => AddBuff(new BuffValue(add), buffTime, BuffType.AddSpeed, () => SetNewMoveSpeed(ReCalculateFloatBuff(BuffType.AddSpeed, orgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed))); | |||
| public bool HasFasterSpeed | |||
| { | |||
| get | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddSpeed]) | |||
| { | |||
| return buffList[(int)BuffType.AddSpeed].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public void AddShield(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Shield, () => | |||
| { }); | |||
| public bool HasShield | |||
| { | |||
| get | |||
| { | |||
| lock (buffListLock[(int)BuffType.Shield]) | |||
| { | |||
| return buffList[(int)BuffType.Shield].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public void AddLIFE(int totelTime) => AddBuff(new BuffValue(), totelTime, BuffType.AddLIFE, () => | |||
| { }); | |||
| public bool HasLIFE | |||
| { | |||
| get | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||
| { | |||
| return buffList[(int)BuffType.AddLIFE].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public bool TryActivatingLIFE() | |||
| { | |||
| if (HasLIFE) | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||
| { | |||
| buffList[(int)BuffType.AddLIFE].Clear(); | |||
| } | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| public void AddSpear(int spearTime) => AddBuff(new BuffValue(), spearTime, BuffType.Spear, () => | |||
| { }); | |||
| public bool HasSpear | |||
| { | |||
| get | |||
| { | |||
| lock (buffListLock[(int)BuffType.Spear]) | |||
| { | |||
| return buffList[(int)BuffType.Spear].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 清除所有buff | |||
| /// </summary> | |||
| public void ClearAll() | |||
| { | |||
| for (int i = 0; i < buffList.Length; ++i) | |||
| { | |||
| lock (buffListLock[i]) | |||
| { | |||
| buffList[i].Clear(); | |||
| } | |||
| } | |||
| } | |||
| public BuffManeger() | |||
| { | |||
| var buffTypeArray = Enum.GetValues(typeof(BuffType)); | |||
| buffList = new LinkedList<BuffValue>[buffTypeArray.Length]; | |||
| buffListLock = new object[buffList.Length]; | |||
| int i = 0; | |||
| foreach (BuffType type in buffTypeArray) | |||
| { | |||
| buffList[i] = new LinkedList<BuffValue>(); | |||
| buffListLock[i++] = new object(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| using GameClass.Skill; | |||
| using Preparation.Utility; | |||
| using System.Collections.Generic; | |||
| using System; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public partial class Character | |||
| { | |||
| private delegate bool CharacterActiveSkill(Character player); // 返回值:是否成功释放了技能 | |||
| private delegate void CharacterPassiveSkill(Character player); | |||
| private readonly CharacterActiveSkill commonSkill; | |||
| private readonly ActiveSkillType commonSkillType; | |||
| public ActiveSkillType CommonSkillType => commonSkillType; | |||
| private readonly CharacterType characterType; | |||
| public CharacterType CharacterType => characterType; | |||
| public bool UseCommonSkill() | |||
| { | |||
| return commonSkill(this); | |||
| } | |||
| private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能 | |||
| public int TimeUntilCommonSkillAvailable | |||
| { | |||
| get => timeUntilCommonSkillAvailable; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| timeUntilCommonSkillAvailable = value < 0 ? 0 : value; | |||
| } | |||
| } | |||
| readonly CharacterPassiveSkill passiveSkill; | |||
| public void UsePassiveSkill() | |||
| { | |||
| passiveSkill(this); | |||
| return; | |||
| } | |||
| public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType, ActiveSkillType commonSkillType) : | |||
| base(initPos, initRadius, initPlace, GameObjType.Character) | |||
| { | |||
| this.CanMove = true; | |||
| this.score = 0; | |||
| this.propInventory = null; | |||
| this.buffManeger = new BuffManeger(); | |||
| IPassiveSkill pSkill; | |||
| ICommonSkill cSkill; | |||
| switch (passiveSkillType) | |||
| { | |||
| case this.CharacterType.RecoverAfterBattle: | |||
| pSkill = new RecoverAfterBattle(); | |||
| break; | |||
| case this.CharacterType.SpeedUpWhenLeavingGrass: | |||
| pSkill = new SpeedUpWhenLeavingGrass(); | |||
| break; | |||
| case this.CharacterType.Vampire: | |||
| pSkill = new Vampire(); | |||
| break; | |||
| default: | |||
| pSkill = new NoPassiveSkill(); | |||
| break; | |||
| } | |||
| switch (commonSkillType) | |||
| { | |||
| case ActiveSkillType.BecomeAssassin: | |||
| cSkill = new BecomeAssassin(); | |||
| break; | |||
| case ActiveSkillType.BecomeVampire: | |||
| cSkill = new BecomeVampire(); | |||
| break; | |||
| case ActiveSkillType.NuclearWeapon: | |||
| cSkill = new NuclearWeapon(); | |||
| break; | |||
| case ActiveSkillType.SuperFast: | |||
| cSkill = new SuperFast(); | |||
| break; | |||
| default: | |||
| cSkill = new NoCommonSkill(); | |||
| break; | |||
| } | |||
| this.MaxHp = cSkill.MaxHp; | |||
| this.hp = cSkill.MaxHp; | |||
| this.OrgMoveSpeed = cSkill.MoveSpeed; | |||
| this.moveSpeed = cSkill.MoveSpeed; | |||
| this.cd = cSkill.CD; | |||
| this.maxBulletNum = cSkill.MaxBulletNum; | |||
| this.bulletNum = maxBulletNum; | |||
| this.bulletOfPlayer = pSkill.InitBullet; | |||
| this.OriBulletOfPlayer = pSkill.InitBullet; | |||
| this.passiveSkill = pSkill.SkillEffect; | |||
| this.commonSkill = cSkill.SkillEffect; | |||
| this.passiveSkillType = passiveSkillType; | |||
| this.commonSkillType = commonSkillType; | |||
| // UsePassiveSkill(); //创建player时开始被动技能,这一过程也可以放到gamestart时进行 | |||
| // 这可以放在AddPlayer中做 | |||
| Debugger.Output(this, "constructed!"); | |||
| } | |||
| } | |||
| } | |||
| @@ -11,9 +11,8 @@ namespace GameClass.GameObj | |||
| { | |||
| private readonly object beAttackedLock = new(); | |||
| #region 角色的基本属性及方法,包括与道具的交互方法 | |||
| /* | |||
| //THUAI5子弹 | |||
| #region 角色的基本属性及方法,包括与道具的交互方法 | |||
| /// <summary> | |||
| /// 装弹冷却 | |||
| /// </summary> | |||
| @@ -21,8 +20,9 @@ namespace GameClass.GameObj | |||
| public int CD | |||
| { | |||
| get => cd; | |||
| private | |||
| set { | |||
| private | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| cd = value; | |||
| @@ -35,13 +35,14 @@ namespace GameClass.GameObj | |||
| public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | |||
| protected int bulletNum; | |||
| public int BulletNum => bulletNum; // 目前持有的子弹数 | |||
| */ | |||
| public int MaxHp { get; protected set; } // 最大血量 | |||
| protected int hp; | |||
| public int HP | |||
| { | |||
| get => hp; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| hp = value <= MaxHp ? value : MaxHp; | |||
| } | |||
| @@ -55,13 +56,31 @@ namespace GameClass.GameObj | |||
| get => score; | |||
| } | |||
| // public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer); | |||
| public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer); | |||
| private double vampire = 0; // 回血率:0-1之间 | |||
| public double Vampire | |||
| { | |||
| get => vampire; | |||
| set { | |||
| set | |||
| { | |||
| if (value > 1) | |||
| lock (gameObjLock) | |||
| vampire = 1; | |||
| else if (value < 0) | |||
| lock (gameObjLock) | |||
| vampire = 0; | |||
| else | |||
| lock (gameObjLock) | |||
| vampire = value; | |||
| } | |||
| } | |||
| private double oriVampire = 0; | |||
| public double OriVampire | |||
| { | |||
| get => oriVampire; | |||
| set | |||
| { | |||
| if (value > 1) | |||
| lock (gameObjLock) | |||
| vampire = 1; | |||
| @@ -73,26 +92,27 @@ namespace GameClass.GameObj | |||
| vampire = value; | |||
| } | |||
| } | |||
| private double OriVampire { get; } | |||
| /* | |||
| public readonly BulletType OriBulletOfPlayer; | |||
| private BulletType bulletOfPlayer; | |||
| public BulletType BulletOfPlayer | |||
| { | |||
| get => bulletOfPlayer; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| bulletOfPlayer = value; | |||
| } | |||
| } | |||
| */ | |||
| private Prop? propInventory; | |||
| public Prop? PropInventory // 持有的道具 | |||
| { | |||
| get => propInventory; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| propInventory = value; | |||
| @@ -122,7 +142,8 @@ namespace GameClass.GameObj | |||
| public bool IsModifyingProp | |||
| { | |||
| get => isModifyingProp; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| isModifyingProp = value; | |||
| @@ -137,14 +158,15 @@ namespace GameClass.GameObj | |||
| public bool IsInvisible | |||
| { | |||
| get => isInvisible; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| isInvisible = value; | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| /// <summary> | |||
| /// 进行一次远程攻击 | |||
| /// </summary> | |||
| @@ -196,7 +218,7 @@ namespace GameClass.GameObj | |||
| return false; | |||
| } | |||
| } | |||
| */ | |||
| /// <summary> | |||
| /// 尝试加血 | |||
| /// </summary> | |||
| @@ -265,7 +287,7 @@ namespace GameClass.GameObj | |||
| Debugger.Output(this, " 's score has been subed to: " + score.ToString()); | |||
| } | |||
| } | |||
| /* | |||
| /// <summary> | |||
| /// 遭受攻击 | |||
| /// </summary> | |||
| @@ -326,7 +348,7 @@ namespace GameClass.GameObj | |||
| return hp <= 0; | |||
| } | |||
| } | |||
| */ | |||
| /// <summary> | |||
| /// 角色所属队伍ID | |||
| /// </summary> | |||
| @@ -334,7 +356,8 @@ namespace GameClass.GameObj | |||
| public long TeamID | |||
| { | |||
| get => teamID; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| teamID = value; | |||
| @@ -346,7 +369,8 @@ namespace GameClass.GameObj | |||
| public long PlayerID | |||
| { | |||
| get => playerID; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| playerID = value; | |||
| @@ -360,16 +384,17 @@ namespace GameClass.GameObj | |||
| public string Message | |||
| { | |||
| get => message; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| message = value; | |||
| } | |||
| } | |||
| } | |||
| #endregion | |||
| #endregion | |||
| #region 角色拥有的buff相关属性、方法 | |||
| #region 角色拥有的buff相关属性、方法 | |||
| public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManeger.AddMoveSpeed(add, buffTime, newVal => | |||
| { MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; }, | |||
| OrgMoveSpeed); | |||
| @@ -387,7 +412,8 @@ namespace GameClass.GameObj | |||
| private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | |||
| public Dictionary<BuffType, bool> Buff | |||
| { | |||
| get { | |||
| get | |||
| { | |||
| Dictionary<BuffType, bool> buff = new Dictionary<BuffType, bool>(); | |||
| foreach (BuffType type in buffTypeArray) | |||
| { | |||
| @@ -420,7 +446,7 @@ namespace GameClass.GameObj | |||
| hp = MaxHp; | |||
| } | |||
| } | |||
| #endregion | |||
| #endregion | |||
| public override void Reset() // 要加锁吗? | |||
| { | |||
| _ = AddDeathCount(); | |||
| @@ -29,8 +29,9 @@ namespace GameClass.GameObj | |||
| public XY Position | |||
| { | |||
| get => position; | |||
| protected | |||
| set { | |||
| protected | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| position = value; | |||
| @@ -43,7 +44,8 @@ namespace GameClass.GameObj | |||
| public XY FacingDirection | |||
| { | |||
| get => facingDirection; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| facingDirection = value; | |||
| } | |||
| @@ -54,7 +56,8 @@ namespace GameClass.GameObj | |||
| public bool CanMove | |||
| { | |||
| get => canMove; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| canMove = value; | |||
| @@ -66,7 +69,8 @@ namespace GameClass.GameObj | |||
| public bool IsMoving | |||
| { | |||
| get => isMoving; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| isMoving = value; | |||
| @@ -78,7 +82,8 @@ namespace GameClass.GameObj | |||
| public bool IsResetting | |||
| { | |||
| get => isResetting; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| isResetting = value; | |||
| @@ -92,7 +97,8 @@ namespace GameClass.GameObj | |||
| public PlaceType Place | |||
| { | |||
| get => place; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| place = value; | |||
| @@ -106,7 +112,8 @@ namespace GameClass.GameObj | |||
| public int MoveSpeed | |||
| { | |||
| get => moveSpeed; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| moveSpeed = value; | |||
| @@ -120,8 +127,9 @@ namespace GameClass.GameObj | |||
| public int OrgMoveSpeed | |||
| { | |||
| get => orgMoveSpeed; | |||
| protected | |||
| set { | |||
| protected | |||
| set | |||
| { | |||
| orgMoveSpeed = value; | |||
| } | |||
| } | |||
| @@ -12,7 +12,8 @@ namespace GameClass.GameObj | |||
| public ICharacter? Parent | |||
| { | |||
| get => parent; | |||
| set { | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| parent = value; | |||
| @@ -0,0 +1,24 @@ | |||
| using Preparation.Utility; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GameClass.GameObj | |||
| { | |||
| // 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组 | |||
| public class PickedProp : GameObj | |||
| { | |||
| public override ShapeType Shape => ShapeType.Circle; | |||
| public override bool IsRigid => false; | |||
| public long MappingID { get; } | |||
| public Prop PropHasPicked; | |||
| public PickedProp(Prop prop) : | |||
| base(prop.Position, prop.Radius, prop.Place, GameObjType.PickedProp) | |||
| { | |||
| this.PropHasPicked = prop; | |||
| this.MappingID = prop.ID; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,125 @@ | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using Preparation.GameData; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public abstract class Prop : ObjOfCharacter | |||
| { | |||
| protected bool laid = false; | |||
| public bool Laid => laid; // 道具是否放置在地图上 | |||
| public override bool IsRigid => true; | |||
| protected override bool IgnoreCollideExecutor(IGameObj targetObj) | |||
| { | |||
| if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet || targetObj.Type == GameObjType.Character) | |||
| return true; | |||
| return false; | |||
| } | |||
| public override ShapeType Shape => ShapeType.Square; | |||
| public abstract PropType GetPropType(); | |||
| public Prop(XY initPos, int radius = GameData.PropRadius) : | |||
| base(initPos, radius, PlaceType.Land, GameObjType.Prop) | |||
| { | |||
| this.CanMove = false; | |||
| this.moveSpeed = GameData.PropMoveSpeed; | |||
| } | |||
| public void SetNewPos(XY pos) | |||
| { | |||
| this.Position = pos; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 增益道具 | |||
| /// </summary> | |||
| public abstract class BuffProp : Prop | |||
| { | |||
| public BuffProp(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| } | |||
| ///// <summary> | |||
| ///// 坑人地雷 | |||
| ///// </summary> | |||
| // public abstract class DebuffMine : Prop | |||
| //{ | |||
| // public DebuffMine(XYPosition initPos) : base(initPos) { } | |||
| // } | |||
| #region 所有增益道具 | |||
| /// <summary> | |||
| /// 增加速度 | |||
| /// </summary> | |||
| public sealed class AddSpeed : BuffProp | |||
| { | |||
| public AddSpeed(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.addSpeed; | |||
| } | |||
| /// <summary> | |||
| /// 复活甲 | |||
| /// </summary> | |||
| public sealed class AddLIFE : BuffProp | |||
| { | |||
| public AddLIFE(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.addLIFE; | |||
| } | |||
| /// <summary> | |||
| /// 护盾 | |||
| /// </summary> | |||
| public sealed class Shield : BuffProp | |||
| { | |||
| public Shield(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Shield; | |||
| } | |||
| /// <summary> | |||
| /// 矛 | |||
| /// </summary> | |||
| public sealed class Spear : BuffProp | |||
| { | |||
| public Spear(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Spear; | |||
| } | |||
| #endregion | |||
| // #region 所有坑人地雷 | |||
| ///// <summary> | |||
| ///// 减速 | |||
| ///// </summary> | |||
| // public sealed class MinusSpeed : DebuffMine | |||
| //{ | |||
| // public MinusSpeed(XYPosition initPos) : base(initPos) { } | |||
| // public override PropType GetPropType() => PropType.minusSpeed; | |||
| // } | |||
| ///// <summary> | |||
| ///// 减少攻击力 | |||
| ///// </summary> | |||
| // public sealed class MinusAP : DebuffMine | |||
| //{ | |||
| // public MinusAP(XYPosition initPos) : base(initPos) { } | |||
| // public override PropType GetPropType() => PropType.minusAP; | |||
| // } | |||
| ///// <summary> | |||
| ///// 增加冷却 | |||
| ///// </summary> | |||
| // public sealed class AddCD : DebuffMine | |||
| //{ | |||
| // public AddCD(XYPosition initPos) : base(initPos) { } | |||
| // public override PropType GetPropType() => PropType.addCD; | |||
| // } | |||
| // #endregion | |||
| } | |||
| @@ -13,7 +13,8 @@ namespace GameClass.GameObj | |||
| private readonly List<Character> playerList; | |||
| public int Score | |||
| { | |||
| get { | |||
| get | |||
| { | |||
| int score = 0; | |||
| foreach (var player in playerList) | |||
| score += player.Score; | |||
| @@ -0,0 +1,219 @@ | |||
| using GameClass.GameObj; | |||
| using System.Threading; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using Preparation.GameData; | |||
| using System; | |||
| using Timothy.FrameRateTask; | |||
| namespace GameClass.Skill | |||
| { | |||
| public class BecomeVampire : ICommonSkill //化身吸血鬼 | |||
| { | |||
| private const int moveSpeed = GameData.basicMoveSpeed; | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = (int)(GameData.basicHp / 6 * 9.5); | |||
| public int MaxHp => maxHp; | |||
| private const int cd = GameData.basicCD; | |||
| public int CD => cd; | |||
| private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; | |||
| public int MaxBulletNum => maxBulletNum; | |||
| // 以上参数以后再改 | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 4; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object CommonSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return CommonSkillFactory.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 BecomeAssassin : ICommonSkill //化身刺客,隐身 | |||
| { | |||
| private const int moveSpeed = GameData.basicMoveSpeed / 3 * 5; | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = (int)(GameData.basicHp / 6 * 7.5); | |||
| public int MaxHp => maxHp; | |||
| private const int cd = GameData.basicCD; | |||
| public int CD => cd; | |||
| private const int maxBulletNum = GameData.basicBulletNum; | |||
| public int MaxBulletNum => maxBulletNum; | |||
| // 以上参数以后再改 | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10 * 6; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object CommonSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.IsInvisible = true; | |||
| Debugger.Output(player, "uses atombomb!"); | |||
| }, | |||
| () => { player.IsInvisible = false; }); | |||
| } | |||
| } | |||
| public class NuclearWeapon : ICommonSkill //核武器 | |||
| { | |||
| private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4; | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = GameData.basicHp; | |||
| public int MaxHp => maxHp; | |||
| private const int cd = GameData.basicCD; | |||
| public int CD => cd; | |||
| private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; | |||
| public int MaxBulletNum => maxBulletNum; | |||
| // 以上参数以后再改 | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 7; | |||
| public int DurationTime => GameData.commonSkillTime / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object CommonSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.AtomBomb; | |||
| Debugger.Output(player, "uses atombomb!"); | |||
| }, | |||
| () => { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||
| } | |||
| } | |||
| public class SuperFast : ICommonSkill //3倍速 | |||
| { | |||
| private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3; | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = GameData.basicHp / 6 * 4; | |||
| public int MaxHp => maxHp; | |||
| private const int cd = GameData.basicCD; | |||
| public int CD => cd; | |||
| private const int maxBulletNum = GameData.basicBulletNum * 4 / 3; | |||
| public int MaxBulletNum => maxBulletNum; | |||
| // 以上参数以后再改 | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10 * 4; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object CommonSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.AddMoveSpeed(this.DurationTime, 3.0); | |||
| Debugger.Output(player, "moves very fast!"); | |||
| }, | |||
| () => { }); | |||
| } | |||
| } | |||
| public class NoCommonSkill : ICommonSkill //这种情况不该发生,定义着以防意外 | |||
| { | |||
| private const int moveSpeed = GameData.basicMoveSpeed; | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = GameData.basicHp; | |||
| public int MaxHp => maxHp; | |||
| private const int cd = GameData.basicCD; | |||
| public int CD => cd; | |||
| private const int maxBulletNum = GameData.basicBulletNum; | |||
| public int MaxBulletNum => maxBulletNum; | |||
| // 以上参数以后再改 | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object CommonSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| public static class CommonSkillFactory | |||
| { | |||
| public static bool SkillEffect(ICommonSkill commonSkill, Character player, Action startSkill, Action endSkill) | |||
| { | |||
| lock (commonSkill.CommonSkillLock) | |||
| { | |||
| if (player.TimeUntilCommonSkillAvailable == 0) | |||
| { | |||
| player.TimeUntilCommonSkillAvailable = commonSkill.SkillCD; | |||
| new Thread | |||
| (() => | |||
| { | |||
| startSkill(); | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => !player.IsResetting, | |||
| () => | |||
| { | |||
| player.TimeUntilCommonSkillAvailable -= (int)GameData.frameDuration; | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: (long)(commonSkill.DurationTime) | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| }.Start(); | |||
| endSkill(); | |||
| Debugger.Output(player, "return to normal."); | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => player.TimeUntilCommonSkillAvailable > 0 && !player.IsResetting, | |||
| () => | |||
| { | |||
| player.TimeUntilCommonSkillAvailable -= (int)GameData.frameDuration; | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: (long)(commonSkill.SkillCD - commonSkill.DurationTime) | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| }.Start(); | |||
| player.TimeUntilCommonSkillAvailable = 0; | |||
| Debugger.Output(player, "CommonSkill is ready."); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| Debugger.Output(player, "CommonSkill is cooling down!"); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| using GameClass.GameObj; | |||
| using Preparation.Utility; | |||
| using System.Threading; | |||
| namespace GameClass.Skill | |||
| { | |||
| public interface IPassiveSkill | |||
| { | |||
| public BulletType InitBullet { get; } | |||
| public void SkillEffect(Character player); | |||
| } | |||
| public interface ICommonSkill | |||
| { | |||
| public int MoveSpeed { get; } | |||
| public int MaxHp { get; } | |||
| public int CD { get; } | |||
| public int MaxBulletNum { get; } | |||
| public bool SkillEffect(Character player); | |||
| public int DurationTime { get; } //技能持续时间 | |||
| public int SkillCD { get; } | |||
| public object CommonSkillLock { get; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,152 @@ | |||
| using System; | |||
| using System.Threading; | |||
| using GameClass.GameObj; | |||
| using Preparation.GameData; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using Timothy.FrameRateTask; | |||
| namespace GameClass.Skill //被动技能开局时就释放,持续到游戏结束 | |||
| { | |||
| public class RecoverAfterBattle : IPassiveSkill //脱战回血,普通子弹 | |||
| { | |||
| private readonly BulletType initBullet = BulletType.OrdinaryBullet; | |||
| public BulletType InitBullet => initBullet; | |||
| //以上参数以后再改 | |||
| public void SkillEffect(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倍速 | |||
| { | |||
| private readonly BulletType initBullet = BulletType.FastBullet; | |||
| public BulletType InitBullet => initBullet; | |||
| //以上参数以后再改 | |||
| public void SkillEffect(Character player) | |||
| { | |||
| PlaceType nowPlace = player.Place; | |||
| PlaceType lastPlace = nowPlace; | |||
| bool speedup = false; | |||
| const int SpeedUpTime = 2000; //加速时间:2s | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => true, | |||
| () => | |||
| { | |||
| lastPlace = nowPlace; | |||
| nowPlace = player.Place; | |||
| if ((lastPlace == PlaceType.Grass1 || lastPlace == PlaceType.Grass2 || lastPlace == PlaceType.Grass3) && nowPlace == PlaceType.Land) | |||
| { | |||
| 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 //被动就是吸血,普通子弹 | |||
| { | |||
| private readonly BulletType initBullet = BulletType.LineBullet; | |||
| public BulletType InitBullet => initBullet; | |||
| //以上参数以后再改 | |||
| public void SkillEffect(Character player) | |||
| { | |||
| player.OriVampire = 0.5; | |||
| player.Vampire = player.OriVampire; | |||
| } | |||
| } | |||
| public class NoPassiveSkill : IPassiveSkill //没技能,这种情况不应该发生,先定义着以防意外 | |||
| { | |||
| private readonly BulletType initBullet = BulletType.OrdinaryBullet; | |||
| public BulletType InitBullet => initBullet; | |||
| //以上参数以后再改 | |||
| public void SkillEffect(Character player) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -66,65 +66,28 @@ namespace GameEngine | |||
| { | |||
| if (!obj.IsAvailable && gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况 | |||
| return; | |||
| lock (obj.MoveLock) | |||
| obj.IsMoving = true; | |||
| double moveVecLength = 0.0; | |||
| double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差 | |||
| IGameObj? collisionObj = null; | |||
| bool isDestroyed = false; | |||
| new FrameRateTaskExecutor<int>( | |||
| () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting, | |||
| () => | |||
| { | |||
| moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||
| bool flag; // 循环标志 | |||
| do | |||
| { | |||
| flag = false; | |||
| collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength)); | |||
| if (collisionObj == null) | |||
| break; | |||
| lock (obj.MoveLock) | |||
| obj.IsMoving = true; | |||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||
| double moveVecLength = 0.0; | |||
| double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差 | |||
| IGameObj? collisionObj = null; | |||
| bool isDestroyed = false; | |||
| new FrameRateTaskExecutor<int>( | |||
| () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting, | |||
| () => | |||
| { | |||
| case AfterCollision.ContinueCheck: | |||
| flag = true; | |||
| break; | |||
| case AfterCollision.Destroyed: | |||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||
| isDestroyed = true; | |||
| return false; | |||
| case AfterCollision.MoveMax: | |||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||
| moveVecLength = 0; | |||
| break; | |||
| } | |||
| } while (flag); | |||
| moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||
| deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); | |||
| return true; | |||
| }, | |||
| GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond, | |||
| () => | |||
| { | |||
| int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||
| bool flag; | |||
| do | |||
| { | |||
| flag = false; | |||
| if (!isDestroyed) | |||
| { | |||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||
| if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null) | |||
| { | |||
| obj.Move(new XY(direction, moveVecLength)); | |||
| } | |||
| else | |||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||
| bool flag; // 循环标志 | |||
| do | |||
| { | |||
| flag = false; | |||
| collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength)); | |||
| if (collisionObj == null) | |||
| break; | |||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||
| { | |||
| case AfterCollision.ContinueCheck: | |||
| @@ -133,43 +96,81 @@ namespace GameEngine | |||
| case AfterCollision.Destroyed: | |||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||
| isDestroyed = true; | |||
| break; | |||
| return false; | |||
| case AfterCollision.MoveMax: | |||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||
| moveVecLength = 0; | |||
| break; | |||
| } | |||
| } while (flag); | |||
| deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); | |||
| return true; | |||
| }, | |||
| GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond, | |||
| () => | |||
| { | |||
| int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||
| bool flag; | |||
| do | |||
| { | |||
| flag = false; | |||
| if (!isDestroyed) | |||
| { | |||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||
| if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null) | |||
| { | |||
| obj.Move(new XY(direction, moveVecLength)); | |||
| } | |||
| else | |||
| { | |||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||
| { | |||
| case AfterCollision.ContinueCheck: | |||
| flag = true; | |||
| break; | |||
| case AfterCollision.Destroyed: | |||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||
| isDestroyed = true; | |||
| break; | |||
| case AfterCollision.MoveMax: | |||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||
| moveVecLength = 0; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } while (flag); | |||
| if (leftTime > 0) | |||
| { | |||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||
| } | |||
| } | |||
| } while (flag); | |||
| if (leftTime > 0) | |||
| lock (obj.MoveLock) | |||
| obj.IsMoving = false; // 结束移动 | |||
| EndMove(obj); | |||
| return 0; | |||
| }, | |||
| maxTotalDuration: moveTime | |||
| ) | |||
| { | |||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||
| } | |||
| lock (obj.MoveLock) | |||
| obj.IsMoving = false; // 结束移动 | |||
| EndMove(obj); | |||
| return 0; | |||
| }, | |||
| maxTotalDuration: moveTime | |||
| ) { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!"); | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!"); | |||
| #if DEBUG | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: Object moving time exceed for once."); | |||
| } | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: Object moving time exceed for once."); | |||
| } | |||
| #endif | |||
| } | |||
| }.Start(); | |||
| } | |||
| }.Start(); | |||
| } | |||
| ).Start(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -54,7 +54,8 @@ namespace Gaming | |||
| // ActivateMine((Character)obj, (Mine)collisionObj); | |||
| // return MoveEngine.AfterCollision.ContinueCheck; | |||
| //} | |||
| return MoveEngine.AfterCollision.MoveMax; }, | |||
| return MoveEngine.AfterCollision.MoveMax; | |||
| }, | |||
| EndMove: obj => | |||
| { | |||
| // Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | |||
| @@ -4,7 +4,7 @@ namespace Preparation.GameData | |||
| { | |||
| public static class GameData | |||
| { | |||
| #region 基本常数与常方法 | |||
| #region 基本常数与常方法 | |||
| public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | |||
| public const int numOfStepPerSecond = 20; // 每秒行走的步数 | |||
| public const int lengthOfMap = 50000; // 地图长度 | |||
| @@ -35,8 +35,8 @@ namespace Preparation.GameData | |||
| } | |||
| public static int numOfBirthPoint = 5; | |||
| #endregion | |||
| #region 角色相关 | |||
| #endregion | |||
| #region 角色相关 | |||
| /// <summary> | |||
| /// 玩家相关 | |||
| /// </summary> | |||
| @@ -71,9 +71,9 @@ namespace Preparation.GameData | |||
| public const long GemProduceTime = 10000; | |||
| public const long PropProduceTime = 10000; | |||
| public const int PropDuration = 10000; | |||
| #endregion | |||
| #region 游戏帧相关 | |||
| #endregion | |||
| #region 游戏帧相关 | |||
| public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | |||
| #endregion | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -21,7 +21,7 @@ namespace Preparation.Utility | |||
| { | |||
| return "(" + x.ToString() + "," + y.ToString() + ")"; | |||
| } | |||
| public static int operator*(XY v1, XY v2) | |||
| public static int operator *(XY v1, XY v2) | |||
| { | |||
| return (v1.x * v2.x) + (v1.y * v2.y); | |||
| } | |||
| @@ -5,23 +5,17 @@ VisualStudioVersion = 17.0.32014.148 | |||
| MinimumVisualStudioVersion = 10.0.40219.1 | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}" | |||
| EndProject | |||
| <<<<<<< HEAD | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameClass", "GameClass\GameClass.csproj", "{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{91448D70-61C3-499F-9B27-979E16DC9E64}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gaming", "Gaming\Gaming.csproj", "{BE9E3584-93C0-4E0F-8DAC-967CF4792709}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MapGenerator", "MapGenerator\MapGenerator.csproj", "{9BC673F1-14B1-4203-944D-474BD0F64EDC}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preparation", "Preparation\Preparation.csproj", "{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}" | |||
| ======= | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\proto\Protos.csproj", "{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}" | |||
| >>>>>>> 9f4b5ac18b94330559cd560708f4100ae913260e | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}" | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| @@ -33,28 +27,18 @@ Global | |||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| <<<<<<< HEAD | |||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| ======= | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| @@ -63,14 +47,10 @@ Global | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| <<<<<<< HEAD | |||
| >>>>>>> 9f4b5ac18b94330559cd560708f4100ae913260e | |||
| ======= | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| >>>>>>> 3fa94addd0e0b62765b62c0788f217f7cf25b7c1 | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||