using Preparation.GameData;
using Preparation.Interface;
using Preparation.Utility;
using System;
using System.Collections.Generic;
using System.Threading;
namespace GameClass.GameObj
{
public partial class Character : GameObj, ICharacter // 负责人LHR摆烂终了
{
private readonly object beAttackedLock = new();
#region 角色的基本属性及方法,包括与道具的交互方法
///
/// 装弹冷却
///
protected int cd;
public int CD
{
get => cd;
private
set
{
lock (gameObjLock)
{
cd = value;
Debugger.Output(this, string.Format("'s CD has been set to: {0}.", value));
}
}
}
public int OrgCD { get; protected set; }
protected int maxBulletNum;
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
{
lock (gameObjLock)
hp = value <= MaxHp ? value : MaxHp;
}
}
private int deathCount = 0;
public int DeathCount => deathCount; // 玩家的死亡次数
private int score = 0;
public int Score
{
get => score;
}
public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer);
private double vampire = 0; // 回血率:0-1之间
public double Vampire
{
get => vampire;
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;
else if (value < 0)
lock (gameObjLock)
vampire = 0;
else
lock (gameObjLock)
vampire = value;
}
}
public readonly BulletType OriBulletOfPlayer;
private BulletType bulletOfPlayer;
public BulletType BulletOfPlayer
{
get => bulletOfPlayer;
set
{
lock (gameObjLock)
bulletOfPlayer = value;
}
}
private Prop? propInventory;
public Prop? PropInventory // 持有的道具
{
get => propInventory;
set
{
lock (gameObjLock)
{
propInventory = value;
Debugger.Output(this, " prop becomes " + (PropInventory == null ? "null" : PropInventory.ToString()));
}
}
}
///
/// 使用物品栏中的道具
///
/// 被使用的道具
public Prop? UseProp()
{
lock (gameObjLock)
{
var oldProp = PropInventory;
PropInventory = null;
return oldProp;
}
}
///
/// 是否正在更换道具(包括捡起与抛出)
///
private bool isModifyingProp = false;
public bool IsModifyingProp
{
get => isModifyingProp;
set
{
lock (gameObjLock)
{
isModifyingProp = value;
}
}
}
///
/// 是否在隐身
///
private bool isInvisible = false;
public bool IsInvisible
{
get => isInvisible;
set
{
lock (gameObjLock)
{
isInvisible = value;
}
}
}
///
/// 进行一次远程攻击
///
/// 子弹初始位置偏差值
/// 攻击操作发出的子弹
public Bullet? RemoteAttack(XY posOffset)
{
if (TrySubBulletNum())
return ProduceOneBullet(this.Position + posOffset);
else
return null;
}
protected Bullet? ProduceOneBullet(XY initPos)
{
var newBullet = BulletFactory.GetBullet(this);
newBullet?.SetPosition(initPos);
return newBullet;
}
///
/// 尝试将子弹数量减1
///
/// 减操作是否成功
private bool TrySubBulletNum()
{
lock (gameObjLock)
{
if (bulletNum > 0)
{
--bulletNum;
return true;
}
return false;
}
}
///
/// 尝试将子弹数量加1
///
/// 加操作是否成功
public bool TryAddBulletNum()
{
lock (gameObjLock)
{
if (bulletNum < maxBulletNum)
{
++bulletNum;
return true;
}
return false;
}
}
///
/// 尝试加血
///
/// 欲加量
/// 加操作是否成功
public bool TryAddHp(int add)
{
if (hp < MaxHp)
{
lock (gameObjLock)
hp = MaxHp > hp + add ? hp + add : MaxHp;
Debugger.Output(this, " hp has added to: " + hp.ToString());
return true;
}
return false;
}
///
/// 尝试减血
///
/// 减血量
/// 减操作是否成功
public bool TrySubHp(int sub)
{
if (hp > 0)
{
lock (gameObjLock)
hp = 0 >= hp - sub ? 0 : hp - sub;
Debugger.Output(this, " hp has subed to: " + hp.ToString());
return true;
}
return false;
}
///
/// 增加死亡次数
///
/// 当前死亡次数
private int AddDeathCount()
{
lock (gameObjLock)
{
++deathCount;
return deathCount;
}
}
///
/// 加分
///
/// 增加量
public void AddScore(int add)
{
lock (gameObjLock)
{
score += add;
Debugger.Output(this, " 's score has been added to: " + score.ToString());
}
}
///
/// 减分
///
/// 减少量
public void SubScore(int sub)
{
lock (gameObjLock)
{
score -= sub;
Debugger.Output(this, " 's score has been subed to: " + score.ToString());
}
}
///
/// 遭受攻击
///
///
///
/// 伤害来源
/// 人物在受到攻击后死了吗
public bool BeAttack(Bullet bullet)
{
lock (beAttackedLock)
{
if (hp <= 0)
return false; // 原来已经死了
if (bullet.Parent.TeamID != this.TeamID)
{
if (HasShield)
{
if (bullet.HasSpear)
_ = TrySubHp(bullet.AP);
else
return false;
}
else
{
TrySubHp(bullet.AP);
}
#if DEBUG
Console.WriteLine($"PlayerID:{ID} is being shot! Now his hp is {hp}.");
#endif
if (hp <= 0)
TryActivatingLIFE(); // 如果有复活甲
}
return hp <= 0;
}
}
///
/// 攻击被反弹,反弹伤害不会再被反弹
///
///
///
/// 反弹伤害者
/// 是否因反弹伤害而死
private bool BeBounced(int subHP, bool hasSpear, Character? bouncer)
{
lock (beAttackedLock)
{
if (hp <= 0)
return false;
if (!(bouncer?.TeamID == this.TeamID))
{
if (hasSpear || !HasShield)
_ = TrySubHp(subHP);
if (hp <= 0)
TryActivatingLIFE();
}
return hp <= 0;
}
}
///
/// 角色所属队伍ID
///
private long teamID = long.MaxValue;
public long TeamID
{
get => teamID;
set
{
lock (gameObjLock)
{
teamID = value;
Debugger.Output(this, " joins in the team: " + value.ToString());
}
}
}
private long playerID = long.MaxValue;
public long PlayerID
{
get => playerID;
set
{
lock (gameObjLock)
{
playerID = value;
}
}
}
///
/// 角色携带的信息
///
private string message = "THUAI5";
public string Message
{
get => message;
set
{
lock (gameObjLock)
{
message = value;
}
}
}
#endregion
#region 角色拥有的buff相关属性、方法
public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManeger.AddMoveSpeed(add, buffTime, newVal =>
{ MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; },
OrgMoveSpeed);
public bool HasFasterSpeed => buffManeger.HasFasterSpeed;
public void AddShield(int shieldTime) => buffManeger.AddShield(shieldTime);
public bool HasShield => buffManeger.HasShield;
public void AddLIFE(int LIFETime) => buffManeger.AddLIFE(LIFETime);
public bool HasLIFE => buffManeger.HasLIFE;
public void AddSpear(int spearTime) => buffManeger.AddSpear(spearTime);
public bool HasSpear => buffManeger.HasSpear;
private Array buffTypeArray = Enum.GetValues(typeof(BuffType));
public Dictionary Buff
{
get
{
Dictionary buff = new Dictionary();
foreach (BuffType type in buffTypeArray)
{
if (type != BuffType.Null)
buff.Add(type, GetBuffStatus(type));
}
return buff;
}
}
private bool GetBuffStatus(BuffType type)
{
switch (type)
{
case BuffType.Spear:
return this.HasSpear;
case BuffType.AddSpeed:
return this.HasFasterSpeed;
case BuffType.Shield:
return this.HasShield;
case BuffType.AddLIFE:
return this.HasLIFE;
default:
return false;
}
}
private void TryActivatingLIFE()
{
if (buffManeger.TryActivatingLIFE())
{
hp = MaxHp;
}
}
#endregion
public override void Reset() // 要加锁吗?
{
_ = AddDeathCount();
base.Reset();
this.MoveSpeed = OrgMoveSpeed;
HP = MaxHp;
PropInventory = null;
// BulletOfPlayer = OriBulletOfPlayer;
// lock (gameObjLock)
// bulletNum = maxBulletNum;
buffManeger.ClearAll();
IsInvisible = false;
this.Vampire = this.OriVampire;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Circle;
protected override bool IgnoreCollideExecutor(IGameObj targetObj)
{
if (targetObj.Type == GameObjType.BirthPoint)
{
if (object.ReferenceEquals(((BirthPoint)targetObj).Parent, this)) // 自己的出生点可以忽略碰撞
{
return true;
}
}
else if (targetObj.Type == GameObjType.Prop) // 自己队的地雷忽略碰撞
{
return true;
}
return false;
}
}
}