Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / Role.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 角色基类
  7. /// </summary>
  8. public abstract partial class Role : ActivityObject
  9. {
  10. /// <summary>
  11. /// 是否是 Ai
  12. /// </summary>
  13. public bool IsAi { get; protected set; } = false;
  14.  
  15. /// <summary>
  16. /// 角色属性
  17. /// </summary>
  18. public RoleState RoleState { get; } = new RoleState();
  19. /// <summary>
  20. /// 默认攻击对象层级
  21. /// </summary>
  22. public const uint DefaultAttackLayer = PhysicsLayer.Player | PhysicsLayer.Enemy | PhysicsLayer.Wall | PhysicsLayer.Prop;
  23. /// <summary>
  24. /// 伤害区域
  25. /// </summary>
  26. [Export, ExportFillNode]
  27. public Area2D HurtArea { get; set; }
  28.  
  29. /// <summary>
  30. /// 所属阵营
  31. /// </summary>
  32. public CampEnum Camp;
  33.  
  34. /// <summary>
  35. /// 攻击目标的碰撞器所属层级, 数据源自于: PhysicsLayer
  36. /// </summary>
  37. public uint AttackLayer { get; set; } = PhysicsLayer.Wall;
  38.  
  39. /// <summary>
  40. /// 携带的被动道具包裹
  41. /// </summary>
  42. public List<BuffProp> BuffPropPack { get; } = new List<BuffProp>();
  43.  
  44. /// <summary>
  45. /// 携带的主动道具包裹
  46. /// </summary>
  47. public Package<ActiveProp> ActivePropsPack { get; private set; }
  48.  
  49. /// <summary>
  50. /// 角色携带的武器背包
  51. /// </summary>
  52. public Package<Weapon> WeaponPack { get; private set; }
  53.  
  54. /// <summary>
  55. /// 武器挂载点
  56. /// </summary>
  57. [Export, ExportFillNode]
  58. public MountRotation MountPoint { get; set; }
  59. /// <summary>
  60. /// 背后武器的挂载点
  61. /// </summary>
  62. [Export, ExportFillNode]
  63. public Marker2D BackMountPoint { get; set; }
  64.  
  65. /// <summary>
  66. /// 互动碰撞区域
  67. /// </summary>
  68. [Export, ExportFillNode]
  69. public Area2D InteractiveArea { get; set; }
  70. /// <summary>
  71. /// 脸的朝向
  72. /// </summary>
  73. public FaceDirection Face { get => _face; set => SetFace(value); }
  74. private FaceDirection _face;
  75.  
  76. /// <summary>
  77. /// 是否死亡
  78. /// </summary>
  79. public bool IsDie { get; private set; }
  80. /// <summary>
  81. /// 血量
  82. /// </summary>
  83. public int Hp
  84. {
  85. get => _hp;
  86. set
  87. {
  88. int temp = _hp;
  89. _hp = Mathf.Clamp(value, 0, _maxHp);
  90. if (temp != _hp)
  91. {
  92. OnChangeHp(_hp);
  93. }
  94. }
  95. }
  96. private int _hp = 20;
  97.  
  98. /// <summary>
  99. /// 最大血量
  100. /// </summary>
  101. public int MaxHp
  102. {
  103. get => _maxHp;
  104. set
  105. {
  106. int temp = _maxHp;
  107. _maxHp = value;
  108. //最大血量值改变
  109. if (temp != _maxHp)
  110. {
  111. OnChangeMaxHp(_maxHp);
  112. }
  113. //调整血量
  114. if (Hp > _maxHp)
  115. {
  116. Hp = _maxHp;
  117. }
  118. }
  119. }
  120. private int _maxHp = 20;
  121. /// <summary>
  122. /// 当前护盾值
  123. /// </summary>
  124. public int Shield
  125. {
  126. get => _shield;
  127. set
  128. {
  129. int temp = _shield;
  130. _shield = value;
  131. //护盾被破坏
  132. if (temp > 0 && _shield <= 0 && _maxShield > 0)
  133. {
  134. OnShieldDestroy();
  135. }
  136. //护盾值改变
  137. if (temp != _shield)
  138. {
  139. OnChangeShield(_shield);
  140. }
  141. }
  142. }
  143. private int _shield = 0;
  144.  
  145. /// <summary>
  146. /// 最大护盾值
  147. /// </summary>
  148. public int MaxShield
  149. {
  150. get => _maxShield;
  151. set
  152. {
  153. int temp = _maxShield;
  154. _maxShield = value;
  155. //最大护盾值改变
  156. if (temp != _maxShield)
  157. {
  158. OnChangeMaxShield(_maxShield);
  159. }
  160. //调整护盾值
  161. if (Shield > _maxShield)
  162. {
  163. Shield = _maxShield;
  164. }
  165. }
  166. }
  167. private int _maxShield = 0;
  168.  
  169. /// <summary>
  170. /// 无敌状态
  171. /// </summary>
  172. public bool Invincible
  173. {
  174. get => _invincible;
  175. set
  176. {
  177. if (_invincible != value)
  178. {
  179. if (value) //无敌状态
  180. {
  181. HurtArea.CollisionLayer = _currentLayer;
  182. _flashingInvincibleTimer = -1;
  183. _flashingInvincibleFlag = false;
  184. }
  185. else //正常状态
  186. {
  187. HurtArea.CollisionLayer = _currentLayer;
  188. SetBlendAlpha(1);
  189. }
  190. }
  191.  
  192. _invincible = value;
  193. }
  194. }
  195.  
  196. private bool _invincible = false;
  197. /// <summary>
  198. /// 当前角色所看向的对象, 也就是枪口指向的对象
  199. /// </summary>
  200. public ActivityObject LookTarget { get; set; }
  201. /// <summary>
  202. /// 当前可以互动的物体
  203. /// </summary>
  204. public ActivityObject InteractiveItem { get; private set; }
  205.  
  206. //初始缩放
  207. private Vector2 _startScale;
  208. //所有角色碰撞的物体
  209. private readonly List<ActivityObject> _interactiveItemList = new List<ActivityObject>();
  210. //当前可互动的物体
  211. private CheckInteractiveResult _currentResultData;
  212. private uint _currentLayer;
  213. //闪烁计时器
  214. private float _flashingInvincibleTimer = -1;
  215. //闪烁状态
  216. private bool _flashingInvincibleFlag = false;
  217. //闪烁动画协程id
  218. private long _invincibleFlashingId = -1;
  219. //护盾恢复计时器
  220. private float _shieldRecoveryTimer = 0;
  221.  
  222. /// <summary>
  223. /// 当血量改变时调用
  224. /// </summary>
  225. protected virtual void OnChangeHp(int hp)
  226. {
  227. }
  228.  
  229. /// <summary>
  230. /// 当最大血量改变时调用
  231. /// </summary>
  232. protected virtual void OnChangeMaxHp(int maxHp)
  233. {
  234. }
  235. /// <summary>
  236. /// 护盾值改变时调用
  237. /// </summary>
  238. protected virtual void OnChangeShield(int shield)
  239. {
  240. }
  241.  
  242. /// <summary>
  243. /// 最大护盾值改变时调用
  244. /// </summary>
  245. protected virtual void OnChangeMaxShield(int maxShield)
  246. {
  247. }
  248.  
  249. /// <summary>
  250. /// 当护盾被破坏时调用
  251. /// </summary>
  252. protected virtual void OnShieldDestroy()
  253. {
  254. }
  255.  
  256. /// <summary>
  257. /// 当受伤时调用
  258. /// </summary>
  259. /// <param name="damage">受到的伤害</param>
  260. /// <param name="realHarm">是否受到真实伤害, 如果为false, 则表示该伤害被互动格挡掉了</param>
  261. protected virtual void OnHit(int damage, bool realHarm)
  262. {
  263. }
  264.  
  265. /// <summary>
  266. /// 受到伤害时调用, 用于改变受到的伤害值
  267. /// </summary>
  268. /// <param name="damage">受到的伤害</param>
  269. protected virtual int OnHandlerHurt(int damage)
  270. {
  271. return damage;
  272. }
  273. /// <summary>
  274. /// 当可互动的物体改变时调用, result 参数为 null 表示变为不可互动
  275. /// </summary>
  276. /// <param name="prev">上一个互动的物体</param>
  277. /// <param name="result">当前物体, 检测是否可互动时的返回值</param>
  278. protected virtual void ChangeInteractiveItem(CheckInteractiveResult prev, CheckInteractiveResult result)
  279. {
  280. }
  281.  
  282. /// <summary>
  283. /// 死亡时调用
  284. /// </summary>
  285. protected virtual void OnDie()
  286. {
  287. }
  288.  
  289. /// <summary>
  290. /// 当往背包中添加道具时调用
  291. /// </summary>
  292. protected virtual void OnPushProp(Prop prop)
  293. {
  294. }
  295.  
  296. /// <summary>
  297. /// 当从背包中移除道具时调用
  298. /// </summary>
  299. protected virtual void OnRemoveProp(Prop prop)
  300. {
  301. }
  302.  
  303. public override void OnInit()
  304. {
  305. ActivePropsPack = new Package<ActiveProp>(this);
  306. WeaponPack = new Package<Weapon>(this);
  307. _startScale = Scale;
  308. MountPoint.Master = this;
  309. HurtArea.CollisionLayer = CollisionLayer;
  310. HurtArea.CollisionMask = 0;
  311. _currentLayer = HurtArea.CollisionLayer;
  312. Face = FaceDirection.Right;
  313. //连接互动物体信号
  314. InteractiveArea.BodyEntered += _OnPropsEnter;
  315. InteractiveArea.BodyExited += _OnPropsExit;
  316. }
  317.  
  318. protected override void Process(float delta)
  319. {
  320. //看向目标
  321. if (LookTarget != null)
  322. {
  323. Vector2 pos = LookTarget.GlobalPosition;
  324. //脸的朝向
  325. var gPos = GlobalPosition;
  326. if (pos.X > gPos.X && Face == FaceDirection.Left)
  327. {
  328. Face = FaceDirection.Right;
  329. }
  330. else if (pos.X < gPos.X && Face == FaceDirection.Right)
  331. {
  332. Face = FaceDirection.Left;
  333. }
  334. //枪口跟随目标
  335. MountPoint.SetLookAt(pos);
  336. }
  337. //检查可互动的物体
  338. bool findFlag = false;
  339. for (int i = 0; i < _interactiveItemList.Count; i++)
  340. {
  341. var item = _interactiveItemList[i];
  342. if (item == null || item.IsDestroyed)
  343. {
  344. _interactiveItemList.RemoveAt(i--);
  345. }
  346. else
  347. {
  348. //找到可互动的物体了
  349. if (!findFlag)
  350. {
  351. var result = item.CheckInteractive(this);
  352. var prev = _currentResultData;
  353. _currentResultData = result;
  354. if (result.CanInteractive) //可以互动
  355. {
  356. findFlag = true;
  357. if (InteractiveItem != item) //更改互动物体
  358. {
  359. InteractiveItem = item;
  360. ChangeInteractiveItem(prev, result);
  361. }
  362. else if (result.Type != _currentResultData.Type) //切换状态
  363. {
  364. ChangeInteractiveItem(prev, result);
  365. }
  366. }
  367. }
  368. }
  369. }
  370. //没有可互动的物体
  371. if (!findFlag && InteractiveItem != null)
  372. {
  373. var prev = _currentResultData;
  374. _currentResultData = null;
  375. InteractiveItem = null;
  376. ChangeInteractiveItem(prev, null);
  377. }
  378.  
  379. //无敌状态, 播放闪烁动画
  380. if (Invincible)
  381. {
  382. _flashingInvincibleTimer -= delta;
  383. if (_flashingInvincibleTimer <= 0)
  384. {
  385. _flashingInvincibleTimer = 0.15f;
  386. if (_flashingInvincibleFlag)
  387. {
  388. _flashingInvincibleFlag = false;
  389. SetBlendAlpha(0.7f);
  390. }
  391. else
  392. {
  393. _flashingInvincibleFlag = true;
  394. SetBlendAlpha(0);
  395. }
  396. }
  397.  
  398. _shieldRecoveryTimer = 0;
  399. }
  400. else //恢复护盾
  401. {
  402. if (Shield < MaxShield)
  403. {
  404. _shieldRecoveryTimer += delta;
  405. if (_shieldRecoveryTimer >= RoleState.ShieldRecoveryTime) //时间到, 恢复
  406. {
  407. Shield++;
  408. _shieldRecoveryTimer = 0;
  409. }
  410. }
  411. else
  412. {
  413. _shieldRecoveryTimer = 0;
  414. }
  415. }
  416.  
  417. //被动道具更新
  418. if (BuffPropPack.Count > 0)
  419. {
  420. var buffProps = BuffPropPack.ToArray();
  421. foreach (var prop in buffProps)
  422. {
  423. prop.PackProcess(delta);
  424. }
  425. }
  426. //主动道具调用更新
  427. var props = (Prop[])ActivePropsPack.ItemSlot.Clone();
  428. foreach (var prop in props)
  429. {
  430. if (prop != null)
  431. {
  432. prop.PackProcess(delta);
  433. }
  434. }
  435. }
  436.  
  437. /// <summary>
  438. /// 当武器放到后背时调用, 用于设置武器位置和角度
  439. /// </summary>
  440. /// <param name="weapon">武器实例</param>
  441. /// <param name="index">放入武器袋的位置</param>
  442. public virtual void OnPutBackMount(Weapon weapon, int index)
  443. {
  444. if (index < 8)
  445. {
  446. if (index % 2 == 0)
  447. {
  448. weapon.Position = new Vector2(-4, 3);
  449. weapon.RotationDegrees = 90 - (index / 2f) * 20;
  450. weapon.Scale = new Vector2(-1, 1);
  451. }
  452. else
  453. {
  454. weapon.Position = new Vector2(4, 3);
  455. weapon.RotationDegrees = 270 + (index - 1) / 2f * 20;
  456. weapon.Scale = new Vector2(1, 1);
  457. }
  458. }
  459. else
  460. {
  461. weapon.Visible = false;
  462. }
  463. }
  464. protected override void OnAffiliationChange()
  465. {
  466. //身上的武器的所属区域也得跟着变
  467. WeaponPack.ForEach((weapon, i) =>
  468. {
  469. if (AffiliationArea != null)
  470. {
  471. AffiliationArea.InsertItem(weapon);
  472. }
  473. else if (weapon.AffiliationArea != null)
  474. {
  475. weapon.AffiliationArea.RemoveItem(weapon);
  476. }
  477. });
  478. }
  479.  
  480. /// <summary>
  481. /// 是否是满血
  482. /// </summary>
  483. public bool IsHpFull()
  484. {
  485. return Hp >= MaxHp;
  486. }
  487. /// <summary>
  488. /// 获取当前角色的中心点坐标
  489. /// </summary>
  490. public Vector2 GetCenterPosition()
  491. {
  492. return MountPoint.GlobalPosition;
  493. }
  494.  
  495. /// <summary>
  496. /// 使角色看向指定的坐标,
  497. /// 注意, 调用该函数会清空 LookTarget, 因为拥有 LookTarget 时也会每帧更新玩家视野位置
  498. /// </summary>
  499. /// <param name="pos"></param>
  500. public void LookTargetPosition(Vector2 pos)
  501. {
  502. LookTarget = null;
  503. //脸的朝向
  504. var gPos = GlobalPosition;
  505. if (pos.X > gPos.X && Face == FaceDirection.Left)
  506. {
  507. Face = FaceDirection.Right;
  508. }
  509. else if (pos.X < gPos.X && Face == FaceDirection.Right)
  510. {
  511. Face = FaceDirection.Left;
  512. }
  513. //枪口跟随目标
  514. MountPoint.SetLookAt(pos);
  515. }
  516. /// <summary>
  517. /// 判断指定坐标是否在角色视野方向
  518. /// </summary>
  519. public bool IsPositionInForward(Vector2 pos)
  520. {
  521. var gps = GlobalPosition;
  522. return (Face == FaceDirection.Left && pos.X <= gps.X) ||
  523. (Face == FaceDirection.Right && pos.X >= gps.X);
  524. }
  525.  
  526. /// <summary>
  527. /// 返回所有武器是否弹药都打光了
  528. /// </summary>
  529. public bool IsAllWeaponTotalAmmoEmpty()
  530. {
  531. foreach (var weapon in WeaponPack.ItemSlot)
  532. {
  533. if (weapon != null && !weapon.IsTotalAmmoEmpty())
  534. {
  535. return false;
  536. }
  537. }
  538.  
  539. return true;
  540. }
  541. /// <summary>
  542. /// 拾起一个武器, 返回是否成功拾取, 如果不想立刻切换到该武器, exchange 请传 false
  543. /// </summary>
  544. /// <param name="weapon">武器对象</param>
  545. /// <param name="exchange">是否立即切换到该武器, 默认 true </param>
  546. public virtual bool PickUpWeapon(Weapon weapon, bool exchange = true)
  547. {
  548. if (WeaponPack.PickupItem(weapon, exchange) != -1)
  549. {
  550. //从可互动队列中移除
  551. _interactiveItemList.Remove(weapon);
  552. return true;
  553. }
  554.  
  555. return false;
  556. }
  557.  
  558. /// <summary>
  559. /// 切换到下一个武器
  560. /// </summary>
  561. public virtual void ExchangeNext()
  562. {
  563. WeaponPack.ExchangeNext();
  564. }
  565.  
  566. /// <summary>
  567. /// 切换到上一个武器
  568. /// </summary>
  569. public virtual void ExchangePrev()
  570. {
  571. WeaponPack.ExchangePrev();
  572. }
  573.  
  574. /// <summary>
  575. /// 扔掉当前使用的武器, 切换到上一个武器
  576. /// </summary>
  577. public virtual void ThrowWeapon()
  578. {
  579. ThrowWeapon(WeaponPack.ActiveIndex);
  580. }
  581.  
  582. /// <summary>
  583. /// 扔掉指定位置的武器
  584. /// </summary>
  585. /// <param name="index">武器在武器袋中的位置</param>
  586. public virtual void ThrowWeapon(int index)
  587. {
  588. var weapon = WeaponPack.GetItem(index);
  589. if (weapon == null)
  590. {
  591. return;
  592. }
  593.  
  594. var temp = weapon.AnimatedSprite.Position;
  595. if (Face == FaceDirection.Left)
  596. {
  597. temp.Y = -temp.Y;
  598. }
  599. //var pos = GlobalPosition + temp.Rotated(weapon.GlobalRotation);
  600. WeaponPack.RemoveItem(index);
  601. //播放抛出效果
  602. weapon.ThrowWeapon(this, GlobalPosition);
  603. }
  604.  
  605. /// <summary>
  606. /// 返回是否存在可互动的物体
  607. /// </summary>
  608. public bool HasInteractive()
  609. {
  610. return InteractiveItem != null;
  611. }
  612.  
  613. /// <summary>
  614. /// 触发与碰撞的物体互动, 并返回与其互动的物体
  615. /// </summary>
  616. public ActivityObject TriggerInteractive()
  617. {
  618. if (HasInteractive())
  619. {
  620. var item = InteractiveItem;
  621. item.Interactive(this);
  622. return item;
  623. }
  624.  
  625. return null;
  626. }
  627.  
  628. /// <summary>
  629. /// 触发换弹
  630. /// </summary>
  631. public virtual void Reload()
  632. {
  633. if (WeaponPack.ActiveItem != null)
  634. {
  635. WeaponPack.ActiveItem.Reload();
  636. }
  637. }
  638.  
  639. /// <summary>
  640. /// 触发攻击
  641. /// </summary>
  642. public virtual void Attack()
  643. {
  644. if (WeaponPack.ActiveItem != null)
  645. {
  646. WeaponPack.ActiveItem.Trigger();
  647. }
  648. }
  649.  
  650. /// <summary>
  651. /// 触发使用道具
  652. /// </summary>
  653. public virtual void UseActiveProp()
  654. {
  655. var activeItem = ActivePropsPack.ActiveItem;
  656. if (activeItem != null)
  657. {
  658. activeItem.Use();
  659. }
  660. }
  661.  
  662. /// <summary>
  663. /// 受到伤害, 如果是在碰撞信号处理函数中调用该函数, 请使用 CallDeferred 来延时调用, 否则很有可能导致报错
  664. /// </summary>
  665. /// <param name="damage">伤害的量</param>
  666. /// <param name="angle">角度</param>
  667. public virtual void Hurt(int damage, float angle)
  668. {
  669. //受伤闪烁, 无敌状态
  670. if (Invincible)
  671. {
  672. return;
  673. }
  674. //计算真正受到的伤害
  675. damage = OnHandlerHurt(damage);
  676. var flag = Shield > 0;
  677. if (flag)
  678. {
  679. Shield -= damage;
  680. }
  681. else
  682. {
  683. damage = RoleState.CallCalcHurtDamageEvent(damage);
  684. if (damage < 0)
  685. {
  686. return;
  687. }
  688. Hp -= damage;
  689. //播放血液效果
  690. // var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_Blood_tscn);
  691. // var blood = packedScene.Instance<Blood>();
  692. // blood.GlobalPosition = GlobalPosition;
  693. // blood.Rotation = angle;
  694. // GameApplication.Instance.Node3D.GetRoot().AddChild(blood);
  695. }
  696. OnHit(damage, !flag);
  697.  
  698. //受伤特效
  699. PlayHitAnimation();
  700. //死亡判定
  701. if (Hp <= 0)
  702. {
  703. //死亡
  704. if (!IsDie)
  705. {
  706. IsDie = true;
  707. OnDie();
  708. }
  709. }
  710. }
  711.  
  712. /// <summary>
  713. /// 播放无敌状态闪烁动画
  714. /// </summary>
  715. /// <param name="time">持续时间</param>
  716. public void PlayInvincibleFlashing(float time)
  717. {
  718. Invincible = true;
  719. if (_invincibleFlashingId >= 0) //上一个还没结束
  720. {
  721. StopCoroutine(_invincibleFlashingId);
  722. }
  723.  
  724. _invincibleFlashingId = StartCoroutine(RunInvincibleFlashing(time));
  725. }
  726.  
  727. /// <summary>
  728. /// 停止无敌状态闪烁动画
  729. /// </summary>
  730. public void StopInvincibleFlashing()
  731. {
  732. Invincible = false;
  733. if (_invincibleFlashingId >= 0)
  734. {
  735. StopCoroutine(_invincibleFlashingId);
  736. _invincibleFlashingId = -1;
  737. }
  738. }
  739.  
  740. private IEnumerator RunInvincibleFlashing(float time)
  741. {
  742. yield return new WaitForSeconds(time);
  743. _invincibleFlashingId = -1;
  744. Invincible = false;
  745. }
  746.  
  747. /// <summary>
  748. /// 设置脸的朝向
  749. /// </summary>
  750. private void SetFace(FaceDirection face)
  751. {
  752. if (_face != face)
  753. {
  754. _face = face;
  755. if (face == FaceDirection.Right)
  756. {
  757. RotationDegrees = 0;
  758. Scale = _startScale;
  759. }
  760. else
  761. {
  762. RotationDegrees = 180;
  763. Scale = new Vector2(_startScale.X, -_startScale.Y);
  764. }
  765. }
  766. }
  767. /// <summary>
  768. /// 连接信号: InteractiveArea.BodyEntered
  769. /// 与物体碰撞
  770. /// </summary>
  771. private void _OnPropsEnter(Node2D other)
  772. {
  773. if (other is ActivityObject propObject && !propObject.CollisionWithMask(PhysicsLayer.OnHand))
  774. {
  775. if (!_interactiveItemList.Contains(propObject))
  776. {
  777. _interactiveItemList.Add(propObject);
  778. }
  779. }
  780. }
  781.  
  782. /// <summary>
  783. /// 连接信号: InteractiveArea.BodyExited
  784. /// 物体离开碰撞区域
  785. /// </summary>
  786. private void _OnPropsExit(Node2D other)
  787. {
  788. if (other is ActivityObject propObject)
  789. {
  790. if (_interactiveItemList.Contains(propObject))
  791. {
  792. _interactiveItemList.Remove(propObject);
  793. }
  794. if (InteractiveItem == propObject)
  795. {
  796. var prev = _currentResultData;
  797. _currentResultData = null;
  798. InteractiveItem = null;
  799. ChangeInteractiveItem(prev, null);
  800. }
  801. }
  802. }
  803.  
  804. /// <summary>
  805. /// 添加道具
  806. /// </summary>
  807. public void PushProp(Prop prop)
  808. {
  809. if (prop is ActiveProp activeProp) //主动道具
  810. {
  811. if (ActivePropsPack.PickupItem(activeProp) == -1)
  812. {
  813. GD.PrintErr("主动道具无法存入背包中!");
  814. return;
  815. }
  816. OnPushProp(prop);
  817. }
  818. else if (prop is BuffProp buffProp) //被动道具
  819. {
  820. if (BuffPropPack.Contains(buffProp))
  821. {
  822. GD.PrintErr("被动道具已经在背包中了!");
  823. return;
  824. }
  825. BuffPropPack.Add(buffProp);
  826. OnPushProp(prop);
  827. }
  828. else
  829. {
  830. GD.PrintErr("尚未被支持的道具类型: " + prop.GetType().FullName);
  831. }
  832. }
  833.  
  834. /// <summary>
  835. /// 移除道具
  836. /// </summary>
  837. public bool RemoveProp(Prop prop)
  838. {
  839. if (prop is ActiveProp activeProp) //主动道具
  840. {
  841. if (ActivePropsPack.RemoveItem(activeProp) != null)
  842. {
  843. OnRemoveProp(prop);
  844. return true;
  845. }
  846. GD.PrintErr("当前道具不在角色背包中!");
  847. return false;
  848. }
  849. else if (prop is BuffProp buffProp) //被动道具
  850. {
  851. if (BuffPropPack.Contains(buffProp))
  852. {
  853. OnRemoveProp(prop);
  854. BuffPropPack.Remove(buffProp);
  855. return true;
  856. }
  857. GD.PrintErr("被动道具不在背包中!");
  858. return false;
  859. }
  860. GD.PrintErr("尚未被支持的道具类型: " + prop.GetType().FullName);
  861. return false;
  862. }
  863.  
  864. protected override void OnDestroy()
  865. {
  866. //销毁道具
  867. foreach (var buffProp in BuffPropPack)
  868. {
  869. buffProp.Destroy();
  870. }
  871. BuffPropPack.Clear();
  872. ActivePropsPack.Destroy();
  873. WeaponPack.Destroy();
  874. }
  875. }