FightWorld.ts 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879
  1. /** @format */
  2. import {ECSWorld} from '../lib/ECSWorld'
  3. import {IRoleConfig, RoleConfig} from '../../config/RoleConfig'
  4. import {Data, Mgr} from '../../GameControl'
  5. import {cCollider} from '../../collision/Collider'
  6. import {ComRole} from '../components/ComRole'
  7. import {ComAttackable} from '../components/ComAttackable'
  8. import {ComType, EntityIndex} from '../lib/Const'
  9. import {ComCocosNode} from '../components/ComCocosNode'
  10. import {
  11. EventGraphicsDraw,
  12. EventHurtOrAdd,
  13. EventRoleTip,
  14. EventRun,
  15. EventSlowDown,
  16. EventStand,
  17. EventType,
  18. } from '../core/NodeEvent'
  19. import {ComTransform} from '../components/ComTransform'
  20. import {ComMovable} from '../components/ComMovable'
  21. import {ComNodeConfig} from '../components/ComNodeConfig'
  22. import {IStageRolePosConfig, StageRolePosConfig} from '../../config/StageRolePosConfig'
  23. import {ComEnemy} from '../components/ComEnemy'
  24. import {ComFriend} from '../components/ComFriend'
  25. import {ISkillConfig, SkillConfig} from '../../config/SkillConfig'
  26. import {ComFindEnemy} from '../components/ComFindEnemy'
  27. import {BulletConfig} from '../../config/BulletConfig'
  28. import {ComBullet} from '../components/ComBullet'
  29. import {ComBehaviorTree} from '../components/ComBehaviorTree'
  30. import {BT} from '../../behaviorTree/BehaviorTree'
  31. import {Log} from '../../utils/LogUtils'
  32. import {
  33. ANI_TYPE,
  34. ATTR_NAME,
  35. BUFF_ANI_TYPE,
  36. BUFF_EFFECT_TYPE,
  37. BUFF_TYPE,
  38. BULLET_EFFECT_TYPE,
  39. BULLET_FLY_TYPE,
  40. BULLET_TYPE,
  41. ENTRY,
  42. GAME_LAYER,
  43. GAME_PREFAB_TYPE,
  44. GAME_ROLE_TIP,
  45. GAME_SCALE_TYPE,
  46. GAME_TYPE,
  47. GAME_WIN_TYPE,
  48. HIT_ANI_TYPE,
  49. LANGUAGE_TYPE,
  50. MONSTER_TYPE,
  51. NEGATIVE_TYPE,
  52. ROLE_TYPE,
  53. SKILL_DIR_TYPE,
  54. SKILL_EFFECT_TYPE,
  55. SKILL_TYPE,
  56. START_POS,
  57. } from '../../enums/Enum'
  58. import {BuffConfig} from '../../config/BuffConfig'
  59. import {ccUtils} from '../../utils/ccUtils'
  60. import {ComRoleSpine} from '../components/ComRoleSpine'
  61. import {EntryObj, IAttackEffect, IBuff, IFightData} from '../core/GameInterface'
  62. import {ComSkill} from '../components/ComSkill'
  63. import {ComDizzy} from '../components/ComDizzy'
  64. import {ComSkillAbel} from '../components/ComSkillAbel'
  65. import {FrameAniConfig} from '../../config/FrameAniConfig'
  66. import {ComFrameAni} from '../components/ComFrameAni'
  67. import {EntryConfig} from '../../config/EntryConfig'
  68. import {TalentConfig} from '../../config/TalentConfig'
  69. import {IBaseAttr, ICard, IRole} from '../../interface/GlobalInterface'
  70. import {ComEnter} from '../components/ComEnter'
  71. import {ArmorConfig} from '../../config/ArmorConfig'
  72. import {ConstValue} from '../../data/ConstValue'
  73. import {SysHasSkill} from '../systems/SysHasSkill'
  74. import {SysFindEnemy} from '../systems/SysFindEnemy'
  75. import {SysBullet} from '../systems/SysBullet'
  76. import {SysBehaviorTree} from '../systems/SysBehaviorTree'
  77. import {SysBuff} from '../systems/SysBuff'
  78. import {SysSkillAbel} from '../systems/SysSkillAbel'
  79. import {SysSkill} from '../systems/SysSkill'
  80. import {SysMovable} from '../systems/SysMovable'
  81. import {SysAttack} from '../systems/SysAttack'
  82. import {SysDizzy} from '../systems/SysDizzy'
  83. import {SysDie} from '../systems/SysDie'
  84. import {SysLifeTime} from '../systems/SysLifeTime'
  85. import {SysFrameAni} from '../systems/SysFrameAni'
  86. import {SysRoleState} from '../systems/SysRoleState'
  87. import {SysCocosView} from '../systems/SysCocosView'
  88. import {SysEnter} from '../systems/SysEnter'
  89. import GameUI from '../../zuma/FightCore'
  90. import {CastleSkillConfig} from '../../config/CastleSkillConfig'
  91. import {idNum} from '../../proto/typedef'
  92. import {SysCastleSkill} from '../systems/SysCastleSkill'
  93. import {ShapeType} from '../../collision/Shape'
  94. import {ComHasSkill} from '../components/ComHasSkill'
  95. import FrameAnimation from '../../uiutils/FrameAnimation'
  96. import {EventProcess} from '../core/EventProcess'
  97. import FightCore from '../../zuma/FightCore'
  98. import {ZumabuffConfig} from '../../config/ZumabuffConfig'
  99. import {RoleSpineProcess} from '../core/RoleSpineProcess'
  100. export class FightWorld extends ECSWorld {
  101. //创建单例
  102. static instance: FightWorld
  103. static getInstance() {
  104. if (!FightWorld.instance) {
  105. FightWorld.instance = new FightWorld()
  106. FightWorld.instance.createWorldCocosView()
  107. }
  108. return FightWorld.instance
  109. }
  110. fightCore: FightCore
  111. rolePosMap: Map<number, IStageRolePosConfig[]>
  112. init() {
  113. this.rolePosMap = new Map<number, IStageRolePosConfig[]>()
  114. this.rolePosMap.set(Data.game.gFriend, [])
  115. this.rolePosMap.set(Data.game.gEnemy, [])
  116. for (let key in StageRolePosConfig) {
  117. if (+key <= 100) {
  118. this.rolePosMap.get(Data.game.gEnemy).push(StageRolePosConfig[key])
  119. } else if (+key > 100 && +key <= 200) {
  120. this.rolePosMap.get(Data.game.gFriend).push(StageRolePosConfig[key])
  121. }
  122. }
  123. this.initEntry()
  124. this.fightCore.registerTouchHandler(this.getSystem(SysCocosView))
  125. }
  126. createWorldCocosView() {
  127. //添加系统顺序不能错,保证行为树的判断能正常执行
  128. this.createEntity() // 创建0号实体
  129. this.addSystem(new SysHasSkill()) // 是否有技能施放
  130. this.addSystem(new SysFindEnemy()) // 寻敌锁定
  131. this.addSystem(new SysBullet()) // 子弹系统(在移动系统之前判断)
  132. this.addSystem(new SysBehaviorTree()) // 行为树
  133. this.addSystem(new SysBuff()) // buff光环系统
  134. this.addSystem(new SysSkillAbel()) // 技能吟唱
  135. this.addSystem(new SysSkill()) // 技能持续生效
  136. this.addSystem(new SysMovable()) // 移动
  137. this.addSystem(new SysAttack()) // 攻击动作
  138. this.addSystem(new SysDizzy()) // 晕眩
  139. this.addSystem(new SysDie()) // 死亡
  140. this.addSystem(new SysLifeTime()) // 生命时间倒计时
  141. this.addSystem(new SysFrameAni()) // 特效
  142. this.addSystem(new SysRoleState()) // role state
  143. this.addSystem(new SysCocosView()) // cocos view
  144. this.addSystem(new SysEnter()) // 角色入场
  145. }
  146. //-------------------------------角色-----------------------------------------
  147. public createRoleEntity(
  148. IDOrCfg: number | IRoleConfig,
  149. isEnemy?: boolean,
  150. posCfgID?: number,
  151. iRole?: IRole,
  152. dropOutGoods?: idNum,
  153. isExtraEnemy?: boolean,
  154. ): EntityIndex {
  155. let roleCfg: IRoleConfig
  156. if (typeof IDOrCfg == 'number') {
  157. roleCfg = RoleConfig[IDOrCfg]
  158. } else {
  159. roleCfg = IDOrCfg
  160. }
  161. if (!roleCfg) {
  162. console.error('没有这个角色配置----------->', IDOrCfg)
  163. }
  164. let entity = this.createEntity()
  165. // 添加nodeconfig
  166. let comMap = this.addComponent(entity, ComNodeConfig)
  167. comMap.id = 1
  168. comMap.layer = GAME_LAYER[GAME_LAYER.role]
  169. comMap.prefabName = GAME_PREFAB_TYPE.role
  170. let entitySpine = this.createEntity()
  171. // 添加spineNode
  172. let comSpineMap = this.addComponent(entitySpine, ComNodeConfig)
  173. comSpineMap.id = 1
  174. comSpineMap.layer = GAME_LAYER[GAME_LAYER.roleSpine]
  175. comSpineMap.prefabName = GAME_PREFAB_TYPE.roleSpine
  176. //移除cocosNode
  177. this.removeComponent(entity, ComCocosNode)
  178. // 添加transform
  179. let comTrans = this.addComponent(entity, ComTransform)
  180. comTrans.x = isEnemy ? Data.game.fightSizeMaxX : Data.game.fightSizeMinX
  181. if (posCfgID > 0 && roleCfg.type != ROLE_TYPE.base) {
  182. comTrans.x = StageRolePosConfig[posCfgID].posX
  183. }
  184. let posArr = this.rolePosMap.get(isEnemy ? Data.game.gEnemy : Data.game.gFriend)
  185. //id为1的是基地
  186. comTrans.y =
  187. posCfgID > 0
  188. ? StageRolePosConfig[posCfgID].posY
  189. : roleCfg.type == ROLE_TYPE.base
  190. ? StageRolePosConfig[1].posY
  191. : posArr[Math.randomRangeInt(0, posArr.length - 1)].posY
  192. if (isEnemy) {
  193. this.addComponent(entity, ComEnemy)
  194. } else {
  195. this.addComponent(entity, ComFriend)
  196. }
  197. // 添加spineNode transform
  198. let comSpineTrans = this.addComponent(entitySpine, ComTransform)
  199. comSpineTrans.x = comTrans.x
  200. comSpineTrans.y = comTrans.y
  201. let comRoleSpine = this.addComponent(entitySpine, ComRoleSpine)
  202. comRoleSpine.roleCfg = roleCfg
  203. comRoleSpine.group = isEnemy ? Data.game.gEnemy : Data.game.gFriend
  204. let comRole = this.addComponent(entity, ComRole)
  205. comRole.roleCfg = roleCfg
  206. comRole.drop = dropOutGoods
  207. let spineData: sp.spine.SkeletonData = Data.main.roleSpineMap.get(roleCfg.url)?.getRuntimeData()
  208. comRole.width = spineData ? (spineData.width * roleCfg.gameScale[GAME_SCALE_TYPE.spine]) / 100 : 60
  209. comRole.height = spineData ? (spineData.height * roleCfg.gameScale[GAME_SCALE_TYPE.spine]) / 100 : 100
  210. comRole.spineEntity = entitySpine
  211. comTrans.halfHeight = comRole.height / 2
  212. let baseAttr: IBaseAttr = iRole ? iRole : roleCfg
  213. Mgr.global.changeBaseAttr(comRole, baseAttr)
  214. comRole.attackRange = roleCfg.attackRange
  215. comRole.attackCD = roleCfg.attackCD == Data.game.cdMax ? Infinity : roleCfg.attackCD
  216. comRole.killNum = 0
  217. comRole.attackNum = 0
  218. comRole.group = isEnemy ? Data.game.gEnemy : Data.game.gFriend
  219. comRole.skills.length = 0
  220. comRole.skillCDs.length = 0
  221. comRole.enterCDs.length = 0
  222. comRole.skillCountDowns.length = 0
  223. comRole.babys.length = 0
  224. comRole.parent = 0
  225. comRole.parentRoleID = 0
  226. comRole.HPDirty = true
  227. comRole.transDirty = false
  228. comRole.transID = 0
  229. comRole.buffs.length = 0
  230. comRole.entryMap.clear()
  231. comRole.equips = null
  232. //所有技能
  233. let allSkill = []
  234. let allSkillCDs = []
  235. let allEnterCDs = []
  236. //人物技能
  237. roleCfg.skills.forEach((skill, index) => {
  238. if (skill) {
  239. allSkill.push(skill)
  240. allSkillCDs.push(roleCfg.skillCDs[index])
  241. allEnterCDs.push(roleCfg.enterCDs[index])
  242. }
  243. })
  244. //天赋词条
  245. for (let id of Data.user.talents) {
  246. this.putEntry2Map(comRole, this.convertEntry2Obj(TalentConfig[id].entryID))
  247. }
  248. //装备词条
  249. if (iRole) {
  250. comRole.equips = iRole.equips
  251. for (let iEquip of iRole.equips) {
  252. if (iEquip) {
  253. if (iEquip.cfg.entry && iEquip.cfg.entry < ENTRY.textShow) {
  254. for (let i = 1; i <= iEquip.cfg.quality; i++) {
  255. let ID = Math.floor(iEquip.cfg.ID / 100) * 100 + i
  256. if (ArmorConfig[ID.toString()].entry)
  257. this.putEntry2Map(comRole, this.convertEntry2Obj(ArmorConfig[ID.toString()].entry))
  258. }
  259. }
  260. //装备技能
  261. iEquip.cfg.skills?.forEach((skill, index) => {
  262. if (skill) {
  263. allSkill.push(skill)
  264. allSkillCDs.push(iEquip.cfg.skillCDs[index])
  265. allEnterCDs.push(iEquip.cfg.enterCDs[index])
  266. }
  267. })
  268. }
  269. }
  270. }
  271. //遗迹词条
  272. if (Data.game.gameType == GAME_TYPE.relic) {
  273. //基础属性
  274. if (Data.main.relicAdd[roleCfg.profession]) {
  275. let keys = Object.keys(ATTR_NAME)
  276. for (let attrKey of keys) {
  277. if (Data.main.relicAdd[roleCfg.profession][attrKey]) {
  278. comRole[attrKey] *= 1 + Data.main.relicAdd[roleCfg.profession][attrKey] / Data.game.rateNum
  279. }
  280. }
  281. }
  282. for (let entry of Data.game.relicEntryArr) {
  283. this.putEntry2Map(comRole, this.convertEntry2Obj(entry))
  284. }
  285. }
  286. if (comRole.entryMap.get(ENTRY.startShieldHP)?.num) {
  287. comRole.shieldHP = comRole.entryMap.get(ENTRY.startShieldHP).num
  288. }
  289. allSkill.forEach((skill, index) => {
  290. if (skill && SkillConfig[skill]) {
  291. comRole.skills.push(SkillConfig[skill])
  292. comRole.skillCDs.push(allSkillCDs[index])
  293. comRole.enterCDs.push(allEnterCDs[index])
  294. let cd = allSkillCDs[index]
  295. if (cd == Data.game.cdMax) cd = Infinity
  296. if (cd > 0 && cd != Infinity && comRole.entryMap.get(ENTRY.skillCD)?.num) {
  297. cd *= 1 - comRole.entryMap.get(ENTRY.skillCD).num / Data.game.rateNum
  298. if (cd < 0) cd = 0
  299. }
  300. //入场CD
  301. let enterCD = allEnterCDs[index]
  302. comRole.skillCountDowns.push(enterCD > 0 && cd != Infinity ? enterCD : cd)
  303. } else {
  304. console.error('没有这个技能配置----------->', allSkill[index])
  305. }
  306. })
  307. let attackTime = Infinity
  308. let castTime = new Array(allSkill.length).fill(0) //spine没有技能动作
  309. let enterTime = 0
  310. let dieTime = 0
  311. if (spineData) {
  312. if (spineData.findAnimation('skill') && castTime.length > 0) {
  313. castTime[0] = spineData.findAnimation('skill').duration
  314. }
  315. for (let i = 1; i <= roleCfg.skills.length; i++) {
  316. if (spineData.findAnimation(`skill${i}`)) {
  317. castTime[i - 1] = spineData.findAnimation(`skill${i}`).duration
  318. } else {
  319. castTime[i - 1] = castTime[0]
  320. }
  321. }
  322. if (spineData.findAnimation('enter')) {
  323. enterTime = spineData.findAnimation('enter').duration
  324. }
  325. if (spineData.findAnimation('attack')) {
  326. attackTime = spineData.findAnimation('attack').duration
  327. }
  328. if (spineData.findAnimation('die')) {
  329. dieTime = spineData.findAnimation('die').duration
  330. }
  331. }
  332. comRole.attackTime = attackTime
  333. comRole.castTime = castTime
  334. comRole.enterTime = enterTime
  335. comRole.dieTime = dieTime
  336. //血量等词条装备处理完后处理
  337. comRole.nowHP = comRole.HP
  338. comRole.lastHP = comRole.HP
  339. comRole.shieldHP = 0
  340. comRole.lastShieldHP = 0
  341. comRole.isExtraEnemy = isExtraEnemy
  342. //处理gameUI显示
  343. if (this.fightCore) {
  344. let entities = this.fightCore.roleEntityMap.get(roleCfg.ID)
  345. if (!entities) {
  346. entities = []
  347. this.fightCore.roleEntityMap.set(roleCfg.ID, entities)
  348. }
  349. entities.push(entity)
  350. if (roleCfg.type == MONSTER_TYPE.boss) {
  351. if (this.fightCore.stageInfo.type == GAME_WIN_TYPE.boss) {
  352. }
  353. this.fightCore.showBossHP(comRole)
  354. }
  355. }
  356. return entity
  357. }
  358. setRoleHP(entity, HP) {
  359. if (!HP) return
  360. let comRole = this.getComponent(entity, ComRole)
  361. if (!comRole) return
  362. comRole.HP = HP
  363. comRole.lastHP = HP
  364. comRole.nowHP = HP
  365. }
  366. public initRoleBehavior(comBehavior: ComBehaviorTree, roleConfig: IRoleConfig) {
  367. let findEnemyNode = new BT.FindEnemyNode()
  368. let meleeMonitorNode = new BT.MeleeMonitorNode()
  369. let meleeXMonitorNode = new BT.MeleeXMonitorNode()
  370. let attackMonitorNode = new BT.AttackMonitorNode()
  371. let attackNode = new BT.AttackNode()
  372. let meleeWalkToTargetNode = new BT.MeleeWalkToTargetNode(roleConfig.moveSpeed * 1.5)
  373. let stopNode = new BT.StopNode()
  374. let hasAttackEnemy = new BT.HasAttackEnemyNode()
  375. let hasBeAttackNode = new BT.HasBeAttackNode()
  376. let willAttackNode = new BT.WillAttackNode()
  377. let willBeAttackNode = new BT.WillBeAttackNode()
  378. let willAttackNotWillAttackNode = new BT.WillAttackNotWillAttackNode()
  379. let stopAttackNode = new BT.StopAttackNode()
  380. let beDizzyNode = new BT.BeDizzyNode()
  381. let notBeDizzyNode = new BT.InverterNode(new BT.BeDizzyNode())
  382. let dizzyNode = new BT.DizzyNode()
  383. let skillNode = new BT.SkillNode()
  384. let hasSkillNode = new BT.HasSkillNode()
  385. let walkToCloseXTargetNode = new BT.WalkToCloseTargetNode(roleConfig.moveSpeed, true)
  386. let walkToCloseTargetNode = new BT.WalkToCloseTargetNode(roleConfig.moveSpeed, false)
  387. let notFindEnemyNode = new BT.InverterNode(findEnemyNode)
  388. let notMeleeMonitorNode = new BT.InverterNode(meleeMonitorNode)
  389. let notMeleeXMonitorNode = new BT.InverterNode(meleeXMonitorNode)
  390. let notAttackMonitorNode = new BT.InverterNode(attackMonitorNode)
  391. let notHasAttackEnemy = new BT.InverterNode(hasAttackEnemy)
  392. let notWillBeAttackNode = new BT.InverterNode(willBeAttackNode)
  393. let notWillAttackNode = new BT.InverterNode(willAttackNode)
  394. let notHasBeAttackNode = new BT.InverterNode(hasBeAttackNode)
  395. let notHasSkillNode = new BT.InverterNode(hasSkillNode)
  396. let notCastSkillNode = new BT.InverterNode(new BT.CastSkillNode())
  397. let stopSkillNode = new BT.StopSkillNode()
  398. let shootRoot = new BT.RootSelectorNode(
  399. [
  400. // 晕眩
  401. new BT.SequenceNode([beDizzyNode, stopNode, stopSkillNode, stopAttackNode, dizzyNode]),
  402. // 放技能
  403. new BT.SequenceNode([notBeDizzyNode, hasSkillNode, stopNode, stopAttackNode, skillNode]),
  404. // 远程攻击范围有敌人,攻击最近的敌人
  405. new BT.SequenceNode([notBeDizzyNode, attackMonitorNode, stopNode, attackNode]),
  406. // 远程攻击范围没有敌人,场上有敌军, 往最近敌方X轴方向移动
  407. new BT.SequenceNode([
  408. notBeDizzyNode,
  409. notHasSkillNode,
  410. findEnemyNode,
  411. notAttackMonitorNode,
  412. walkToCloseTargetNode,
  413. ]),
  414. // 没有敌人停止移动
  415. new BT.SequenceNode([notFindEnemyNode, stopNode]),
  416. ],
  417. false,
  418. )
  419. let meleeRoot = new BT.RootSelectorNode([
  420. // 晕眩
  421. new BT.SequenceNode([beDizzyNode, stopNode, stopSkillNode, stopAttackNode, dizzyNode]),
  422. // 放技能
  423. new BT.SequenceNode([notBeDizzyNode, hasSkillNode, stopNode, stopAttackNode, skillNode]),
  424. // X轴Y轴近战探测范围没有敌人,场上有敌军, 往最近敌方X轴方向移动
  425. new BT.SequenceNode([
  426. notBeDizzyNode,
  427. notHasSkillNode,
  428. findEnemyNode,
  429. notHasAttackEnemy,
  430. notWillBeAttackNode,
  431. notWillAttackNode,
  432. notMeleeXMonitorNode,
  433. notMeleeMonitorNode,
  434. walkToCloseXTargetNode,
  435. ]),
  436. // X轴近战探测范围有敌人,往最近敌方X轴方向移动,直到进入攻击范围
  437. new BT.SequenceNode([
  438. notBeDizzyNode,
  439. notHasSkillNode,
  440. findEnemyNode,
  441. notHasAttackEnemy,
  442. notWillBeAttackNode,
  443. notWillAttackNode,
  444. meleeXMonitorNode,
  445. walkToCloseXTargetNode,
  446. ]),
  447. // X轴近战攻击范围没有敌人,没有被近战即将攻击, 往最近Y轴的敌方方向移动
  448. new BT.SequenceNode([
  449. notBeDizzyNode,
  450. notHasSkillNode,
  451. findEnemyNode,
  452. notHasAttackEnemy,
  453. notWillBeAttackNode,
  454. notWillAttackNode,
  455. notMeleeXMonitorNode,
  456. meleeMonitorNode,
  457. walkToCloseTargetNode,
  458. ]),
  459. // 自己即将被攻击,停止
  460. new BT.SequenceNode([notBeDizzyNode, notHasSkillNode, notHasAttackEnemy, willBeAttackNode, stopNode]),
  461. // 自己即将攻击敌人,跑到攻击点
  462. new BT.SequenceNode([
  463. notBeDizzyNode,
  464. notHasAttackEnemy,
  465. // notHasBeAttackNode,
  466. willAttackNode,
  467. willAttackNotWillAttackNode,
  468. meleeWalkToTargetNode,
  469. ]),
  470. // 到达了攻击地点,继续攻击
  471. new BT.SequenceNode([notBeDizzyNode, hasAttackEnemy, stopNode, attackNode]),
  472. // 停止移动
  473. new BT.SequenceNode([notFindEnemyNode, stopNode]),
  474. ])
  475. comBehavior.root = roleConfig.attackRange > Data.game.meleeRange ? shootRoot : meleeRoot
  476. if (roleConfig.attackRange == 0) comBehavior.root = null
  477. }
  478. public changeMoveSpeed(entity: EntityIndex, speed: number) {
  479. let comMovable = this.getComponent(entity, ComMovable)
  480. let comCocosNode = this.getComponent(entity, ComCocosNode)
  481. let comRole = this.getComponent(entity, ComRole)
  482. let comFriend = this.getComponent(entity, ComFriend)
  483. if (!comMovable || !comCocosNode) return
  484. let isChange = comMovable.speed != speed || comFriend
  485. comMovable.speed = speed
  486. //同步spine战立和移动
  487. let comSpineNode = this.getComponent(comRole?.spineEntity, ComCocosNode)
  488. if (comMovable.speed > 0) {
  489. isChange && comCocosNode.events.push(new EventRun()) && comSpineNode?.events.push(new EventRun())
  490. } else {
  491. comMovable.points.length = 0
  492. comMovable.pointIdx = 0
  493. isChange && comCocosNode.events.push(new EventStand()) && comSpineNode?.events.push(new EventStand())
  494. }
  495. }
  496. public changeRoleRun(entity: EntityIndex, isRun: boolean) {
  497. let comRole = this.getComponent(entity, ComRole)
  498. if (!comRole) return
  499. let comSpineNode = this.getComponent(comRole.spineEntity, ComCocosNode)
  500. comSpineNode?.node.getComponent(RoleSpineProcess).processEvent(isRun ? new EventRun() : new EventStand())
  501. }
  502. isDie(idOrCom: EntityIndex | ComRole) {
  503. let comRole: ComRole
  504. if (typeof idOrCom == 'number') {
  505. if (!idOrCom) return true
  506. comRole = this.getComponent(idOrCom, ComRole)
  507. } else {
  508. comRole = idOrCom
  509. }
  510. return !comRole || comRole.nowHP + comRole.shieldHP <= 0
  511. }
  512. isEnter(id: EntityIndex) {
  513. let comEnter = this.getComponent(id, ComEnter)
  514. return comEnter != null
  515. }
  516. isBase(idOrCom: EntityIndex | ComRole) {
  517. return this.isRoleType(idOrCom, ROLE_TYPE.base)
  518. }
  519. isBoss(idOrCom: EntityIndex | ComRole) {
  520. return this.isRoleType(idOrCom, MONSTER_TYPE.boss)
  521. }
  522. isRoleType(idOrCom: EntityIndex | ComRole, type: ROLE_TYPE | MONSTER_TYPE) {
  523. let comRole: ComRole
  524. if (typeof idOrCom == 'number') {
  525. if (!idOrCom) return false
  526. comRole = this.getComponent(idOrCom, ComRole)
  527. } else {
  528. comRole = idOrCom
  529. }
  530. return !comRole || comRole.roleCfg.type === type
  531. }
  532. //-------------------------战斗扣血加血-----------------------------------------------
  533. //扣血
  534. changeHpByHurt(role: EntityIndex, hurtHP: number, isCrit: boolean, HitAniID: number) {
  535. if (!hurtHP) return
  536. let changeHPRole = this.getComponent(role, ComRole)
  537. if (changeHPRole.invincible) return
  538. let changeHPComCocosNode = this.getComponent(role, ComCocosNode)
  539. changeHPRole.lastHP = changeHPRole.nowHP
  540. changeHPRole.lastShieldHP = changeHPRole.shieldHP
  541. changeHPComCocosNode.events.push(
  542. new EventRoleTip(
  543. isCrit ? GAME_ROLE_TIP.critTip : GAME_ROLE_TIP.damageTip,
  544. -hurtHP,
  545. `-${Math.toKMBNum(hurtHP)}`,
  546. ),
  547. )
  548. let comSpineNode = this.getComponent(changeHPRole.spineEntity, ComCocosNode)
  549. comSpineNode?.events.push(new EventHurtOrAdd(-hurtHP, isCrit))
  550. if (changeHPRole.shieldHP > 0) {
  551. changeHPRole.shieldHP -= hurtHP
  552. if (changeHPRole.shieldHP < 0) {
  553. changeHPRole.nowHP += changeHPRole.shieldHP
  554. changeHPRole.shieldHP = 0
  555. }
  556. } else {
  557. changeHPRole.nowHP -= hurtHP
  558. }
  559. changeHPRole.HPDirty = true
  560. if (!this.isBase(changeHPRole) && changeHPRole.roleCfg.type != ROLE_TYPE.totem && HitAniID > 0) {
  561. this.createAni(HitAniID, role)
  562. }
  563. }
  564. getDefenseRate(defenseObj: IFightData, attackObj?: IFightData) {
  565. let ignoreDefenseE = attackObj?.entryMap.get(ENTRY.ignoreDefense)?.num || 0
  566. return (
  567. 1 -
  568. (defenseObj.defense * (1 - ignoreDefenseE / Data.game.rateNum)) /
  569. (defenseObj.defense + Data.game.defenseConst)
  570. )
  571. }
  572. getSpellDefenseRate(fightData: IFightData, attackObj?: IFightData) {
  573. let ignoreDefenseE = attackObj?.entryMap.get(ENTRY.ignoreDefense)?.num || 0
  574. return (
  575. 1 -
  576. (fightData.spellDefense * (1 - ignoreDefenseE / Data.game.rateNum)) /
  577. (fightData.spellDefense + Data.game.defenseConst)
  578. )
  579. }
  580. //攻击扣血值
  581. getHurtByAttackRole(attackObj: IFightData, role: EntityIndex, attackEffect: IAttackEffect): number {
  582. let hurtHP = 0
  583. let changeHPRole = this.getComponent(role, ComRole)
  584. let changeHPComCocosNode = this.getComponent(role, ComCocosNode)
  585. if (this.isDie(changeHPRole) || !changeHPComCocosNode || !changeHPComCocosNode.loaded) return hurtHP
  586. let critAddAttack = 0
  587. let rateNum = Data.game.rateNum
  588. let attack = attackObj.attack
  589. let spellAttack = attackObj.spellAttack
  590. let realAttack = attackObj.realAttack
  591. // 所有的比例加伤
  592. let hurtAddRate = 0
  593. let realHurtAdd: number = 0
  594. attackObj.buffs.forEach(buff => {
  595. let buffConfig = buff.buffCfg
  596. if (buffConfig.buffType == BUFF_TYPE.backAddHurt && attackEffect.isBack) {
  597. //后背加伤(万分比)
  598. hurtAddRate += buffConfig.attrRate[0]
  599. } else if (buffConfig.buffType == BUFF_TYPE.realByHp) {
  600. //血量比例加真实攻击(万分比)
  601. realHurtAdd += attackObj.nowHP * (buffConfig.attrRate[0] / rateNum)
  602. } else if (
  603. buffConfig.buffType == BUFF_TYPE.attackNumAddHurt &&
  604. attackObj.attackNum % buffConfig.attrNum[0] == 0
  605. ) {
  606. //N弹加伤(万分比)
  607. hurtAddRate += buffConfig.attrRate[0]
  608. }
  609. })
  610. //普攻对boss加伤
  611. if (attackObj.entryMap.get(ENTRY.boosHurt)?.num && changeHPRole.roleCfg.type == MONSTER_TYPE.boss) {
  612. hurtAddRate += attackObj.entryMap.get(ENTRY.boosHurt).num
  613. }
  614. changeHPRole.buffs.forEach(buff => {
  615. let buffConfig = buff.buffCfg
  616. if (buffConfig.buffType == BUFF_TYPE.shieldReduceHurt) {
  617. //顶盾减伤(万分比)
  618. hurtAddRate += buffConfig.attrRate[0]
  619. } else if (buffConfig.buffType == BUFF_TYPE.hurtRateChange) {
  620. //伤害减免(万分比)
  621. hurtAddRate += buffConfig.attrRate[0]
  622. }
  623. })
  624. //暴击
  625. if (attackEffect.isCrit) {
  626. attack *= attackObj.critNum / rateNum
  627. spellAttack *= attackObj.critNum / rateNum
  628. realAttack *= attackObj.critNum / rateNum
  629. }
  630. //溅射
  631. if (attackEffect.sputter) {
  632. attack *= attackEffect.sputter / rateNum
  633. spellAttack *= attackEffect.sputter / rateNum
  634. realAttack *= attackEffect.sputter / rateNum
  635. }
  636. if (attack || spellAttack || realAttack) {
  637. //物理伤害 物理攻击*(1-物理防御/(物理防御+防御常数))
  638. let hurt = attack * this.getDefenseRate(changeHPRole, attackObj)
  639. //魔法伤害 魔法攻击*(1-魔法防御/(魔法防御+防御常数))
  640. let spellHurt = spellAttack * this.getSpellDefenseRate(changeHPRole, attackObj)
  641. //真实伤害 真实攻击
  642. let realHurt = realAttack
  643. realHurt += realHurtAdd
  644. let endHurtRate = 1 + hurtAddRate / rateNum
  645. if (endHurtRate < 0) endHurtRate = 0
  646. hurtHP = (hurt + spellHurt + realHurt) * (1 + Data.game.curHurtRate / rateNum) * endHurtRate
  647. }
  648. //普攻减伤
  649. if (changeHPRole.entryMap.get(ENTRY.hurtReduce)?.num > 0) {
  650. hurtHP -= changeHPRole.entryMap.get(ENTRY.hurtReduce).num
  651. }
  652. if (hurtHP < 0) hurtHP = 0
  653. return hurtHP
  654. }
  655. //技能加减血
  656. changeHpBySkill(skill: ComSkill, role: EntityIndex) {
  657. let changeHPRole = this.getComponent(role, ComRole)
  658. let changeHPComCocosNode = this.getComponent(role, ComCocosNode)
  659. if (
  660. this.isDie(changeHPRole) ||
  661. (this.isBase(changeHPRole) && !skill.skillCfg.effectType.includes(SKILL_EFFECT_TYPE.hurtBase)) ||
  662. changeHPRole.invincible ||
  663. !changeHPComCocosNode ||
  664. !changeHPComCocosNode.loaded
  665. )
  666. return
  667. let fightData = skill.fightData
  668. if (
  669. (skill.skillCfg.type == SKILL_TYPE.normal || skill.skillCfg.type == SKILL_TYPE.attackBack) &&
  670. skill.skillCfg.hurtRate
  671. ) {
  672. let rateNum = Data.game.rateNum
  673. let hurtHP = 0
  674. let attack = fightData.attack
  675. let spellAttack = fightData.spellAttack
  676. let realAttack = fightData.realAttack
  677. let hurtAddRate = skill.skillCfg.hurtRate
  678. //技能加伤
  679. if (fightData.entryMap.get(ENTRY.skillHurtRate)?.num) {
  680. hurtAddRate += fightData.entryMap.get(ENTRY.skillHurtRate).num
  681. }
  682. //技能对boss加伤
  683. if (fightData.entryMap.get(ENTRY.boosHurt)?.num && changeHPRole.roleCfg.type == MONSTER_TYPE.boss) {
  684. hurtAddRate += fightData.entryMap.get(ENTRY.boosHurt).num
  685. }
  686. //自身buff加伤
  687. for (let j = 0; j < fightData.buffs.length; j++) {
  688. let buffCfg = fightData.buffs[j].buffCfg
  689. if (
  690. buffCfg.buffType == BUFF_TYPE.skillHurt &&
  691. ((buffCfg.effectType.includes(BUFF_EFFECT_TYPE.normalSkill) && !skill.skillCfg.isSpecial) ||
  692. (buffCfg.effectType.includes(BUFF_EFFECT_TYPE.specialSkill) && skill.skillCfg.isSpecial))
  693. ) {
  694. hurtAddRate += buffCfg.attrRate[0]
  695. }
  696. }
  697. //受击者buff减伤
  698. changeHPRole.buffs.forEach(buff => {
  699. let buffConfig = buff.buffCfg
  700. if (buffConfig.buffType == BUFF_TYPE.hurtRateChange) {
  701. //伤害减免(万分比)
  702. hurtAddRate += buffConfig.attrRate[0]
  703. }
  704. })
  705. if (attack || spellAttack || realAttack) {
  706. //物理伤害 物理攻击*(1-物理防御/(物理防御+防御常数))
  707. let hurt = attack * this.getDefenseRate(changeHPRole)
  708. //魔法伤害 魔法攻击*(1-魔法防御/(魔法防御+防御常数))
  709. let spellHurt = spellAttack * this.getSpellDefenseRate(changeHPRole)
  710. //真实伤害 真实攻击
  711. let realHurt = realAttack
  712. hurtHP = (hurt + spellHurt + realHurt) * (1 + Data.game.curHurtRate / rateNum) * (hurtAddRate / rateNum)
  713. }
  714. //技能减伤
  715. if (changeHPRole.entryMap.get(ENTRY.hurtReduce)?.num > 0) {
  716. hurtHP -= changeHPRole.entryMap.get(ENTRY.hurtReduce).num
  717. }
  718. if (hurtHP < 0) hurtHP = 0
  719. //受击特效统一处理,这里是0
  720. this.changeHpByHurt(role, hurtHP, false, 0)
  721. }
  722. let addNum = 0
  723. if (skill.skillCfg.type == SKILL_TYPE.addHP) {
  724. addNum = (skill.skillCfg.hurtRate / Data.game.rateNum) * fightData.spellAttack
  725. let moreAddNum = 0
  726. if (addNum + changeHPRole.nowHP > changeHPRole.HP) {
  727. moreAddNum = addNum + changeHPRole.nowHP - changeHPRole.HP
  728. addNum = changeHPRole.HP - changeHPRole.nowHP
  729. }
  730. for (let i = 0; i < skill.skillCfg.effectType.length; i++) {
  731. if (skill.skillCfg.effectType[i] == SKILL_EFFECT_TYPE.addExtraHP) {
  732. if (changeHPRole.nowHP / changeHPRole.HP < skill.skillCfg.effectParm[i][0] / Data.game.rateNum) {
  733. addNum += skill.skillCfg.effectParm[i][1]
  734. }
  735. } else if (skill.skillCfg.effectType[i] == SKILL_EFFECT_TYPE.addRateHP) {
  736. addNum += (skill.skillCfg.effectParm[i][0] / Data.game.rateNum) * changeHPRole.HP
  737. }
  738. }
  739. //增加治疗量
  740. if (fightData.entryMap.get(ENTRY.addHealing)?.num) {
  741. addNum *= 1 + fightData.entryMap.get(ENTRY.addHealing).num / Data.game.rateNum
  742. }
  743. //受治疗增加量
  744. if (changeHPRole.entryMap.get(ENTRY.healingMore)?.num) {
  745. addNum *= 1 + changeHPRole.entryMap.get(ENTRY.healingMore).num / Data.game.rateNum
  746. }
  747. //多的治疗量转为白血盾
  748. if (changeHPRole.entryMap.get(ENTRY.healing2Shield)?.num && moreAddNum) {
  749. changeHPRole.shieldHP +=
  750. (changeHPRole.entryMap.get(ENTRY.healing2Shield).num / Data.game.rateNum) * moreAddNum
  751. }
  752. this.addHP(addNum, role)
  753. }
  754. if (
  755. skill.skillCfg.type == SKILL_TYPE.addShieldHPByHP ||
  756. skill.skillCfg.type == SKILL_TYPE.addShieldHPBySpAttack
  757. ) {
  758. addNum =
  759. (skill.skillCfg.hurtRate / Data.game.rateNum) *
  760. (skill.skillCfg.type == SKILL_TYPE.addShieldHPByHP ? fightData.HP : fightData.spellAttack)
  761. if (changeHPRole.shieldHP < addNum) changeHPRole.shieldHP = addNum
  762. if (skill.skillCfg.type == SKILL_TYPE.addShieldHPBySpAttack) {
  763. for (let i = 0; i < skill.skillCfg.effectType.length; i++) {
  764. if (skill.skillCfg.effectType[i] == SKILL_EFFECT_TYPE.addRateShieldHP) {
  765. addNum += (skill.skillCfg.effectParm[i][0] / Data.game.rateNum) * changeHPRole.HP
  766. }
  767. }
  768. }
  769. }
  770. changeHPRole.HPDirty = true
  771. }
  772. changeHpByRebound(role: EntityIndex, enemy: EntityIndex) {
  773. let comRoleEnemy: ComRole = this.getComponent(enemy, ComRole)
  774. let comRole: ComRole = this.getComponent(enemy, ComRole)
  775. if (this.isDie(comRoleEnemy)) return
  776. comRoleEnemy.buffs.forEach(buff => {
  777. let buffType = buff.buffCfg.buffType
  778. if (buffType == BUFF_TYPE.reboundAttack || buffType == BUFF_TYPE.reboundReal) {
  779. //真实伤害
  780. let defenseRate = 1
  781. if (buffType == BUFF_TYPE.reboundAttack) {
  782. //物理伤害
  783. defenseRate = this.getDefenseRate(comRole, comRoleEnemy)
  784. }
  785. let hurt = (comRoleEnemy.attack * defenseRate * buff.buffCfg.attrRate[0]) / Data.game.rateNum
  786. this.changeHpByHurt(role, hurt, false, 0)
  787. }
  788. })
  789. if (comRoleEnemy.entryMap.get(ENTRY.hurtRebound)?.num) {
  790. let defenseRate = this.getDefenseRate(comRole, comRoleEnemy)
  791. let hurt =
  792. (comRoleEnemy.attack * defenseRate * comRoleEnemy.entryMap.get(ENTRY.hurtRebound)?.num) /
  793. Data.game.rateNum
  794. this.changeHpByHurt(role, hurt, false, 0)
  795. }
  796. }
  797. moveToMeleeAttackPos(
  798. selfEntity: EntityIndex,
  799. comTrans: ComTransform,
  800. targetComTrans: ComTransform,
  801. targetComMovable: ComMovable,
  802. isBack?: boolean,
  803. ) {
  804. let targetPos = cc.v2(targetComTrans.x, targetComTrans.y)
  805. // 近战前往目标敌人没被锁定的某一个近战范围攻击点
  806. let isLeft = comTrans.x - targetComTrans.x < 0
  807. if (isBack) isLeft = !isLeft
  808. if (targetComTrans.x >= Data.game.fightSizeMaxX) {
  809. isLeft = true
  810. }
  811. if (targetComTrans.x <= Data.game.fightSizeMinX) {
  812. isLeft = false
  813. }
  814. let isDown = comTrans.y - targetComTrans.y < 0
  815. let attackArrayPos = isLeft ? Data.game.attackLeftRadiusPoints : Data.game.attackRightRadiusPoints
  816. let curAttackArrayPos = isLeft
  817. ? targetComMovable.leftMeleeEnemiesPosDirty
  818. : targetComMovable.rightMeleeEnemiesPosDirty
  819. let posIndex = curAttackArrayPos.indexOf(-1)
  820. let secondPosIndex = curAttackArrayPos.indexOf(-1, posIndex + 1)
  821. let targetIndex
  822. //因为leftMeleeEnemiesPosDirty数组是上下位置交替插入的,所以找出离自己近的点
  823. if (posIndex >= 0 && secondPosIndex > 0) {
  824. if (isDown) {
  825. targetIndex = attackArrayPos[posIndex].y < 0 ? posIndex : secondPosIndex
  826. } else {
  827. targetIndex = attackArrayPos[posIndex].y >= 0 ? posIndex : secondPosIndex
  828. }
  829. } else if (posIndex >= 0 && secondPosIndex <= 0) {
  830. targetIndex = posIndex
  831. } else {
  832. targetIndex = Math.randomRangeInt(0, attackArrayPos.length - 1)
  833. }
  834. curAttackArrayPos[targetIndex] = selfEntity
  835. targetPos.addSelf(attackArrayPos[targetIndex])
  836. if (targetPos.y <= Data.game.fightSizeMinY) targetPos.y = Data.game.fightSizeMinY
  837. if (targetPos.y >= Data.game.fightSizeMaxY) targetPos.y = Data.game.fightSizeMaxY
  838. return targetPos
  839. }
  840. //加血吸血
  841. addHP(addHPNum: number, role: EntityIndex) {
  842. let comRole = this.getComponent(role, ComRole)
  843. let comCocosNode = this.getComponent(role, ComCocosNode)
  844. if (!this.isDie(role)) {
  845. if (addHPNum >= 1) {
  846. comCocosNode.events.push(new EventRoleTip(GAME_ROLE_TIP.hpTip, addHPNum, `+${Math.toKMBNum(addHPNum)}`))
  847. }
  848. let target = comRole.nowHP + addHPNum
  849. if (target > comRole.HP) {
  850. addHPNum = comRole.HP - comRole.nowHP
  851. }
  852. comRole.nowHP += addHPNum
  853. }
  854. }
  855. //-------------------------------子弹-----------------------------------------
  856. public createBulletEntity(role: EntityIndex, isCrit: boolean): EntityIndex[] {
  857. let comRole = this.getComponent(role, ComRole)
  858. let comTransform = this.getComponent(role, ComTransform)
  859. let comFindEnemy = this.getComponent(role, ComFindEnemy)
  860. let comAttackable = this.getComponent(role, ComAttackable)
  861. let entities = []
  862. if (this.isDie(comRole)) {
  863. //Log.warn('创建子弹失败')
  864. return entities
  865. }
  866. let bulletID = comRole.roleCfg.bullet
  867. if (!bulletID) {
  868. return entities
  869. }
  870. let bulletCfg = BulletConfig[bulletID]
  871. let enemies = [comAttackable.curAttack]
  872. let endPosArr: cc.Vec2[] = []
  873. //跟踪敌人改成固定角度
  874. if (bulletCfg.splitNum > 1) {
  875. // let otherEnemies = comFindEnemy.attackCObject.containsBody.keysArr()
  876. // otherEnemies = otherEnemies.filter(
  877. // v =>
  878. // Math.sign(comTransform.dir.x) != Math.sign(this.getComponent(v, ComTransform)?.dir.x) &&
  879. // v != comAttackable.curAttack,
  880. // )
  881. //
  882. // otherEnemies.sort((a, b) => {
  883. // let at = this.getComponent(a, ComTransform)
  884. // let bt = this.getComponent(b, ComTransform)
  885. // return at.x ** 2 + at.y ** 2 - (bt.x ** 2 + bt.y ** 2)
  886. // })
  887. // enemies = enemies.concat(otherEnemies)
  888. let enemyComTransform = this.getComponent(enemies[0], ComTransform)
  889. let startPos = cc.v2(comTransform.x, comTransform.y + comTransform.halfHeight)
  890. let hitPos = cc.v2(enemyComTransform.x, enemyComTransform.y + enemyComTransform.halfHeight)
  891. for (let i = 1; i < bulletCfg.splitNum; i++) {
  892. endPosArr.push(this.rotatePoint(startPos, hitPos, 10 * i * (i % 2 == 0 ? -1 : 1)))
  893. }
  894. }
  895. for (let i = 0; i < bulletCfg.splitNum; i++) {
  896. //if (i < enemies.length) {
  897. let enemyComTransform = this.getComponent(enemies[i], ComTransform)
  898. if (!enemyComTransform) {
  899. enemyComTransform = new ComTransform()
  900. enemyComTransform.x = endPosArr[i - 1].x
  901. enemyComTransform.y = endPosArr[i - 1].y
  902. }
  903. let entity = this.createEntity()
  904. // 添加nodeconfig
  905. let comMap = this.addComponent(entity, ComNodeConfig)
  906. comMap.id = 1
  907. comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
  908. comMap.prefabName = GAME_PREFAB_TYPE.bullet
  909. //移除cocosNode
  910. this.removeComponent(entity, ComCocosNode)
  911. // 添加transform
  912. let comTrans = this.addComponent(entity, ComTransform)
  913. let bulletPosScaleX = comTransform.dir.x >= 0 ? 1 : -1
  914. let spineScale = comRole.roleCfg.gameScale[GAME_SCALE_TYPE.spine] / 100
  915. comTrans.x = comTransform.x + comRole.roleCfg.bulletPos[0] * bulletPosScaleX * spineScale
  916. comTrans.y = comTransform.y + comRole.roleCfg.bulletPos[1] * spineScale
  917. let comMovable = this.addComponent(entity, ComMovable)
  918. comMovable.speed = 0
  919. let comBullet = this.addComponent(entity, ComBullet)
  920. comBullet.group = comRole.group == Data.game.gFriend ? Data.game.gFriendBullet : Data.game.gEnemyBullet
  921. comBullet.fightData = {...comRole, roleEntity: role}
  922. comBullet.fightData.buffs = ccUtils.deepCopy(comRole.buffs)
  923. comBullet.bulletCfg = bulletCfg
  924. comBullet.ejectionEnemies.length = 0
  925. comBullet.ejectionEnemy = enemies[i] ? enemies[i] : 0
  926. comBullet.hitEnemies.length = 0
  927. comBullet.isCrit = isCrit
  928. this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
  929. entities.push(entity)
  930. // }
  931. }
  932. return entities
  933. }
  934. public createRoleSkillBulletEntity(
  935. skillConfig: ISkillConfig,
  936. bulletID: number,
  937. createEntity: EntityIndex,
  938. enemy: EntityIndex,
  939. randomPos: boolean = false,
  940. pos?: cc.Vec2,
  941. ): EntityIndex[] {
  942. let bulletCfg = BulletConfig[bulletID]
  943. let roleComTransform = this.getComponent(createEntity, ComTransform)
  944. let enemyComTransform = this.getComponent(enemy, ComTransform)
  945. if (pos) {
  946. enemyComTransform = new ComTransform()
  947. enemyComTransform.x = pos.x
  948. enemyComTransform.y = pos.y
  949. }
  950. if (!enemyComTransform || !bulletCfg) {
  951. return
  952. }
  953. let endPosArr: cc.Vec2[] = []
  954. //跟踪敌人改成固定角度
  955. if (bulletCfg.splitNum > 1) {
  956. let startPos = cc.v2(roleComTransform.x, roleComTransform.y + roleComTransform.halfHeight)
  957. let hitPos = cc.v2(enemyComTransform.x, enemyComTransform.y + enemyComTransform.halfHeight)
  958. for (let i = 1; i < bulletCfg.splitNum; i++) {
  959. endPosArr.push(this.rotatePoint(startPos, hitPos, 10 * i * (i % 2 == 0 ? -1 : 1)))
  960. }
  961. }
  962. let entityArr = []
  963. for (let i = 0; i < bulletCfg.splitNum; i++) {
  964. let entity = this.createEntity()
  965. // 添加nodeconfig
  966. let comMap = this.addComponent(entity, ComNodeConfig)
  967. comMap.id = 1
  968. comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
  969. comMap.prefabName = GAME_PREFAB_TYPE.bullet
  970. //移除cocosNode
  971. this.removeComponent(entity, ComCocosNode)
  972. let comRole = this.getComponent(createEntity, ComRole)
  973. // 添加transform
  974. let comTrans = this.addComponent(entity, ComTransform)
  975. let bulletPosScaleX = roleComTransform.dir.x >= 0 ? 1 : -1
  976. let spineScale = comRole.roleCfg.gameScale[GAME_SCALE_TYPE.spine] / 100
  977. comTrans.x = roleComTransform.x + comRole.roleCfg.bulletPos[0] * bulletPosScaleX * spineScale
  978. comTrans.y =
  979. roleComTransform.y +
  980. (comRole.roleCfg.bulletPos[1] ? comRole.roleCfg.bulletPos[1] * spineScale : roleComTransform.halfHeight)
  981. let comMovable = this.addComponent(entity, ComMovable)
  982. comMovable.speed = 0
  983. let comBullet = this.addComponent(entity, ComBullet)
  984. comBullet.group = comRole.group == Data.game.gFriend ? Data.game.gFriendBullet : Data.game.gEnemyBullet
  985. comBullet.fightData = {...comRole, roleEntity: createEntity}
  986. comBullet.bulletCfg = bulletCfg
  987. comBullet.ejectionEnemies.length = 0
  988. comBullet.ejectionEnemy = enemy
  989. comBullet.hitEnemies.length = 0
  990. comBullet.isCrit = false
  991. //特效子弹位置随机
  992. if (randomPos) {
  993. let randomWidth = SkillConfig[bulletCfg.skill]
  994. ? SkillConfig[bulletCfg.skill].attackRangeX
  995. : skillConfig.attackRangeX
  996. let randomHeight = SkillConfig[bulletCfg.skill]
  997. ? SkillConfig[bulletCfg.skill].attackRangeY
  998. : skillConfig.attackRangeY
  999. let randomX = enemyComTransform.x + Math.randomRangeFloat(-randomWidth / 2, randomWidth / 2)
  1000. let randomY = enemyComTransform.y + Math.randomRangeFloat(-randomHeight / 2, randomHeight / 2)
  1001. enemyComTransform = new ComTransform()
  1002. enemyComTransform.x = randomX
  1003. enemyComTransform.y = randomY
  1004. }
  1005. if (bulletCfg.born == START_POS.straightFall || bulletCfg.born == START_POS.obliqueFall) {
  1006. comTrans.x = enemyComTransform.x - (bulletCfg.born == START_POS.obliqueFall ? 200 : 0)
  1007. comTrans.y = ConstValue.CANVAS_HEIGHT / 2
  1008. }
  1009. if (i > 0) {
  1010. enemyComTransform = new ComTransform()
  1011. enemyComTransform.x = endPosArr[i - 1].x
  1012. enemyComTransform.y = endPosArr[i - 1].y
  1013. }
  1014. this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
  1015. entityArr.push(entity)
  1016. }
  1017. return entityArr
  1018. }
  1019. public createCardBulletEntity(
  1020. iCard: ICard,
  1021. startPos: cc.Vec2,
  1022. endPos: cc.Vec2,
  1023. enemy: EntityIndex = 0,
  1024. ): EntityIndex {
  1025. let cardSkillCfg = iCard.cfg
  1026. let bulletCfg = BulletConfig[cardSkillCfg.bullet]
  1027. let entity = this.createEntity()
  1028. // 添加nodeconfig
  1029. let comMap = this.addComponent(entity, ComNodeConfig)
  1030. comMap.id = 1
  1031. comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
  1032. comMap.prefabName = GAME_PREFAB_TYPE.bullet
  1033. //移除cocosNode
  1034. this.removeComponent(entity, ComCocosNode)
  1035. // 添加transform
  1036. let comTrans = this.addComponent(entity, ComTransform)
  1037. comTrans.x = startPos.x
  1038. comTrans.y = startPos.y
  1039. let comMovable = this.addComponent(entity, ComMovable)
  1040. comMovable.speed = 0
  1041. let comBullet = this.addComponent(entity, ComBullet)
  1042. comBullet.group = Data.game.gFriendBullet
  1043. comBullet.fightData = {buffs: [], entryMap: new Map<ENTRY, EntryObj>(), ...iCard}
  1044. comBullet.bulletCfg = bulletCfg
  1045. comBullet.ejectionEnemies.length = 0
  1046. comBullet.ejectionEnemy = enemy
  1047. comBullet.hitEnemies.length = 0
  1048. comBullet.isCrit = false
  1049. let enemyComTransform = new ComTransform()
  1050. enemyComTransform.x = endPos.x
  1051. enemyComTransform.y = endPos.y
  1052. this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
  1053. return entity
  1054. }
  1055. public createBaseBulletEntity(posOrTrans: ComTransform | cc.Vec2) {
  1056. let sysCastleSkill = this.getSystem(SysCastleSkill)
  1057. if (sysCastleSkill.rechargeTime > 0) {
  1058. Mgr.ui.tip(LANGUAGE_TYPE.inRecharge)
  1059. return
  1060. }
  1061. if (!Data.user.useCastleSkillID) return
  1062. sysCastleSkill.reduceLeftNum()
  1063. let entity = this.createEntity()
  1064. // 添加nodeconfig
  1065. let comMap = this.addComponent(entity, ComNodeConfig)
  1066. comMap.id = 1
  1067. comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
  1068. comMap.prefabName = GAME_PREFAB_TYPE.bullet
  1069. //移除cocosNode
  1070. this.removeComponent(entity, ComCocosNode)
  1071. // 添加transform
  1072. let comTrans = this.addComponent(entity, ComTransform)
  1073. comTrans.x = -10000
  1074. comTrans.y = 10000
  1075. let comMovable = this.addComponent(entity, ComMovable)
  1076. comMovable.speed = 0
  1077. let comBullet = this.addComponent(entity, ComBullet)
  1078. comBullet.group = Data.game.gFriendBullet
  1079. let baseBulletCfg = CastleSkillConfig[Data.user.useCastleSkillID]
  1080. comBullet.fightData = {buffs: [], entryMap: new Map<ENTRY, EntryObj>(), ...baseBulletCfg}
  1081. comBullet.bulletCfg = BulletConfig[baseBulletCfg.bullet]
  1082. comBullet.ejectionEnemies.length = 0
  1083. comBullet.ejectionEnemy = 0
  1084. comBullet.hitEnemies.length = 0
  1085. comBullet.ejectionAnis.length = 0
  1086. comBullet.isCrit = false
  1087. let enemyComTransform
  1088. if (posOrTrans instanceof ComTransform) {
  1089. enemyComTransform = posOrTrans
  1090. } else {
  1091. let startPos = cc.v2(comTrans.x, comTrans.y)
  1092. let direction = posOrTrans.sub(startPos).normalize()
  1093. let endPos = startPos.add(direction.mul(baseBulletCfg.attackRange))
  1094. enemyComTransform = new ComTransform()
  1095. enemyComTransform.x = endPos.x
  1096. enemyComTransform.y = endPos.y
  1097. }
  1098. this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
  1099. return entity
  1100. }
  1101. public initBulletDir(
  1102. comTrans: ComTransform,
  1103. enemyComTransform: ComTransform,
  1104. comMovable: ComMovable,
  1105. comBullet: ComBullet,
  1106. comCocosNode?: ComCocosNode,
  1107. ) {
  1108. let startPos = cc.v2(comTrans.x, comTrans.y)
  1109. let hitPos = cc.v2(enemyComTransform.x, enemyComTransform.y + enemyComTransform.halfHeight)
  1110. // 计算子弹的飞行方向向量
  1111. let direction = hitPos.sub(startPos).normalize()
  1112. let bulletCfg = comBullet.bulletCfg
  1113. if (
  1114. !bulletCfg.isEjection &&
  1115. bulletCfg.type == BULLET_TYPE.normal &&
  1116. !bulletCfg.effectType.includes(BULLET_EFFECT_TYPE.attackRange) &&
  1117. !bulletCfg.effectType.includes(BULLET_EFFECT_TYPE.boomerangRange)
  1118. ) {
  1119. //如果是直线子弹,将子弹终点设置为边界外的某个点,子弹到达边界点,移除子弹
  1120. hitPos = this.findIntersection(startPos, direction)
  1121. //当子弹从区域外进入,直接让子弹结束
  1122. if (!hitPos) hitPos = startPos
  1123. }
  1124. let hitPosArr = [hitPos]
  1125. if (bulletCfg.flyType == BULLET_FLY_TYPE.parabolic) {
  1126. hitPosArr = this.getParabolaPoints(startPos, hitPos, 50)
  1127. if (hitPosArr.length >= 2) direction = hitPosArr[1].sub(hitPosArr[0]).normalize()
  1128. } else if (bulletCfg.flyType == BULLET_FLY_TYPE.bezier) {
  1129. hitPosArr.length = 0
  1130. hitPosArr.push(...this.getEquidistantPoints(startPos, hitPos, 10, comBullet.group))
  1131. hitPosArr.push(hitPos)
  1132. } else if (bulletCfg.flyType == BULLET_FLY_TYPE.boomerang) {
  1133. hitPosArr.length = 0
  1134. let parms = bulletCfg.effectParm[bulletCfg.effectType.indexOf(BULLET_EFFECT_TYPE.boomerangRange)]
  1135. let halfPoints = this.getEquidistantPoints(startPos, hitPos, 10, comBullet.group, parms[1])
  1136. let leftPoints = this.getEquidistantPoints(hitPos, startPos, 10, comBullet.group, parms[1])
  1137. hitPosArr.push(...halfPoints)
  1138. hitPosArr.push(hitPos)
  1139. hitPosArr.push(...leftPoints)
  1140. hitPosArr.push(startPos)
  1141. } else if (bulletCfg.flyType == BULLET_FLY_TYPE.horizon) {
  1142. hitPosArr.length = 0
  1143. hitPosArr.push(cc.v2(comTrans.x + (direction.x >= 0 ? 1000 : -1000), comTrans.y))
  1144. }
  1145. comTrans.dir.x = direction.x
  1146. comTrans.dir.y = direction.y
  1147. comMovable.pointIdx = 0
  1148. comMovable.points.length = 0
  1149. comMovable.points.push(...hitPosArr)
  1150. if (comCocosNode) {
  1151. //计算发射角度
  1152. let angle = Math.atan2(comTrans.dir.y, comTrans.dir.x)
  1153. comCocosNode.node.angle = cc.misc.radiansToDegrees(angle)
  1154. }
  1155. }
  1156. getParabolaPoints(a: cc.Vec2, b: cc.Vec2, interval: number): cc.Vec2[] {
  1157. let xA = a.x,
  1158. yA = a.y
  1159. let xB = b.x,
  1160. yB = b.y
  1161. let yMax = Data.game.fightSizeMaxY - Math.randomRangeInt(0, Data.game.fightSizeMaxY - Math.max(yA, yB)) // 最高点的高度
  1162. let xC = (xA + xB) / 2 // 假设C是A和B的中点(水平方向)
  1163. let xD = xA + (xC - xA) / 2 // 控制点D的x坐标是A和C的x坐标的平均值
  1164. let yD = yA + (yMax - yA) / 2 // 控制点D的y坐标是A和最高点之间的某个值(这里取中点)
  1165. let points = []
  1166. let step = 1 / (interval - 1)
  1167. for (let t = 0; t <= 1; t += step) {
  1168. let x =
  1169. Math.pow(1 - t, 3) * xA +
  1170. 3 * Math.pow(1 - t, 2) * t * xD +
  1171. 3 * (1 - t) * Math.pow(t, 2) * xC +
  1172. Math.pow(t, 3) * xB
  1173. let y =
  1174. Math.pow(1 - t, 3) * yA +
  1175. 3 * Math.pow(1 - t, 2) * t * yD +
  1176. 3 * (1 - t) * Math.pow(t, 2) * yMax +
  1177. Math.pow(t, 3) * yB
  1178. points.push(cc.v2(x, y))
  1179. }
  1180. return points
  1181. }
  1182. boundaries = [
  1183. {dir: 'right', eq: Data.game.fightAreaMaxX, var: 'x'}, // 右边界
  1184. {dir: 'left', eq: Data.game.fightAreaMinX, var: 'x'}, // 左边界
  1185. {dir: 'top', eq: Data.game.fightAreaMaxY, var: 'y'}, // 上边界
  1186. {dir: 'bottom', eq: Data.game.fightAreaMinY, var: 'y'}, // 下边界
  1187. ]
  1188. findIntersection(a, v) {
  1189. // 将矩形边界转换为线性方程组
  1190. // 例如,对于矩形的上边界(y-centerY = height/2),转换为 y = centerY + height/2
  1191. // 并以此类推其他三个边界
  1192. // 定义四个边界线性方程
  1193. let intersection = null
  1194. //起点Y位置加上了人物身高,这里做个限制,让子弹起始点在屏幕内
  1195. this.boundaries.forEach(boundary => {
  1196. let t
  1197. if (boundary.var === 'x') {
  1198. // 解 x = a.x + t*v.x
  1199. t = (boundary.eq - a.x) / v.x
  1200. } else {
  1201. // 解 y = a.y + t*v.y
  1202. t = (boundary.eq - a.y) / v.y
  1203. }
  1204. // 检查t是否在[0, +∞)范围内,确保交点在射线方向上且不过原点
  1205. if (t >= 0) {
  1206. let intersectPoint = cc.v2(a.x + t * v.x, a.y + t * v.y)
  1207. // 判断交点是否在矩形内或边上
  1208. if (
  1209. (boundary.dir === 'right' || boundary.dir === 'left') &&
  1210. intersectPoint.y >= Data.game.fightAreaMinY &&
  1211. intersectPoint.y <= Data.game.fightAreaMaxY
  1212. ) {
  1213. if (!intersection || intersection.sub(a).mag() < intersectPoint.sub(a).mag())
  1214. intersection = intersectPoint
  1215. } else if (
  1216. (boundary.dir === 'top' || boundary.dir === 'bottom') &&
  1217. intersectPoint.x >= Data.game.fightAreaMinX &&
  1218. intersectPoint.x <= Data.game.fightAreaMaxX
  1219. ) {
  1220. if (!intersection || intersection.sub(a).mag() < intersectPoint.sub(a).mag())
  1221. intersection = intersectPoint
  1222. }
  1223. }
  1224. })
  1225. return intersection
  1226. }
  1227. public removeBulletEntity(entity: EntityIndex) {
  1228. let comCocosNode = this.getComponent(entity, ComCocosNode)
  1229. let comBullet = this.getComponent(entity, ComBullet)
  1230. if (!comBullet) {
  1231. return
  1232. //console.log('子弹已经移除')
  1233. }
  1234. //1秒后移除弹射特效
  1235. comBullet.ejectionAnis.forEach(aniEntity => {
  1236. let aniEntityCom = this.getComponent(aniEntity, ComFrameAni)
  1237. if (aniEntityCom && aniEntityCom.countDown > 1) aniEntityCom.countDown = 1
  1238. })
  1239. if (comBullet.cObject) {
  1240. cCollider.inst.remove(comBullet.cObject.body)
  1241. comCocosNode.node.removeComponent(comBullet.cObject)
  1242. comBullet.cObject = null
  1243. }
  1244. this.removeNodeEntity(entity)
  1245. }
  1246. rotatePoint(a: cc.Vec2, b: cc.Vec2, angleDegrees: number): cc.Vec2 {
  1247. // 将角度转换为弧度
  1248. const angleRadians = (angleDegrees * Math.PI) / 180
  1249. // 计算cos和sin值
  1250. const cosAngle = Math.cos(angleRadians)
  1251. const sinAngle = Math.sin(angleRadians)
  1252. // 计算新的坐标
  1253. const x_new = (b.x - a.x) * cosAngle - (b.y - a.y) * sinAngle + a.x
  1254. const y_new = (b.x - a.x) * sinAngle + (b.y - a.y) * cosAngle + a.y
  1255. return cc.v2(x_new, y_new)
  1256. }
  1257. bezierPoint(t, a, c, d, b) {
  1258. let x =
  1259. Math.pow(1 - t, 3) * a.x +
  1260. 3 * Math.pow(1 - t, 2) * t * c.x +
  1261. 3 * (1 - t) * Math.pow(t, 2) * d.x +
  1262. Math.pow(t, 3) * b.x
  1263. let y =
  1264. Math.pow(1 - t, 3) * a.y +
  1265. 3 * Math.pow(1 - t, 2) * t * c.y +
  1266. 3 * (1 - t) * Math.pow(t, 2) * d.y +
  1267. Math.pow(t, 3) * b.y
  1268. return cc.v2(x, y)
  1269. }
  1270. getBezierLength(a, c, d, b, numPoints) {
  1271. let length = 0
  1272. let previousPoint = a
  1273. for (let i = 1; i <= numPoints; i++) {
  1274. let t = i / numPoints
  1275. let currentPoint = this.bezierPoint(t, a, c, d, b)
  1276. length += previousPoint.sub(currentPoint).mag()
  1277. previousPoint = currentPoint
  1278. }
  1279. return length
  1280. }
  1281. getEquidistantPoints(a, b, numPoints, group, height?) {
  1282. let {c, d} = this.calculatePointCD(a.x, a.y, b.x, b.y, group, height)
  1283. let points = []
  1284. let totalLength = this.getBezierLength(a, c, d, b, numPoints)
  1285. let segmentLength = totalLength / (numPoints - 1)
  1286. let previousPoint = a
  1287. points.push(previousPoint)
  1288. for (let i = 1; i < numPoints; i++) {
  1289. let targetLength = segmentLength * i
  1290. let low = (i - 1) / numPoints
  1291. let high = i / numPoints
  1292. while (high - low > 1e-5) {
  1293. let mid = (low + high) / 2
  1294. let point = this.bezierPoint(mid, a, c, d, b)
  1295. let length = previousPoint.sub(point).mag()
  1296. if (length < targetLength) {
  1297. low = mid
  1298. } else {
  1299. high = mid
  1300. }
  1301. }
  1302. let point = this.bezierPoint((low + high) / 2, a, c, d, b)
  1303. points.push(point)
  1304. previousPoint = point
  1305. }
  1306. return points
  1307. }
  1308. calculatePointCD(x1, y1, x2, y2, group, height?) {
  1309. let a = cc.v2(x1, y1)
  1310. let b = cc.v2(x2, y2)
  1311. let dir = b.sub(a).normalize()
  1312. let length = a.sub(b).mag()
  1313. let k = Math.max(100000 / length, 50)
  1314. k = Math.min(k, 100)
  1315. if (height) k = height
  1316. // 垂直方向向量
  1317. let vDir = dir.rotate(90 * (Math.PI / 180)).mul(group == Data.game.gFriendBullet ? 1 : -1)
  1318. let c = a.add(vDir.mul(k)).add(dir.mul(length / 3))
  1319. let d = a.add(vDir.mul(k)).add(dir.mul((length * 2) / 3))
  1320. return {c, d}
  1321. }
  1322. //-------------------------------技能-----------------------------------------
  1323. public createSkill(
  1324. fightData: IFightData,
  1325. skillCfg: ISkillConfig,
  1326. role: EntityIndex,
  1327. pos?: cc.Vec3,
  1328. group?: number,
  1329. ) {
  1330. let entity = this.createEntity()
  1331. // 添加nodeconfig
  1332. let comMap = this.addComponent(entity, ComNodeConfig)
  1333. comMap.id = 1
  1334. comMap.layer = GAME_LAYER[skillCfg.layer ? skillCfg.layer : GAME_LAYER.skill]
  1335. comMap.prefabName = GAME_PREFAB_TYPE.skill
  1336. //移除cocosNode
  1337. this.removeComponent(entity, ComCocosNode)
  1338. // 添加transform
  1339. let comTrans = this.addComponent(entity, ComTransform)
  1340. //提升自己数值技能
  1341. let comSkill = this.addComponent(entity, ComSkill)
  1342. comSkill.skillCfg = skillCfg
  1343. comSkill.fightData = fightData
  1344. comSkill.countDown = skillCfg.duration
  1345. comSkill.role = role
  1346. comSkill.group = group
  1347. comSkill.hurtFrameCompleted = false
  1348. comSkill.dirty = false
  1349. if (role > 0) {
  1350. let comRoleTrans = this.getComponent(role, ComTransform)
  1351. let comRole = this.getComponent(role, ComRole)
  1352. comTrans.x = comRoleTrans.x
  1353. comTrans.y = comRoleTrans.y + comRoleTrans.halfHeight * (skillCfg.offsetPos[0] - 1)
  1354. comSkill.group =
  1355. comRole.group == Data.game.gFriend
  1356. ? skillCfg.isHurt
  1357. ? skillCfg.dirType == SKILL_DIR_TYPE.selfNormal
  1358. ? Data.game.gFriendHurtSkill
  1359. : Data.game.gEnemyHurtSkill
  1360. : Data.game.gFriendGainSkill
  1361. : skillCfg.isHurt
  1362. ? skillCfg.dirType == SKILL_DIR_TYPE.selfNormal
  1363. ? Data.game.gEnemyHurtSkill
  1364. : Data.game.gFriendHurtSkill
  1365. : Data.game.gEnemyGainSkill
  1366. } else {
  1367. if (!pos || !group) Log.error('技能创建失败')
  1368. comTrans.x = pos.x
  1369. comTrans.y = pos.y
  1370. }
  1371. comTrans.x += skillCfg.offsetPos[1]
  1372. comTrans.y += skillCfg.offsetPos[2]
  1373. if (skillCfg.type == SKILL_TYPE.attackBack && skillCfg.effectType.indexOf(SKILL_EFFECT_TYPE.move) >= 0) {
  1374. let comMovable = this.addComponent(entity, ComMovable)
  1375. comMovable.pointIdx = 0
  1376. comMovable.points.length = 0
  1377. comMovable.speed = skillCfg.effectParm[skillCfg.effectType.indexOf(SKILL_EFFECT_TYPE.move)][0]
  1378. comMovable.points.push(
  1379. cc.v2(
  1380. comSkill.group == Data.game.gFriendHurtSkill || comSkill.group == Data.game.gFriendGainSkill
  1381. ? Data.game.fightAreaMaxX
  1382. : Data.game.fightAreaMinX,
  1383. comTrans.y,
  1384. ),
  1385. )
  1386. }
  1387. return entity
  1388. }
  1389. public createSkillByFightData(fightData: IFightData, skillCfg: ISkillConfig, roles: EntityIndex[]) {
  1390. let isSuccess = false
  1391. roles.forEach((role: EntityIndex) => {
  1392. let comRole = this.getComponent(role, ComRole)
  1393. if (this.isDie(comRole)) return
  1394. this.createSkill(fightData, skillCfg, role)
  1395. isSuccess = true
  1396. })
  1397. return isSuccess
  1398. }
  1399. public createCardBulletSkill(comBullet: ComBullet, role: EntityIndex, pos?: cc.Vec3) {
  1400. //卡牌弹射子弹每次命中目标放技能
  1401. let skillCfg = SkillConfig[comBullet.bulletCfg.skill]
  1402. for (let i = 0; i < skillCfg.effectType.length; i++) {
  1403. let type = skillCfg.effectType[i]
  1404. if (type == SKILL_EFFECT_TYPE.reduce) {
  1405. comBullet.fightData.attack *= 1 - skillCfg.effectParm[i][0] / Data.game.rateNum
  1406. comBullet.fightData.spellAttack *= 1 - skillCfg.effectParm[i][0] / Data.game.rateNum
  1407. comBullet.fightData.realAttack *= 1 - skillCfg.effectParm[i][0] / Data.game.rateNum
  1408. }
  1409. }
  1410. if (role) {
  1411. this.createSkillByFightData(comBullet.fightData, skillCfg, [role])
  1412. } else {
  1413. let skillEntity = this.createSkill(
  1414. comBullet.fightData,
  1415. skillCfg,
  1416. 0,
  1417. pos,
  1418. comBullet.group == Data.game.gEnemyBullet
  1419. ? skillCfg.isHurt
  1420. ? Data.game.gEnemyHurtSkill
  1421. : Data.game.gEnemyGainSkill
  1422. : skillCfg.isHurt
  1423. ? Data.game.gFriendHurtSkill
  1424. : Data.game.gFriendGainSkill,
  1425. )
  1426. let tmp = this.getComponent(skillEntity, ComSkill)
  1427. }
  1428. //地板受击
  1429. if (skillCfg.hitID[HIT_ANI_TYPE.floor]) {
  1430. this.createAni(skillCfg.hitID[HIT_ANI_TYPE.floor], role, role ? null : cc.v2(pos))
  1431. }
  1432. }
  1433. public isOneRoleSkill(skillCfg: ISkillConfig): boolean {
  1434. return (
  1435. skillCfg.dirType == SKILL_DIR_TYPE.selfRole ||
  1436. skillCfg.dirType == SKILL_DIR_TYPE.anyRole ||
  1437. skillCfg.dirType == SKILL_DIR_TYPE.minHpRole ||
  1438. skillCfg.dirType == SKILL_DIR_TYPE.baby
  1439. )
  1440. }
  1441. removeSkillEntity(entity) {
  1442. let comSkill = this.getComponent(entity, ComSkill)
  1443. let comCocosNode = this.getComponent(entity, ComCocosNode)
  1444. if (!comSkill || !comCocosNode) return
  1445. cCollider.inst.remove(comSkill.cObject.body)
  1446. comCocosNode.node.removeComponent(comSkill.cObject)
  1447. comSkill.cObject = null
  1448. this.removeNodeEntity(entity)
  1449. }
  1450. //-------------------------------BUFF-----------------------------------------
  1451. public createBuff(buffID, fightData: IFightData) {
  1452. if (!BuffConfig[buffID]) return
  1453. let buff = {buffCfg: BuffConfig[buffID]} as IBuff
  1454. buff.countDown = buff.buffCfg.duration == Data.game.cdMax ? Infinity : buff.buffCfg.duration
  1455. buff.countUp = 0
  1456. buff.hurtFrameCompleted = false
  1457. buff.hurtTimes = 0
  1458. buff.immuneTimes = 0
  1459. buff.curAttrChangeNum = []
  1460. buff.createBaseAttr = Mgr.global.buildIBaseAttr(fightData, !fightData)
  1461. buff.aniEntityArr = []
  1462. return buff
  1463. }
  1464. public addBuff(skillEntity: EntityIndex, buff: IBuff, fightData: IFightData) {
  1465. if (!buff) return
  1466. let comRoleSkill = this.getComponent(skillEntity, ComRole)
  1467. let comRoleTrans = this.getComponent(skillEntity, ComTransform)
  1468. let comCocosNodeSkill = this.getComponent(skillEntity, ComCocosNode)
  1469. let comHasSkillSkill = this.getComponent(skillEntity, ComHasSkill)
  1470. let comSpineNode = this.getComponent(comRoleSkill.spineEntity, ComCocosNode)
  1471. if (!comCocosNodeSkill || !comCocosNodeSkill.loaded || this.isDie(comRoleSkill) || this.isBase(comRoleSkill)) {
  1472. return
  1473. }
  1474. //图腾对象不施加BUFF
  1475. if (comRoleSkill.roleCfg.type == ROLE_TYPE.totem) return
  1476. let sameIDBuffs = comRoleSkill.buffs.filter(buffTmp => buffTmp.buffCfg.ID == buff.buffCfg.ID)
  1477. let buffCfg = buff.buffCfg
  1478. let sameArrIDBuffs = comRoleSkill.buffs.filter(
  1479. buffTmp => buffCfg.arrID > 0 && buffTmp.buffCfg.arrID == buffCfg.arrID,
  1480. )
  1481. let addBuffFuc = (isReplace: boolean = false) => {
  1482. let hasImmune = false
  1483. comRoleSkill.buffs.forEach(buffTmp => {
  1484. let buffCfg = buffTmp.buffCfg
  1485. if (buffCfg.buffType == BUFF_TYPE.negativeImmune) {
  1486. let negativeArr = buffCfg.effectParm[buffCfg.effectType.indexOf(BUFF_EFFECT_TYPE.immuneNegative)]
  1487. if (negativeArr) {
  1488. hasImmune ||=
  1489. negativeArr.includes(NEGATIVE_TYPE.delay) && buff.buffCfg.buffType == BUFF_TYPE.dizzy
  1490. hasImmune ||=
  1491. negativeArr.includes(NEGATIVE_TYPE.slow) &&
  1492. buff.buffCfg.attrRate[buff.buffCfg.attr.indexOf(ATTR_NAME.moveSpeed)] < 0
  1493. }
  1494. }
  1495. })
  1496. if (hasImmune) return
  1497. //光环buff不施放,在处理hasSkill处理
  1498. comRoleSkill.buffs.push(buff)
  1499. //comCocosNodeSkill.events.push(new EventBuffChange(comRoleSkill.buffs, [buff], []))
  1500. for (let aniID of buff.buffCfg.buffUrl) {
  1501. if (!aniID || isReplace) continue
  1502. if (aniID == BUFF_ANI_TYPE.slow) {
  1503. comSpineNode?.events.push(new EventSlowDown(true))
  1504. }
  1505. buff.aniEntityArr.push(this.createAni(aniID, skillEntity))
  1506. }
  1507. buffCfg.buffIcon.forEach(value => {
  1508. console.log('推入buff', value)
  1509. comCocosNodeSkill.events.push(new EventRoleTip(GAME_ROLE_TIP.buffTip, buffCfg.hurtEffect, value))
  1510. })
  1511. if (buff.buffCfg.buffType == BUFF_TYPE.dizzy) {
  1512. let comDizzy = this.getComponent(skillEntity, ComDizzy)
  1513. if (comDizzy && !this.isDie(comRoleSkill)) {
  1514. comDizzy.countDown = buff.buffCfg.attrNum[0]
  1515. for (let i = 0; i < buff.buffCfg.effectType.length; i++) {
  1516. let type = buff.buffCfg.effectType[i]
  1517. if (type == BUFF_EFFECT_TYPE.boss && comRoleSkill.roleCfg.type == MONSTER_TYPE.boss) {
  1518. comDizzy.countDown *= 1 - buff.buffCfg.effectParm[i][0] / Data.game.rateNum
  1519. }
  1520. }
  1521. if (comRoleSkill.entryMap.get(ENTRY.delayReduce)?.num) {
  1522. comDizzy.countDown *= 1 - comRoleSkill.entryMap.get(ENTRY.delayReduce).num / Data.game.rateNum
  1523. }
  1524. if (fightData && fightData.entryMap.get(ENTRY.delayAdd)?.num) {
  1525. comDizzy.countDown *= 1 + fightData.entryMap.get(ENTRY.delayAdd).num / Data.game.rateNum
  1526. }
  1527. //将顶盾的buff去掉
  1528. let findIndex = comRoleSkill.buffs.findIndex(
  1529. value => value.buffCfg.buffType == BUFF_TYPE.shieldReduceHurt,
  1530. )
  1531. if (findIndex != -1) comRoleSkill.buffs.splice(findIndex, 1)
  1532. let comDizzySkillAbel = this.getComponent(skillEntity, ComSkillAbel)
  1533. comDizzySkillAbel.isInShield = false
  1534. //将顶盾的罩子,友军免疫远程攻击buff去掉
  1535. this.removeNodeEntity(comDizzySkillAbel.ani)
  1536. let skillIndex = comRoleSkill.skills.findIndex(v => v.type == SKILL_TYPE.holo)
  1537. if (skillIndex >= 0) {
  1538. let allEntity = Array.from(comHasSkillSkill.skillCObjects[skillIndex].containsBody.keys())
  1539. allEntity = allEntity.filter(entityTmp => !this.isDie(entityTmp))
  1540. allEntity.forEach(v => {
  1541. let tmpComRole = this.getComponent(v, ComRole)
  1542. let findIndex = tmpComRole.buffs.findIndex(
  1543. value => value.buffCfg.buffType == BUFF_TYPE.rangedImmune,
  1544. )
  1545. if (findIndex != -1) {
  1546. console.warn('去掉免疫buff')
  1547. tmpComRole.buffs.splice(findIndex, 1)
  1548. }
  1549. })
  1550. }
  1551. //将技能弹射子弹去除
  1552. if (comDizzySkillAbel.bullets) {
  1553. comDizzySkillAbel.bullets.forEach(v => {
  1554. this.removeBulletEntity(v)
  1555. })
  1556. comDizzySkillAbel.bullets.length = 0
  1557. }
  1558. }
  1559. }
  1560. }
  1561. let replaceBuffFuc = (replaceBuff: IBuff) => {
  1562. //addType==0直接替换,==1替换效果最好的
  1563. if (
  1564. buffCfg.addType == 0 ||
  1565. (buffCfg.addType == 1 && buffCfg.attrRate[0] >= replaceBuff.buffCfg.attrRate[0])
  1566. ) {
  1567. let removeBuffs = comRoleSkill.buffs.splice(comRoleSkill.buffs.indexOf(replaceBuff), 1)
  1568. this.removeBuffAttr(skillEntity, removeBuffs[0])
  1569. addBuffFuc(true)
  1570. //特效继承,时间重置
  1571. buff.aniEntityArr.push(...removeBuffs[0].aniEntityArr)
  1572. for (let aniEntity of buff.aniEntityArr) {
  1573. let comFrameAni = this.getComponent(aniEntity, ComFrameAni)
  1574. if (comFrameAni) comFrameAni.countDown = comFrameAni.aniConfig.duration
  1575. }
  1576. }
  1577. }
  1578. if (buffCfg.arrID > 0) {
  1579. //有buff组,根据叠加和替换规则确定是否叠加和替换
  1580. if (buffCfg.isAdd && (!buffCfg.addNum || (buffCfg.addNum > 0 && sameArrIDBuffs.length < buffCfg.addNum))) {
  1581. //叠加
  1582. addBuffFuc()
  1583. } else if (!buffCfg.isAdd) {
  1584. //不叠加
  1585. if (sameArrIDBuffs.length == 0) {
  1586. addBuffFuc()
  1587. } else {
  1588. replaceBuffFuc(sameArrIDBuffs[0])
  1589. }
  1590. }
  1591. } else {
  1592. //不叠加
  1593. if (sameIDBuffs.length == 0) {
  1594. addBuffFuc()
  1595. } else {
  1596. replaceBuffFuc(sameIDBuffs[0])
  1597. }
  1598. }
  1599. }
  1600. public removeBuffAttr(role: EntityIndex, buff: IBuff) {
  1601. let comRole = this.getComponent(role, ComRole)
  1602. if (this.isDie(comRole)) return
  1603. let buffConfig = buff.buffCfg
  1604. for (let j = 0; j < buffConfig.attr.length; j++) {
  1605. if (buff.curAttrChangeNum[j]) {
  1606. comRole[buffConfig.attr[j]] -= buff.curAttrChangeNum[j]
  1607. if (buffConfig.attr[j] == ATTR_NAME.attackRange) {
  1608. let comFindEnemy = this.getComponent(role, ComFindEnemy)
  1609. if (comFindEnemy.attackCObject.radius != comRole.attackRange) {
  1610. comFindEnemy.attackCObject.updateSphereShape(comRole.attackRange)
  1611. }
  1612. }
  1613. }
  1614. }
  1615. }
  1616. //-------------------------------特效-----------------------------------------
  1617. public createAni(aniID: number, role: EntityIndex, pos?: cc.Vec2) {
  1618. let frameAniConfig = FrameAniConfig[aniID]
  1619. if (!frameAniConfig) {
  1620. console.error('frameAniID不存在', aniID)
  1621. return
  1622. }
  1623. if (frameAniConfig.type == ANI_TYPE.shader) return
  1624. let entity = this.createEntity()
  1625. // 添加nodeconfig
  1626. let comMap = this.addComponent(entity, ComNodeConfig)
  1627. comMap.id = 1
  1628. comMap.layer = GAME_LAYER[frameAniConfig.layer ? frameAniConfig.layer : GAME_LAYER.skill]
  1629. comMap.prefabName = GAME_PREFAB_TYPE.frameAni
  1630. //移除cocosNode
  1631. this.removeComponent(entity, ComCocosNode)
  1632. // 添加transform
  1633. let comTrans = this.addComponent(entity, ComTransform)
  1634. let comFrameAni = this.addComponent(entity, ComFrameAni)
  1635. comFrameAni.countDown = frameAniConfig.duration
  1636. comFrameAni.dirty = false
  1637. comFrameAni.aniConfig = frameAniConfig
  1638. comFrameAni.role = role
  1639. comFrameAni.lineStartPos = null
  1640. comFrameAni.lineStartEntity = 0
  1641. comFrameAni.lineEndEntity = 0
  1642. let comRoleTrans = this.getComponent(role, ComTransform)
  1643. if (pos) {
  1644. comTrans.x = pos.x
  1645. comTrans.y = pos.y
  1646. } else if (comRoleTrans) {
  1647. comTrans.x = comRoleTrans.x
  1648. comTrans.y =
  1649. comRoleTrans.y +
  1650. (frameAniConfig.offsetPos[0] ? comRoleTrans.halfHeight * (frameAniConfig.offsetPos[0] - 1) : 0)
  1651. }
  1652. comTrans.x += frameAniConfig.offsetPos[1]
  1653. comTrans.y += frameAniConfig.offsetPos[2]
  1654. return entity
  1655. }
  1656. //--------------------------------词条-------------------------------------------------
  1657. isGameEntry(type: ENTRY) {
  1658. return type >= ENTRY.ignoreDefense && type <= 100
  1659. }
  1660. initEntry() {
  1661. if (Data.game.gameType != GAME_TYPE.relic) {
  1662. for (let id of Data.user.talents) {
  1663. let talentCfg = TalentConfig[id]
  1664. let type = EntryConfig[talentCfg.entryID].type
  1665. switch (type) {
  1666. case ENTRY.startCostAdd:
  1667. break
  1668. }
  1669. }
  1670. }
  1671. }
  1672. convertEntry2Obj(entryID: number): EntryObj {
  1673. let entryCfg = EntryConfig[entryID]
  1674. let num = 0
  1675. if (entryCfg.parmArr[0] && entryCfg.parmArr.length == 1) num = entryCfg.parmArr[0]
  1676. if (entryCfg.rateArr[0] && entryCfg.rateArr.length == 1) num = entryCfg.rateArr[0]
  1677. let numArrTmp = []
  1678. if (entryCfg.parmArr.length > 1) numArrTmp.push(entryCfg.parmArr)
  1679. if (entryCfg.rateArr.length > 1) numArrTmp.push(entryCfg.rateArr)
  1680. return {num, numArr: numArrTmp, type: entryCfg.type, profession: entryCfg.profession}
  1681. }
  1682. putEntry2Map(comRole: ComRole, entryObj: EntryObj) {
  1683. let map = comRole.entryMap
  1684. if (!this.isGameEntry(entryObj.type) || !entryObj.profession.includes(comRole.roleCfg.profession)) return
  1685. let obj = map.get(entryObj.type)
  1686. if (obj) {
  1687. //叠加规则
  1688. if (entryObj.num > 0) {
  1689. //默认数值相加
  1690. obj.num += entryObj.num
  1691. } else if (entryObj.numArr.length > 0) {
  1692. //数组默认覆盖最好的效果
  1693. let lastNum = obj.numArr[0][obj.numArr[0].length - 1]
  1694. let newLastNum = entryObj.numArr[0][entryObj.numArr[0].length - 1]
  1695. if (newLastNum > lastNum) {
  1696. obj.numArr[0][obj.numArr[0].length - 1] = newLastNum
  1697. }
  1698. }
  1699. } else {
  1700. map.set(entryObj.type, entryObj)
  1701. }
  1702. }
  1703. //--------------------------------改变无敌状态-------------------------------------------------
  1704. changeInvincible(role: EntityIndex, invincible: boolean) {
  1705. let comRole = this.getComponent(role, ComRole)
  1706. if (this.isDie(comRole)) return
  1707. comRole.invincible = invincible
  1708. }
  1709. //--------------------------------绘制碰撞体-------------------------------------------------
  1710. drawDebug(entity: EntityIndex, cObject) {
  1711. let comCocosNode = this.getComponent(entity, ComCocosNode)
  1712. let comTrans = this.getComponent(entity, ComTransform)
  1713. if (!comCocosNode || !comTrans || !cObject || !CC_DEV || !cc.debug.isDisplayStats()) return
  1714. //绘制碰撞体
  1715. let localPoints
  1716. let offset = cc.v2(comTrans.x, comTrans.y).add(cc.v2(cObject.center))
  1717. if (cObject.type == ShapeType.Box) {
  1718. localPoints = []
  1719. localPoints.push(cc.v2(offset.x - cObject.size.x / 2, offset.y + cObject.size.y / 2)) // 左上角
  1720. localPoints.push(cc.v2(offset.x + cObject.size.x / 2, offset.y + cObject.size.y / 2)) // 右上角
  1721. localPoints.push(cc.v2(offset.x + cObject.size.x / 2, offset.y - cObject.size.y / 2)) // 右下角
  1722. localPoints.push(cc.v2(offset.x - cObject.size.x / 2, offset.y - cObject.size.y / 2)) // 左下角
  1723. }
  1724. if (cObject.type == ShapeType.Sphere) {
  1725. localPoints = [cc.v2(comTrans.x, comTrans.y).add(cc.v2(cObject.center))]
  1726. }
  1727. if (localPoints) {
  1728. let color
  1729. let comRole = this.getComponent(entity, ComRole)
  1730. if (comRole) {
  1731. color = comRole.group == Data.game.gFriend ? cc.Color.GREEN : cc.Color.RED
  1732. }
  1733. let comSkill = this.getComponent(entity, ComSkill)
  1734. if (comSkill) {
  1735. color =
  1736. comSkill.group == Data.game.gFriendGainSkill || comSkill.group == Data.game.gFriendHurtSkill
  1737. ? cc.Color.GREEN
  1738. : cc.Color.RED
  1739. }
  1740. comCocosNode.events.push(
  1741. new EventGraphicsDraw(localPoints, cObject.type == ShapeType.Box ? 0 : cObject.radius, color),
  1742. )
  1743. }
  1744. }
  1745. //--------------------------------移除战场上的实体-------------------------------------------------
  1746. removeNodeEntity(entity: EntityIndex) {
  1747. this.putNode(entity)
  1748. this.removeAllComponents(entity)
  1749. this.removeEntity(entity)
  1750. }
  1751. putNode(entity: EntityIndex) {
  1752. let comCocosNode = this.getComponent(entity, ComCocosNode)
  1753. if (comCocosNode) {
  1754. let node = comCocosNode.node
  1755. if (node) {
  1756. let eventProcess = node.getComponent(EventProcess)
  1757. eventProcess.onDetach()
  1758. node.removeFromParent()
  1759. if (this.fightCore) {
  1760. let pool = this.fightCore.gamePool.get(node.name)
  1761. if (pool) {
  1762. this.resetGameNode(node)
  1763. pool.put(node)
  1764. }
  1765. }
  1766. }
  1767. }
  1768. }
  1769. resetGameNode(node) {
  1770. ccUtils.stopAni(node)
  1771. node.stopAllActions()
  1772. node.opacity = 255
  1773. node.angle = 0
  1774. node.scale = 1
  1775. node.position = cc.v2(-10000, -10000)
  1776. let sprite = node.getComponent(cc.Sprite)
  1777. if (sprite) sprite.spriteFrame = null
  1778. let spine = node.getComponent(sp.Skeleton)
  1779. if (spine) spine.skeletonData = null
  1780. let frameAnimation = node.getComponent(FrameAnimation)
  1781. if (frameAnimation) {
  1782. frameAnimation.stop()
  1783. //frameAnimation.spriteAtlas = null
  1784. }
  1785. if (node.name != GAME_PREFAB_TYPE.role) node.children.forEach(v => this.resetGameNode(v))
  1786. }
  1787. }