12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883 |
- /** @format */
- import {ECSWorld} from '../lib/ECSWorld'
- import {IRoleConfig, RoleConfig} from '../../config/RoleConfig'
- import {Data, Mgr} from '../../GameControl'
- import {cCollider} from '../../collision/Collider'
- import {ComRole} from '../components/ComRole'
- import {ComAttackable} from '../components/ComAttackable'
- import {ComType, EntityIndex} from '../lib/Const'
- import {ComCocosNode} from '../components/ComCocosNode'
- import {
- EventGraphicsDraw,
- EventHurtOrAdd,
- EventRoleTip,
- EventRun,
- EventSlowDown,
- EventStand,
- EventType,
- } from '../core/NodeEvent'
- import {ComTransform} from '../components/ComTransform'
- import {ComMovable} from '../components/ComMovable'
- import {ComNodeConfig} from '../components/ComNodeConfig'
- import {IStageRolePosConfig, StageRolePosConfig} from '../../config/StageRolePosConfig'
- import {ComEnemy} from '../components/ComEnemy'
- import {ComFriend} from '../components/ComFriend'
- import {ISkillConfig, SkillConfig} from '../../config/SkillConfig'
- import {ComFindEnemy} from '../components/ComFindEnemy'
- import {BulletConfig} from '../../config/BulletConfig'
- import {ComBullet} from '../components/ComBullet'
- import {ComBehaviorTree} from '../components/ComBehaviorTree'
- import {BT} from '../../behaviorTree/BehaviorTree'
- import {Log} from '../../utils/LogUtils'
- import {
- ANI_TYPE,
- ATTR_NAME,
- BUFF_ANI_TYPE,
- BUFF_EFFECT_TYPE,
- BUFF_TYPE,
- BULLET_EFFECT_TYPE,
- BULLET_FLY_TYPE,
- BULLET_TYPE,
- ENTRY,
- GAME_LAYER,
- GAME_PREFAB_TYPE,
- GAME_ROLE_TIP,
- GAME_SCALE_TYPE,
- GAME_TYPE,
- GAME_WIN_TYPE,
- HIT_ANI_TYPE,
- LANGUAGE_TYPE,
- MONSTER_TYPE,
- NEGATIVE_TYPE,
- ROLE_TYPE,
- SKILL_DIR_TYPE,
- SKILL_EFFECT_TYPE,
- SKILL_TYPE,
- START_POS,
- } from '../../enums/Enum'
- import {BuffConfig} from '../../config/BuffConfig'
- import {ccUtils} from '../../utils/ccUtils'
- import {ComRoleSpine} from '../components/ComRoleSpine'
- import {EntryObj, IAttackEffect, IBuff, IFightData} from '../core/GameInterface'
- import {ComSkill} from '../components/ComSkill'
- import {ComDizzy} from '../components/ComDizzy'
- import {ComSkillAbel} from '../components/ComSkillAbel'
- import {FrameAniConfig} from '../../config/FrameAniConfig'
- import {ComFrameAni} from '../components/ComFrameAni'
- import {EntryConfig} from '../../config/EntryConfig'
- import {TalentConfig} from '../../config/TalentConfig'
- import {IBaseAttr, ICard, IRole} from '../../interface/GlobalInterface'
- import {ComEnter} from '../components/ComEnter'
- import {ArmorConfig} from '../../config/ArmorConfig'
- import {ConstValue} from '../../data/ConstValue'
- import {SysHasSkill} from '../systems/SysHasSkill'
- import {SysFindEnemy} from '../systems/SysFindEnemy'
- import {SysBullet} from '../systems/SysBullet'
- import {SysBehaviorTree} from '../systems/SysBehaviorTree'
- import {SysBuff} from '../systems/SysBuff'
- import {SysSkillAbel} from '../systems/SysSkillAbel'
- import {SysSkill} from '../systems/SysSkill'
- import {SysMovable} from '../systems/SysMovable'
- import {SysAttack} from '../systems/SysAttack'
- import {SysDizzy} from '../systems/SysDizzy'
- import {SysDie} from '../systems/SysDie'
- import {SysLifeTime} from '../systems/SysLifeTime'
- import {SysFrameAni} from '../systems/SysFrameAni'
- import {SysRoleState} from '../systems/SysRoleState'
- import {SysCocosView} from '../systems/SysCocosView'
- import {SysEnter} from '../systems/SysEnter'
- import GameUI from '../../zuma/FightCore'
- import {CastleSkillConfig} from '../../config/CastleSkillConfig'
- import {idNum} from '../../proto/typedef'
- import {SysCastleSkill} from '../systems/SysCastleSkill'
- import {ShapeType} from '../../collision/Shape'
- import {ComHasSkill} from '../components/ComHasSkill'
- import FrameAnimation from '../../uiutils/FrameAnimation'
- import {EventProcess} from '../core/EventProcess'
- import FightCore from '../../zuma/FightCore'
- import {ZumabuffConfig} from '../../config/ZumabuffConfig'
- import {RoleSpineProcess} from '../core/RoleSpineProcess'
- export class FightWorld extends ECSWorld {
- //创建单例
- static instance: FightWorld
- static getInstance() {
- if (!FightWorld.instance) {
- FightWorld.instance = new FightWorld()
- FightWorld.instance.createWorldCocosView()
- }
- return FightWorld.instance
- }
- fightCore: FightCore
- rolePosMap: Map<number, IStageRolePosConfig[]>
- init() {
- this.rolePosMap = new Map<number, IStageRolePosConfig[]>()
- this.rolePosMap.set(Data.game.gFriend, [])
- this.rolePosMap.set(Data.game.gEnemy, [])
- for (let key in StageRolePosConfig) {
- if (+key <= 100) {
- this.rolePosMap.get(Data.game.gEnemy).push(StageRolePosConfig[key])
- } else if (+key > 100 && +key <= 200) {
- this.rolePosMap.get(Data.game.gFriend).push(StageRolePosConfig[key])
- }
- }
- this.initEntry()
- this.fightCore.registerTouchHandler(this.getSystem(SysCocosView))
- }
- createWorldCocosView() {
- //添加系统顺序不能错,保证行为树的判断能正常执行
- this.createEntity() // 创建0号实体
- this.addSystem(new SysHasSkill()) // 是否有技能施放
- this.addSystem(new SysFindEnemy()) // 寻敌锁定
- this.addSystem(new SysBullet()) // 子弹系统(在移动系统之前判断)
- this.addSystem(new SysBehaviorTree()) // 行为树
- this.addSystem(new SysBuff()) // buff光环系统
- this.addSystem(new SysSkillAbel()) // 技能吟唱
- this.addSystem(new SysSkill()) // 技能持续生效
- this.addSystem(new SysMovable()) // 移动
- this.addSystem(new SysAttack()) // 攻击动作
- this.addSystem(new SysDizzy()) // 晕眩
- this.addSystem(new SysDie()) // 死亡
- this.addSystem(new SysLifeTime()) // 生命时间倒计时
- this.addSystem(new SysFrameAni()) // 特效
- this.addSystem(new SysRoleState()) // role state
- this.addSystem(new SysCocosView()) // cocos view
- this.addSystem(new SysEnter()) // 角色入场
- }
- //-------------------------------角色-----------------------------------------
- public createRoleEntity(
- IDOrCfg: number | IRoleConfig,
- isEnemy?: boolean,
- posCfgID?: number,
- iRole?: IRole,
- dropOutGoods?: idNum,
- isExtraEnemy?: boolean,
- ): EntityIndex {
- let roleCfg: IRoleConfig
- if (typeof IDOrCfg == 'number') {
- roleCfg = RoleConfig[IDOrCfg]
- } else {
- roleCfg = IDOrCfg
- }
- if (!roleCfg) {
- console.error('没有这个角色配置----------->', IDOrCfg)
- }
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[GAME_LAYER.role]
- comMap.prefabName = GAME_PREFAB_TYPE.role
- let entitySpine = this.createEntity()
- // 添加spineNode
- let comSpineMap = this.addComponent(entitySpine, ComNodeConfig)
- comSpineMap.id = 1
- comSpineMap.layer = GAME_LAYER[GAME_LAYER.roleSpine]
- comSpineMap.prefabName = GAME_PREFAB_TYPE.roleSpine
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- comTrans.x = isEnemy ? Data.game.fightSizeMaxX : Data.game.fightSizeMinX
- if (posCfgID > 0 && roleCfg.type != ROLE_TYPE.base) {
- comTrans.x = StageRolePosConfig[posCfgID].posX
- }
- let posArr = this.rolePosMap.get(isEnemy ? Data.game.gEnemy : Data.game.gFriend)
- //id为1的是基地
- comTrans.y =
- posCfgID > 0
- ? StageRolePosConfig[posCfgID].posY
- : roleCfg.type == ROLE_TYPE.base
- ? StageRolePosConfig[1].posY
- : posArr[Math.randomRangeInt(0, posArr.length - 1)].posY
- if (isEnemy) {
- this.addComponent(entity, ComEnemy)
- } else {
- this.addComponent(entity, ComFriend)
- }
- // 添加spineNode transform
- let comSpineTrans = this.addComponent(entitySpine, ComTransform)
- comSpineTrans.x = comTrans.x
- comSpineTrans.y = comTrans.y
- let comRoleSpine = this.addComponent(entitySpine, ComRoleSpine)
- comRoleSpine.roleCfg = roleCfg
- comRoleSpine.group = isEnemy ? Data.game.gEnemy : Data.game.gFriend
- let comRole = this.addComponent(entity, ComRole)
- comRole.roleCfg = roleCfg
- comRole.drop = dropOutGoods
- let spineData: sp.spine.SkeletonData = Data.main.roleSpineMap.get(roleCfg.url)?.getRuntimeData()
- comRole.width = spineData ? (spineData.width * roleCfg.gameScale[GAME_SCALE_TYPE.spine]) / 100 : 60
- comRole.height = spineData ? (spineData.height * roleCfg.gameScale[GAME_SCALE_TYPE.spine]) / 100 : 100
- comRole.spineEntity = entitySpine
- comTrans.halfHeight = comRole.height / 2
- let baseAttr: IBaseAttr = iRole ? iRole : roleCfg
- Mgr.global.changeBaseAttr(comRole, baseAttr)
- comRole.attackRange = roleCfg.attackRange
- comRole.attackCD = roleCfg.attackCD == Data.game.cdMax ? Infinity : roleCfg.attackCD
- comRole.killNum = 0
- comRole.attackNum = 0
- comRole.group = isEnemy ? Data.game.gEnemy : Data.game.gFriend
- comRole.skills.length = 0
- comRole.skillCDs.length = 0
- comRole.enterCDs.length = 0
- comRole.skillCountDowns.length = 0
- comRole.babys.length = 0
- comRole.parent = 0
- comRole.parentRoleID = 0
- comRole.HPDirty = true
- comRole.transDirty = false
- comRole.transID = 0
- comRole.buffs.length = 0
- comRole.entryMap.clear()
- comRole.equips = null
- //所有技能
- let allSkill = []
- let allSkillCDs = []
- let allEnterCDs = []
- //人物技能
- roleCfg.skills.forEach((skill, index) => {
- if (skill) {
- allSkill.push(skill)
- allSkillCDs.push(roleCfg.skillCDs[index])
- allEnterCDs.push(roleCfg.enterCDs[index])
- }
- })
- //天赋词条
- for (let id of Data.user.talents) {
- this.putEntry2Map(comRole, this.convertEntry2Obj(TalentConfig[id].entryID))
- }
- //装备词条
- if (iRole) {
- comRole.equips = iRole.equips
- for (let iEquip of iRole.equips) {
- if (iEquip) {
- if (iEquip.cfg.entry && iEquip.cfg.entry < ENTRY.textShow) {
- for (let i = 1; i <= iEquip.cfg.quality; i++) {
- let ID = Math.floor(iEquip.cfg.ID / 100) * 100 + i
- if (ArmorConfig[ID.toString()].entry)
- this.putEntry2Map(comRole, this.convertEntry2Obj(ArmorConfig[ID.toString()].entry))
- }
- }
- //装备技能
- iEquip.cfg.skills?.forEach((skill, index) => {
- if (skill) {
- allSkill.push(skill)
- allSkillCDs.push(iEquip.cfg.skillCDs[index])
- allEnterCDs.push(iEquip.cfg.enterCDs[index])
- }
- })
- }
- }
- }
- //遗迹词条
- if (Data.game.gameType == GAME_TYPE.relic) {
- //基础属性
- if (Data.main.relicAdd[roleCfg.profession]) {
- let keys = Object.keys(ATTR_NAME)
- for (let attrKey of keys) {
- if (Data.main.relicAdd[roleCfg.profession][attrKey]) {
- comRole[attrKey] *= 1 + Data.main.relicAdd[roleCfg.profession][attrKey] / Data.game.rateNum
- }
- }
- }
- for (let entry of Data.game.relicEntryArr) {
- this.putEntry2Map(comRole, this.convertEntry2Obj(entry))
- }
- }
- if (comRole.entryMap.get(ENTRY.startShieldHP)?.num) {
- comRole.shieldHP = comRole.entryMap.get(ENTRY.startShieldHP).num
- }
- allSkill.forEach((skill, index) => {
- if (skill && SkillConfig[skill]) {
- comRole.skills.push(SkillConfig[skill])
- comRole.skillCDs.push(allSkillCDs[index])
- comRole.enterCDs.push(allEnterCDs[index])
- let cd = allSkillCDs[index]
- if (cd == Data.game.cdMax) cd = Infinity
- if (cd > 0 && cd != Infinity && comRole.entryMap.get(ENTRY.skillCD)?.num) {
- cd *= 1 - comRole.entryMap.get(ENTRY.skillCD).num / Data.game.rateNum
- if (cd < 0) cd = 0
- }
- //入场CD
- let enterCD = allEnterCDs[index]
- comRole.skillCountDowns.push(enterCD > 0 && cd != Infinity ? enterCD : cd)
- } else {
- console.error('没有这个技能配置----------->', allSkill[index])
- }
- })
- let attackTime = Infinity
- let castTime = new Array(allSkill.length).fill(0) //spine没有技能动作
- let enterTime = 0
- let dieTime = 0
- if (spineData) {
- if (spineData.findAnimation('skill') && castTime.length > 0) {
- castTime[0] = spineData.findAnimation('skill').duration
- }
- for (let i = 1; i <= roleCfg.skills.length; i++) {
- if (spineData.findAnimation(`skill${i}`)) {
- castTime[i - 1] = spineData.findAnimation(`skill${i}`).duration
- } else {
- castTime[i - 1] = castTime[0]
- }
- }
- if (spineData.findAnimation('enter')) {
- enterTime = spineData.findAnimation('enter').duration
- }
- if (spineData.findAnimation('attack')) {
- attackTime = spineData.findAnimation('attack').duration
- }
- if (spineData.findAnimation('die')) {
- dieTime = spineData.findAnimation('die').duration
- }
- }
- comRole.attackTime = attackTime
- comRole.castTime = castTime
- comRole.enterTime = enterTime
- comRole.dieTime = dieTime
- //血量等词条装备处理完后处理
- comRole.nowHP = comRole.HP
- comRole.lastHP = comRole.HP
- comRole.shieldHP = 0
- comRole.lastShieldHP = 0
- comRole.isExtraEnemy = isExtraEnemy
- //处理gameUI显示
- if (this.fightCore) {
- let entities = this.fightCore.roleEntityMap.get(roleCfg.ID)
- if (!entities) {
- entities = []
- this.fightCore.roleEntityMap.set(roleCfg.ID, entities)
- }
- entities.push(entity)
- if (roleCfg.type == MONSTER_TYPE.boss) {
- if (this.fightCore.stageInfo.type == GAME_WIN_TYPE.boss) {
- }
- this.fightCore.showBossHP(comRole)
- }
- }
- return entity
- }
- setRoleHP(entity, HP) {
- if (!HP) return
- let comRole = this.getComponent(entity, ComRole)
- if (!comRole) return
- comRole.HP = HP
- comRole.lastHP = HP
- comRole.nowHP = HP
- }
- public initRoleBehavior(comBehavior: ComBehaviorTree, roleConfig: IRoleConfig) {
- let findEnemyNode = new BT.FindEnemyNode()
- let meleeMonitorNode = new BT.MeleeMonitorNode()
- let meleeXMonitorNode = new BT.MeleeXMonitorNode()
- let attackMonitorNode = new BT.AttackMonitorNode()
- let attackNode = new BT.AttackNode()
- let meleeWalkToTargetNode = new BT.MeleeWalkToTargetNode(roleConfig.moveSpeed * 1.5)
- let stopNode = new BT.StopNode()
- let hasAttackEnemy = new BT.HasAttackEnemyNode()
- let hasBeAttackNode = new BT.HasBeAttackNode()
- let willAttackNode = new BT.WillAttackNode()
- let willBeAttackNode = new BT.WillBeAttackNode()
- let willAttackNotWillAttackNode = new BT.WillAttackNotWillAttackNode()
- let stopAttackNode = new BT.StopAttackNode()
- let beDizzyNode = new BT.BeDizzyNode()
- let notBeDizzyNode = new BT.InverterNode(new BT.BeDizzyNode())
- let dizzyNode = new BT.DizzyNode()
- let skillNode = new BT.SkillNode()
- let hasSkillNode = new BT.HasSkillNode()
- let walkToCloseXTargetNode = new BT.WalkToCloseTargetNode(roleConfig.moveSpeed, true)
- let walkToCloseTargetNode = new BT.WalkToCloseTargetNode(roleConfig.moveSpeed, false)
- let notFindEnemyNode = new BT.InverterNode(findEnemyNode)
- let notMeleeMonitorNode = new BT.InverterNode(meleeMonitorNode)
- let notMeleeXMonitorNode = new BT.InverterNode(meleeXMonitorNode)
- let notAttackMonitorNode = new BT.InverterNode(attackMonitorNode)
- let notHasAttackEnemy = new BT.InverterNode(hasAttackEnemy)
- let notWillBeAttackNode = new BT.InverterNode(willBeAttackNode)
- let notWillAttackNode = new BT.InverterNode(willAttackNode)
- let notHasBeAttackNode = new BT.InverterNode(hasBeAttackNode)
- let notHasSkillNode = new BT.InverterNode(hasSkillNode)
- let notCastSkillNode = new BT.InverterNode(new BT.CastSkillNode())
- let stopSkillNode = new BT.StopSkillNode()
- let shootRoot = new BT.RootSelectorNode(
- [
- // 晕眩
- new BT.SequenceNode([beDizzyNode, stopNode, stopSkillNode, stopAttackNode, dizzyNode]),
- // 放技能
- new BT.SequenceNode([notBeDizzyNode, hasSkillNode, stopNode, stopAttackNode, skillNode]),
- // 远程攻击范围有敌人,攻击最近的敌人
- new BT.SequenceNode([notBeDizzyNode, attackMonitorNode, stopNode, attackNode]),
- // 远程攻击范围没有敌人,场上有敌军, 往最近敌方X轴方向移动
- new BT.SequenceNode([
- notBeDizzyNode,
- notHasSkillNode,
- findEnemyNode,
- notAttackMonitorNode,
- walkToCloseTargetNode,
- ]),
- // 没有敌人停止移动
- new BT.SequenceNode([notFindEnemyNode, stopNode]),
- ],
- false,
- )
- let meleeRoot = new BT.RootSelectorNode([
- // 晕眩
- new BT.SequenceNode([beDizzyNode, stopNode, stopSkillNode, stopAttackNode, dizzyNode]),
- // 放技能
- new BT.SequenceNode([notBeDizzyNode, hasSkillNode, stopNode, stopAttackNode, skillNode]),
- // X轴Y轴近战探测范围没有敌人,场上有敌军, 往最近敌方X轴方向移动
- new BT.SequenceNode([
- notBeDizzyNode,
- notHasSkillNode,
- findEnemyNode,
- notHasAttackEnemy,
- notWillBeAttackNode,
- notWillAttackNode,
- notMeleeXMonitorNode,
- notMeleeMonitorNode,
- walkToCloseXTargetNode,
- ]),
- // X轴近战探测范围有敌人,往最近敌方X轴方向移动,直到进入攻击范围
- new BT.SequenceNode([
- notBeDizzyNode,
- notHasSkillNode,
- findEnemyNode,
- notHasAttackEnemy,
- notWillBeAttackNode,
- notWillAttackNode,
- meleeXMonitorNode,
- walkToCloseXTargetNode,
- ]),
- // X轴近战攻击范围没有敌人,没有被近战即将攻击, 往最近Y轴的敌方方向移动
- new BT.SequenceNode([
- notBeDizzyNode,
- notHasSkillNode,
- findEnemyNode,
- notHasAttackEnemy,
- notWillBeAttackNode,
- notWillAttackNode,
- notMeleeXMonitorNode,
- meleeMonitorNode,
- walkToCloseTargetNode,
- ]),
- // 自己即将被攻击,停止
- new BT.SequenceNode([notBeDizzyNode, notHasSkillNode, notHasAttackEnemy, willBeAttackNode, stopNode]),
- // 自己即将攻击敌人,跑到攻击点
- new BT.SequenceNode([
- notBeDizzyNode,
- notHasAttackEnemy,
- // notHasBeAttackNode,
- willAttackNode,
- willAttackNotWillAttackNode,
- meleeWalkToTargetNode,
- ]),
- // 到达了攻击地点,继续攻击
- new BT.SequenceNode([notBeDizzyNode, hasAttackEnemy, stopNode, attackNode]),
- // 停止移动
- new BT.SequenceNode([notFindEnemyNode, stopNode]),
- ])
- comBehavior.root = roleConfig.attackRange > Data.game.meleeRange ? shootRoot : meleeRoot
- if (roleConfig.attackRange == 0) comBehavior.root = null
- }
- public changeMoveSpeed(entity: EntityIndex, speed: number) {
- let comMovable = this.getComponent(entity, ComMovable)
- let comCocosNode = this.getComponent(entity, ComCocosNode)
- let comRole = this.getComponent(entity, ComRole)
- let comFriend = this.getComponent(entity, ComFriend)
- if (!comMovable || !comCocosNode) return
- let isChange = comMovable.speed != speed || comFriend
- comMovable.speed = speed
- //同步spine战立和移动
- let comSpineNode = this.getComponent(comRole?.spineEntity, ComCocosNode)
- if (comMovable.speed > 0) {
- isChange && comCocosNode.events.push(new EventRun()) && comSpineNode?.events.push(new EventRun())
- } else {
- comMovable.points.length = 0
- comMovable.pointIdx = 0
- isChange && comCocosNode.events.push(new EventStand()) && comSpineNode?.events.push(new EventStand())
- }
- }
- public changeRoleRun(entity: EntityIndex, isRun: boolean) {
- let comRole = this.getComponent(entity, ComRole)
- if (!comRole) return
- let comSpineNode = this.getComponent(comRole.spineEntity, ComCocosNode)
- comSpineNode?.node.getComponent(RoleSpineProcess).processEvent(isRun ? new EventRun() : new EventStand())
- }
- isDie(idOrCom: EntityIndex | ComRole) {
- let comRole: ComRole
- if (typeof idOrCom == 'number') {
- if (!idOrCom) return true
- comRole = this.getComponent(idOrCom, ComRole)
- } else {
- comRole = idOrCom
- }
- return !comRole || comRole.nowHP + comRole.shieldHP <= 0
- }
- isEnter(id: EntityIndex) {
- let comEnter = this.getComponent(id, ComEnter)
- return comEnter != null
- }
- isBase(idOrCom: EntityIndex | ComRole) {
- return this.isRoleType(idOrCom, ROLE_TYPE.base)
- }
- isBoss(idOrCom: EntityIndex | ComRole) {
- return this.isRoleType(idOrCom, MONSTER_TYPE.boss)
- }
- isRoleType(idOrCom: EntityIndex | ComRole, type: ROLE_TYPE | MONSTER_TYPE) {
- let comRole: ComRole
- if (typeof idOrCom == 'number') {
- if (!idOrCom) return false
- comRole = this.getComponent(idOrCom, ComRole)
- } else {
- comRole = idOrCom
- }
- return !comRole || comRole.roleCfg.type === type
- }
- //-------------------------战斗扣血加血-----------------------------------------------
- //扣血
- changeHpByHurt(role: EntityIndex, hurtHP: number, isCrit: boolean, HitAniID: number) {
- if (!hurtHP) return
- let changeHPRole = this.getComponent(role, ComRole)
- if (changeHPRole.invincible) return
- let changeHPComCocosNode = this.getComponent(role, ComCocosNode)
- changeHPRole.lastHP = changeHPRole.nowHP
- changeHPRole.lastShieldHP = changeHPRole.shieldHP
- changeHPComCocosNode.events.push(
- new EventRoleTip(
- isCrit ? GAME_ROLE_TIP.critTip : GAME_ROLE_TIP.damageTip,
- -hurtHP,
- `-${Math.toKMBNum(hurtHP)}`,
- ),
- )
- let comSpineNode = this.getComponent(changeHPRole.spineEntity, ComCocosNode)
- comSpineNode?.events.push(new EventHurtOrAdd(-hurtHP, isCrit))
- if (changeHPRole.shieldHP > 0) {
- changeHPRole.shieldHP -= hurtHP
- if (changeHPRole.shieldHP < 0) {
- changeHPRole.nowHP += changeHPRole.shieldHP
- changeHPRole.shieldHP = 0
- }
- } else {
- changeHPRole.nowHP -= hurtHP
- }
- changeHPRole.HPDirty = true
- if (!this.isBase(changeHPRole) && changeHPRole.roleCfg.type != ROLE_TYPE.totem && HitAniID > 0) {
- this.createAni(HitAniID, role)
- }
- }
- getDefenseRate(defenseObj: IFightData, attackObj?: IFightData) {
- let ignoreDefenseE = attackObj?.entryMap.get(ENTRY.ignoreDefense)?.num || 0
- return (
- 1 -
- (defenseObj.defense * (1 - ignoreDefenseE / Data.game.rateNum)) /
- (defenseObj.defense + Data.game.defenseConst)
- )
- }
- getSpellDefenseRate(fightData: IFightData, attackObj?: IFightData) {
- let ignoreDefenseE = attackObj?.entryMap.get(ENTRY.ignoreDefense)?.num || 0
- return (
- 1 -
- (fightData.spellDefense * (1 - ignoreDefenseE / Data.game.rateNum)) /
- (fightData.spellDefense + Data.game.defenseConst)
- )
- }
- //攻击扣血值
- getHurtByAttackRole(attackObj: IFightData, role: EntityIndex, attackEffect: IAttackEffect): number {
- let hurtHP = 0
- let changeHPRole = this.getComponent(role, ComRole)
- let changeHPComCocosNode = this.getComponent(role, ComCocosNode)
- if (this.isDie(changeHPRole) || !changeHPComCocosNode || !changeHPComCocosNode.loaded) return hurtHP
- let critAddAttack = 0
- let rateNum = Data.game.rateNum
- let attack = attackObj.attack
- let spellAttack = attackObj.spellAttack
- let realAttack = attackObj.realAttack
- // 所有的比例加伤
- let hurtAddRate = 0
- let realHurtAdd: number = 0
- attackObj.buffs.forEach(buff => {
- let buffConfig = buff.buffCfg
- if (buffConfig.buffType == BUFF_TYPE.backAddHurt && attackEffect.isBack) {
- //后背加伤(万分比)
- hurtAddRate += buffConfig.attrRate[0]
- } else if (buffConfig.buffType == BUFF_TYPE.realByHp) {
- //血量比例加真实攻击(万分比)
- realHurtAdd += attackObj.nowHP * (buffConfig.attrRate[0] / rateNum)
- } else if (
- buffConfig.buffType == BUFF_TYPE.attackNumAddHurt &&
- attackObj.attackNum % buffConfig.attrNum[0] == 0
- ) {
- //N弹加伤(万分比)
- hurtAddRate += buffConfig.attrRate[0]
- }
- })
- //普攻对boss加伤
- if (attackObj.entryMap.get(ENTRY.boosHurt)?.num && changeHPRole.roleCfg.type == MONSTER_TYPE.boss) {
- hurtAddRate += attackObj.entryMap.get(ENTRY.boosHurt).num
- }
- changeHPRole.buffs.forEach(buff => {
- let buffConfig = buff.buffCfg
- if (buffConfig.buffType == BUFF_TYPE.shieldReduceHurt) {
- //顶盾减伤(万分比)
- hurtAddRate += buffConfig.attrRate[0]
- } else if (buffConfig.buffType == BUFF_TYPE.hurtRateChange) {
- //伤害减免(万分比)
- hurtAddRate += buffConfig.attrRate[0]
- }
- })
- //暴击
- if (attackEffect.isCrit) {
- attack *= attackObj.critNum / rateNum
- spellAttack *= attackObj.critNum / rateNum
- realAttack *= attackObj.critNum / rateNum
- }
- //溅射
- if (attackEffect.sputter) {
- attack *= attackEffect.sputter / rateNum
- spellAttack *= attackEffect.sputter / rateNum
- realAttack *= attackEffect.sputter / rateNum
- }
- if (attack || spellAttack || realAttack) {
- //物理伤害 物理攻击*(1-物理防御/(物理防御+防御常数))
- let hurt = attack * this.getDefenseRate(changeHPRole, attackObj)
- //魔法伤害 魔法攻击*(1-魔法防御/(魔法防御+防御常数))
- let spellHurt = spellAttack * this.getSpellDefenseRate(changeHPRole, attackObj)
- //真实伤害 真实攻击
- let realHurt = realAttack
- realHurt += realHurtAdd
- let endHurtRate = 1 + hurtAddRate / rateNum
- if (endHurtRate < 0) endHurtRate = 0
- hurtHP = (hurt + spellHurt + realHurt) * (1 + Data.game.curHurtRate / rateNum) * endHurtRate
- }
- //普攻减伤
- if (changeHPRole.entryMap.get(ENTRY.hurtReduce)?.num > 0) {
- hurtHP -= changeHPRole.entryMap.get(ENTRY.hurtReduce).num
- }
- if (hurtHP < 0) hurtHP = 0
- return hurtHP
- }
- //技能加减血
- changeHpBySkill(skill: ComSkill, role: EntityIndex) {
- let changeHPRole = this.getComponent(role, ComRole)
- let changeHPComCocosNode = this.getComponent(role, ComCocosNode)
- if (
- this.isDie(changeHPRole) ||
- (this.isBase(changeHPRole) && !skill.skillCfg.effectType.includes(SKILL_EFFECT_TYPE.hurtBase)) ||
- changeHPRole.invincible ||
- !changeHPComCocosNode ||
- !changeHPComCocosNode.loaded
- )
- return
- let fightData = skill.fightData
- if (
- (skill.skillCfg.type == SKILL_TYPE.normal || skill.skillCfg.type == SKILL_TYPE.attackBack) &&
- skill.skillCfg.hurtRate
- ) {
- let rateNum = Data.game.rateNum
- let hurtHP = 0
- let attack = fightData.attack
- let spellAttack = fightData.spellAttack
- let realAttack = fightData.realAttack
- let hurtAddRate = skill.skillCfg.hurtRate
- //技能加伤
- if (fightData.entryMap.get(ENTRY.skillHurtRate)?.num) {
- hurtAddRate += fightData.entryMap.get(ENTRY.skillHurtRate).num
- }
- //技能对boss加伤
- if (fightData.entryMap.get(ENTRY.boosHurt)?.num && changeHPRole.roleCfg.type == MONSTER_TYPE.boss) {
- hurtAddRate += fightData.entryMap.get(ENTRY.boosHurt).num
- }
- //自身buff加伤
- for (let j = 0; j < fightData.buffs.length; j++) {
- let buffCfg = fightData.buffs[j].buffCfg
- if (buffCfg.buffType == BUFF_TYPE.skillHurt && buffCfg.attrRate[skill.skillIndex]) {
- hurtAddRate += buffCfg.attrRate[skill.skillIndex]
- }
- }
- //受击者buff减伤
- changeHPRole.buffs.forEach(buff => {
- let buffConfig = buff.buffCfg
- if (buffConfig.buffType == BUFF_TYPE.hurtRateChange) {
- //伤害减免(万分比)
- hurtAddRate += buffConfig.attrRate[0]
- }
- })
- if (attack || spellAttack || realAttack) {
- //物理伤害 物理攻击*(1-物理防御/(物理防御+防御常数))
- let hurt = attack * this.getDefenseRate(changeHPRole)
- //魔法伤害 魔法攻击*(1-魔法防御/(魔法防御+防御常数))
- let spellHurt = spellAttack * this.getSpellDefenseRate(changeHPRole)
- //真实伤害 真实攻击
- let realHurt = realAttack
- hurtHP = (hurt + spellHurt + realHurt) * (1 + Data.game.curHurtRate / rateNum) * (hurtAddRate / rateNum)
- }
- //技能减伤
- if (changeHPRole.entryMap.get(ENTRY.hurtReduce)?.num > 0) {
- hurtHP -= changeHPRole.entryMap.get(ENTRY.hurtReduce).num
- }
- if (hurtHP < 0) hurtHP = 0
- //受击特效统一处理,这里是0
- this.changeHpByHurt(role, hurtHP, false, 0)
- }
- let addNum = 0
- if (skill.skillCfg.type == SKILL_TYPE.addHP) {
- addNum = (skill.skillCfg.hurtRate / Data.game.rateNum) * fightData.spellAttack
- let moreAddNum = 0
- if (addNum + changeHPRole.nowHP > changeHPRole.HP) {
- moreAddNum = addNum + changeHPRole.nowHP - changeHPRole.HP
- addNum = changeHPRole.HP - changeHPRole.nowHP
- }
- for (let i = 0; i < skill.skillCfg.effectType.length; i++) {
- if (skill.skillCfg.effectType[i] == SKILL_EFFECT_TYPE.addExtraHP) {
- if (changeHPRole.nowHP / changeHPRole.HP < skill.skillCfg.effectParm[i][0] / Data.game.rateNum) {
- addNum += skill.skillCfg.effectParm[i][1]
- }
- } else if (skill.skillCfg.effectType[i] == SKILL_EFFECT_TYPE.addRateHP) {
- addNum += (skill.skillCfg.effectParm[i][0] / Data.game.rateNum) * changeHPRole.HP
- }
- }
- //增加治疗量
- if (fightData.entryMap.get(ENTRY.addHealing)?.num) {
- addNum *= 1 + fightData.entryMap.get(ENTRY.addHealing).num / Data.game.rateNum
- }
- //受治疗增加量
- if (changeHPRole.entryMap.get(ENTRY.healingMore)?.num) {
- addNum *= 1 + changeHPRole.entryMap.get(ENTRY.healingMore).num / Data.game.rateNum
- }
- //多的治疗量转为白血盾
- if (changeHPRole.entryMap.get(ENTRY.healing2Shield)?.num && moreAddNum) {
- changeHPRole.shieldHP +=
- (changeHPRole.entryMap.get(ENTRY.healing2Shield).num / Data.game.rateNum) * moreAddNum
- }
- this.addHP(addNum, role)
- }
- if (
- skill.skillCfg.type == SKILL_TYPE.addShieldHPByHP ||
- skill.skillCfg.type == SKILL_TYPE.addShieldHPBySpAttack
- ) {
- addNum =
- (skill.skillCfg.hurtRate / Data.game.rateNum) *
- (skill.skillCfg.type == SKILL_TYPE.addShieldHPByHP ? fightData.HP : fightData.spellAttack)
- if (changeHPRole.shieldHP < addNum) changeHPRole.shieldHP = addNum
- if (skill.skillCfg.type == SKILL_TYPE.addShieldHPBySpAttack) {
- for (let i = 0; i < skill.skillCfg.effectType.length; i++) {
- if (skill.skillCfg.effectType[i] == SKILL_EFFECT_TYPE.addRateShieldHP) {
- addNum += (skill.skillCfg.effectParm[i][0] / Data.game.rateNum) * changeHPRole.HP
- }
- }
- }
- }
- changeHPRole.HPDirty = true
- }
- changeHpByRebound(role: EntityIndex, enemy: EntityIndex) {
- let comRoleEnemy: ComRole = this.getComponent(enemy, ComRole)
- let comRole: ComRole = this.getComponent(enemy, ComRole)
- if (this.isDie(comRoleEnemy)) return
- comRoleEnemy.buffs.forEach(buff => {
- let buffType = buff.buffCfg.buffType
- if (buffType == BUFF_TYPE.reboundAttack || buffType == BUFF_TYPE.reboundReal) {
- //真实伤害
- let defenseRate = 1
- if (buffType == BUFF_TYPE.reboundAttack) {
- //物理伤害
- defenseRate = this.getDefenseRate(comRole, comRoleEnemy)
- }
- let hurt = (comRoleEnemy.attack * defenseRate * buff.buffCfg.attrRate[0]) / Data.game.rateNum
- this.changeHpByHurt(role, hurt, false, 0)
- }
- })
- if (comRoleEnemy.entryMap.get(ENTRY.hurtRebound)?.num) {
- let defenseRate = this.getDefenseRate(comRole, comRoleEnemy)
- let hurt =
- (comRoleEnemy.attack * defenseRate * comRoleEnemy.entryMap.get(ENTRY.hurtRebound)?.num) /
- Data.game.rateNum
- this.changeHpByHurt(role, hurt, false, 0)
- }
- }
- moveToMeleeAttackPos(
- selfEntity: EntityIndex,
- comTrans: ComTransform,
- targetComTrans: ComTransform,
- targetComMovable: ComMovable,
- isBack?: boolean,
- ) {
- let targetPos = cc.v2(targetComTrans.x, targetComTrans.y)
- // 近战前往目标敌人没被锁定的某一个近战范围攻击点
- let isLeft = comTrans.x - targetComTrans.x < 0
- if (isBack) isLeft = !isLeft
- if (targetComTrans.x >= Data.game.fightSizeMaxX) {
- isLeft = true
- }
- if (targetComTrans.x <= Data.game.fightSizeMinX) {
- isLeft = false
- }
- let isDown = comTrans.y - targetComTrans.y < 0
- let attackArrayPos = isLeft ? Data.game.attackLeftRadiusPoints : Data.game.attackRightRadiusPoints
- let curAttackArrayPos = isLeft
- ? targetComMovable.leftMeleeEnemiesPosDirty
- : targetComMovable.rightMeleeEnemiesPosDirty
- let posIndex = curAttackArrayPos.indexOf(-1)
- let secondPosIndex = curAttackArrayPos.indexOf(-1, posIndex + 1)
- let targetIndex
- //因为leftMeleeEnemiesPosDirty数组是上下位置交替插入的,所以找出离自己近的点
- if (posIndex >= 0 && secondPosIndex > 0) {
- if (isDown) {
- targetIndex = attackArrayPos[posIndex].y < 0 ? posIndex : secondPosIndex
- } else {
- targetIndex = attackArrayPos[posIndex].y >= 0 ? posIndex : secondPosIndex
- }
- } else if (posIndex >= 0 && secondPosIndex <= 0) {
- targetIndex = posIndex
- } else {
- targetIndex = Math.randomRangeInt(0, attackArrayPos.length - 1)
- }
- curAttackArrayPos[targetIndex] = selfEntity
- targetPos.addSelf(attackArrayPos[targetIndex])
- if (targetPos.y <= Data.game.fightSizeMinY) targetPos.y = Data.game.fightSizeMinY
- if (targetPos.y >= Data.game.fightSizeMaxY) targetPos.y = Data.game.fightSizeMaxY
- return targetPos
- }
- //加血吸血
- addHP(addHPNum: number, role: EntityIndex) {
- let comRole = this.getComponent(role, ComRole)
- let comCocosNode = this.getComponent(role, ComCocosNode)
- if (!this.isDie(role)) {
- if (addHPNum >= 1) {
- comCocosNode.events.push(new EventRoleTip(GAME_ROLE_TIP.hpTip, addHPNum, `+${Math.toKMBNum(addHPNum)}`))
- }
- let target = comRole.nowHP + addHPNum
- if (target > comRole.HP) {
- addHPNum = comRole.HP - comRole.nowHP
- }
- comRole.nowHP += addHPNum
- }
- }
- //-------------------------------子弹-----------------------------------------
- public createBulletEntity(role: EntityIndex, isCrit: boolean): EntityIndex[] {
- let comRole = this.getComponent(role, ComRole)
- let comTransform = this.getComponent(role, ComTransform)
- let comFindEnemy = this.getComponent(role, ComFindEnemy)
- let comAttackable = this.getComponent(role, ComAttackable)
- let entities = []
- if (this.isDie(comRole)) {
- //Log.warn('创建子弹失败')
- return entities
- }
- let bulletID = comRole.roleCfg.bullet
- if (!bulletID) {
- return entities
- }
- let bulletCfg = BulletConfig[bulletID]
- let enemies = [comAttackable.curAttack]
- let endPosArr: cc.Vec2[] = []
- //跟踪敌人改成固定角度
- if (bulletCfg.splitNum > 1) {
- // let otherEnemies = comFindEnemy.attackCObject.containsBody.keysArr()
- // otherEnemies = otherEnemies.filter(
- // v =>
- // Math.sign(comTransform.dir.x) != Math.sign(this.getComponent(v, ComTransform)?.dir.x) &&
- // v != comAttackable.curAttack,
- // )
- //
- // otherEnemies.sort((a, b) => {
- // let at = this.getComponent(a, ComTransform)
- // let bt = this.getComponent(b, ComTransform)
- // return at.x ** 2 + at.y ** 2 - (bt.x ** 2 + bt.y ** 2)
- // })
- // enemies = enemies.concat(otherEnemies)
- let enemyComTransform = this.getComponent(enemies[0], ComTransform)
- let startPos = cc.v2(comTransform.x, comTransform.y + comTransform.halfHeight)
- let hitPos = cc.v2(enemyComTransform.x, enemyComTransform.y + enemyComTransform.halfHeight)
- for (let i = 1; i < bulletCfg.splitNum; i++) {
- endPosArr.push(this.rotatePoint(startPos, hitPos, 10 * i * (i % 2 == 0 ? -1 : 1)))
- }
- }
- for (let i = 0; i < bulletCfg.splitNum; i++) {
- //if (i < enemies.length) {
- let enemyComTransform = this.getComponent(enemies[i], ComTransform)
- if (!enemyComTransform) {
- enemyComTransform = new ComTransform()
- enemyComTransform.x = endPosArr[i - 1].x
- enemyComTransform.y = endPosArr[i - 1].y
- }
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
- comMap.prefabName = GAME_PREFAB_TYPE.bullet
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- let bulletPosScaleX = comTransform.dir.x >= 0 ? 1 : -1
- let spineScale = comRole.roleCfg.gameScale[GAME_SCALE_TYPE.spine] / 100
- comTrans.x = comTransform.x + comRole.roleCfg.bulletPos[0] * bulletPosScaleX * spineScale
- comTrans.y = comTransform.y + comRole.roleCfg.bulletPos[1] * spineScale
- let comMovable = this.addComponent(entity, ComMovable)
- comMovable.speed = 0
- let comBullet = this.addComponent(entity, ComBullet)
- comBullet.group = comRole.group == Data.game.gFriend ? Data.game.gFriendBullet : Data.game.gEnemyBullet
- comBullet.fightData = {...comRole, roleEntity: role}
- comBullet.fightData.buffs = ccUtils.deepCopy(comRole.buffs)
- comBullet.bulletCfg = bulletCfg
- comBullet.ejectionEnemies.length = 0
- comBullet.ejectionEnemy = enemies[i] ? enemies[i] : 0
- comBullet.hitEnemies.length = 0
- comBullet.isCrit = isCrit
- this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
- entities.push(entity)
- // }
- }
- return entities
- }
- public createRoleSkillBulletEntity(
- skillConfig: ISkillConfig,
- bulletID: number,
- createEntity: EntityIndex,
- enemy: EntityIndex,
- randomPos: boolean = false,
- pos?: cc.Vec2,
- ): EntityIndex[] {
- let bulletCfg = BulletConfig[bulletID]
- let roleComTransform = this.getComponent(createEntity, ComTransform)
- let enemyComTransform = this.getComponent(enemy, ComTransform)
- if (pos) {
- enemyComTransform = new ComTransform()
- enemyComTransform.x = pos.x
- enemyComTransform.y = pos.y
- }
- if (!enemyComTransform || !bulletCfg) {
- return
- }
- let endPosArr: cc.Vec2[] = []
- //跟踪敌人改成固定角度
- if (bulletCfg.splitNum > 1) {
- let startPos = cc.v2(roleComTransform.x, roleComTransform.y + roleComTransform.halfHeight)
- let hitPos = cc.v2(enemyComTransform.x, enemyComTransform.y + enemyComTransform.halfHeight)
- for (let i = 1; i < bulletCfg.splitNum; i++) {
- endPosArr.push(this.rotatePoint(startPos, hitPos, 10 * i * (i % 2 == 0 ? -1 : 1)))
- }
- }
- let entityArr = []
- for (let i = 0; i < bulletCfg.splitNum; i++) {
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
- comMap.prefabName = GAME_PREFAB_TYPE.bullet
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- let comRole = this.getComponent(createEntity, ComRole)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- let bulletPosScaleX = roleComTransform.dir.x >= 0 ? 1 : -1
- let spineScale = comRole.roleCfg.gameScale[GAME_SCALE_TYPE.spine] / 100
- comTrans.x = roleComTransform.x + comRole.roleCfg.bulletPos[0] * bulletPosScaleX * spineScale
- comTrans.y =
- roleComTransform.y +
- (comRole.roleCfg.bulletPos[1] ? comRole.roleCfg.bulletPos[1] * spineScale : roleComTransform.halfHeight)
- let comMovable = this.addComponent(entity, ComMovable)
- comMovable.speed = 0
- let comBullet = this.addComponent(entity, ComBullet)
- comBullet.group = comRole.group == Data.game.gFriend ? Data.game.gFriendBullet : Data.game.gEnemyBullet
- comBullet.fightData = {...comRole, roleEntity: createEntity}
- comBullet.bulletCfg = bulletCfg
- comBullet.ejectionEnemies.length = 0
- comBullet.ejectionEnemy = enemy
- comBullet.hitEnemies.length = 0
- comBullet.isCrit = false
- //特效子弹位置随机
- if (randomPos) {
- let randomWidth = SkillConfig[bulletCfg.skill]
- ? SkillConfig[bulletCfg.skill].attackRangeX
- : skillConfig.attackRangeX
- let randomHeight = SkillConfig[bulletCfg.skill]
- ? SkillConfig[bulletCfg.skill].attackRangeY
- : skillConfig.attackRangeY
- let randomX = enemyComTransform.x + Math.randomRangeFloat(-randomWidth / 2, randomWidth / 2)
- let randomY = enemyComTransform.y + Math.randomRangeFloat(-randomHeight / 2, randomHeight / 2)
- enemyComTransform = new ComTransform()
- enemyComTransform.x = randomX
- enemyComTransform.y = randomY
- }
- if (bulletCfg.born == START_POS.straightFall || bulletCfg.born == START_POS.obliqueFall) {
- comTrans.x = enemyComTransform.x - (bulletCfg.born == START_POS.obliqueFall ? 200 : 0)
- comTrans.y = ConstValue.CANVAS_HEIGHT / 2
- }
- if (i > 0) {
- enemyComTransform = new ComTransform()
- enemyComTransform.x = endPosArr[i - 1].x
- enemyComTransform.y = endPosArr[i - 1].y
- }
- this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
- entityArr.push(entity)
- }
- return entityArr
- }
- public createCardBulletEntity(
- iCard: ICard,
- startPos: cc.Vec2,
- endPos: cc.Vec2,
- enemy: EntityIndex = 0,
- ): EntityIndex {
- let cardSkillCfg = iCard.cfg
- let bulletCfg = BulletConfig[cardSkillCfg.bullet]
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
- comMap.prefabName = GAME_PREFAB_TYPE.bullet
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- comTrans.x = startPos.x
- comTrans.y = startPos.y
- let comMovable = this.addComponent(entity, ComMovable)
- comMovable.speed = 0
- let comBullet = this.addComponent(entity, ComBullet)
- comBullet.group = Data.game.gFriendBullet
- comBullet.fightData = {buffs: [], entryMap: new Map<ENTRY, EntryObj>(), ...iCard}
- comBullet.bulletCfg = bulletCfg
- comBullet.ejectionEnemies.length = 0
- comBullet.ejectionEnemy = enemy
- comBullet.hitEnemies.length = 0
- comBullet.isCrit = false
- let enemyComTransform = new ComTransform()
- enemyComTransform.x = endPos.x
- enemyComTransform.y = endPos.y
- this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
- return entity
- }
- public createBaseBulletEntity(posOrTrans: ComTransform | cc.Vec2) {
- let sysCastleSkill = this.getSystem(SysCastleSkill)
- if (sysCastleSkill.rechargeTime > 0) {
- Mgr.ui.tip(LANGUAGE_TYPE.inRecharge)
- return
- }
- if (!Data.user.useCastleSkillID) return
- sysCastleSkill.reduceLeftNum()
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[GAME_LAYER.bullet]
- comMap.prefabName = GAME_PREFAB_TYPE.bullet
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- comTrans.x = -10000
- comTrans.y = 10000
- let comMovable = this.addComponent(entity, ComMovable)
- comMovable.speed = 0
- let comBullet = this.addComponent(entity, ComBullet)
- comBullet.group = Data.game.gFriendBullet
- let baseBulletCfg = CastleSkillConfig[Data.user.useCastleSkillID]
- comBullet.fightData = {buffs: [], entryMap: new Map<ENTRY, EntryObj>(), ...baseBulletCfg}
- comBullet.bulletCfg = BulletConfig[baseBulletCfg.bullet]
- comBullet.ejectionEnemies.length = 0
- comBullet.ejectionEnemy = 0
- comBullet.hitEnemies.length = 0
- comBullet.ejectionAnis.length = 0
- comBullet.isCrit = false
- let enemyComTransform
- if (posOrTrans instanceof ComTransform) {
- enemyComTransform = posOrTrans
- } else {
- let startPos = cc.v2(comTrans.x, comTrans.y)
- let direction = posOrTrans.sub(startPos).normalize()
- let endPos = startPos.add(direction.mul(baseBulletCfg.attackRange))
- enemyComTransform = new ComTransform()
- enemyComTransform.x = endPos.x
- enemyComTransform.y = endPos.y
- }
- this.initBulletDir(comTrans, enemyComTransform, comMovable, comBullet)
- return entity
- }
- public initBulletDir(
- comTrans: ComTransform,
- enemyComTransform: ComTransform,
- comMovable: ComMovable,
- comBullet: ComBullet,
- comCocosNode?: ComCocosNode,
- ) {
- let startPos = cc.v2(comTrans.x, comTrans.y)
- let hitPos = cc.v2(enemyComTransform.x, enemyComTransform.y + enemyComTransform.halfHeight)
- // 计算子弹的飞行方向向量
- let direction = hitPos.sub(startPos).normalize()
- let bulletCfg = comBullet.bulletCfg
- if (
- !bulletCfg.isEjection &&
- bulletCfg.type == BULLET_TYPE.normal &&
- !bulletCfg.effectType.includes(BULLET_EFFECT_TYPE.attackRange) &&
- !bulletCfg.effectType.includes(BULLET_EFFECT_TYPE.boomerangRange)
- ) {
- //如果是直线子弹,将子弹终点设置为边界外的某个点,子弹到达边界点,移除子弹
- hitPos = this.findIntersection(startPos, direction)
- //当子弹从区域外进入,直接让子弹结束
- if (!hitPos) hitPos = startPos
- }
- let hitPosArr = [hitPos]
- if (bulletCfg.flyType == BULLET_FLY_TYPE.parabolic) {
- hitPosArr = this.getParabolaPoints(startPos, hitPos, 50)
- if (hitPosArr.length >= 2) direction = hitPosArr[1].sub(hitPosArr[0]).normalize()
- } else if (bulletCfg.flyType == BULLET_FLY_TYPE.bezier) {
- hitPosArr.length = 0
- hitPosArr.push(...this.getEquidistantPoints(startPos, hitPos, 10, comBullet.group))
- hitPosArr.push(hitPos)
- } else if (bulletCfg.flyType == BULLET_FLY_TYPE.boomerang) {
- hitPosArr.length = 0
- let parms = bulletCfg.effectParm[bulletCfg.effectType.indexOf(BULLET_EFFECT_TYPE.boomerangRange)]
- let halfPoints = this.getEquidistantPoints(startPos, hitPos, 10, comBullet.group, parms[1])
- let leftPoints = this.getEquidistantPoints(hitPos, startPos, 10, comBullet.group, parms[1])
- hitPosArr.push(...halfPoints)
- hitPosArr.push(hitPos)
- hitPosArr.push(...leftPoints)
- hitPosArr.push(startPos)
- } else if (bulletCfg.flyType == BULLET_FLY_TYPE.horizon) {
- hitPosArr.length = 0
- hitPosArr.push(cc.v2(comTrans.x + (direction.x >= 0 ? 1000 : -1000), comTrans.y))
- }
- comTrans.dir.x = direction.x
- comTrans.dir.y = direction.y
- comMovable.pointIdx = 0
- comMovable.points.length = 0
- comMovable.points.push(...hitPosArr)
- if (comCocosNode) {
- //计算发射角度
- let angle = Math.atan2(comTrans.dir.y, comTrans.dir.x)
- comCocosNode.node.angle = cc.misc.radiansToDegrees(angle)
- }
- }
- getParabolaPoints(a: cc.Vec2, b: cc.Vec2, interval: number): cc.Vec2[] {
- let xA = a.x,
- yA = a.y
- let xB = b.x,
- yB = b.y
- let yMax = Data.game.fightSizeMaxY - Math.randomRangeInt(0, Data.game.fightSizeMaxY - Math.max(yA, yB)) // 最高点的高度
- let xC = (xA + xB) / 2 // 假设C是A和B的中点(水平方向)
- let xD = xA + (xC - xA) / 2 // 控制点D的x坐标是A和C的x坐标的平均值
- let yD = yA + (yMax - yA) / 2 // 控制点D的y坐标是A和最高点之间的某个值(这里取中点)
- let points = []
- let step = 1 / (interval - 1)
- for (let t = 0; t <= 1; t += step) {
- let x =
- Math.pow(1 - t, 3) * xA +
- 3 * Math.pow(1 - t, 2) * t * xD +
- 3 * (1 - t) * Math.pow(t, 2) * xC +
- Math.pow(t, 3) * xB
- let y =
- Math.pow(1 - t, 3) * yA +
- 3 * Math.pow(1 - t, 2) * t * yD +
- 3 * (1 - t) * Math.pow(t, 2) * yMax +
- Math.pow(t, 3) * yB
- points.push(cc.v2(x, y))
- }
- return points
- }
- boundaries = [
- {dir: 'right', eq: Data.game.fightAreaMaxX, var: 'x'}, // 右边界
- {dir: 'left', eq: Data.game.fightAreaMinX, var: 'x'}, // 左边界
- {dir: 'top', eq: Data.game.fightAreaMaxY, var: 'y'}, // 上边界
- {dir: 'bottom', eq: Data.game.fightAreaMinY, var: 'y'}, // 下边界
- ]
- findIntersection(a, v) {
- // 将矩形边界转换为线性方程组
- // 例如,对于矩形的上边界(y-centerY = height/2),转换为 y = centerY + height/2
- // 并以此类推其他三个边界
- // 定义四个边界线性方程
- let intersection = null
- //起点Y位置加上了人物身高,这里做个限制,让子弹起始点在屏幕内
- this.boundaries.forEach(boundary => {
- let t
- if (boundary.var === 'x') {
- // 解 x = a.x + t*v.x
- t = (boundary.eq - a.x) / v.x
- } else {
- // 解 y = a.y + t*v.y
- t = (boundary.eq - a.y) / v.y
- }
- // 检查t是否在[0, +∞)范围内,确保交点在射线方向上且不过原点
- if (t >= 0) {
- let intersectPoint = cc.v2(a.x + t * v.x, a.y + t * v.y)
- // 判断交点是否在矩形内或边上
- if (
- (boundary.dir === 'right' || boundary.dir === 'left') &&
- intersectPoint.y >= Data.game.fightAreaMinY &&
- intersectPoint.y <= Data.game.fightAreaMaxY
- ) {
- if (!intersection || intersection.sub(a).mag() < intersectPoint.sub(a).mag())
- intersection = intersectPoint
- } else if (
- (boundary.dir === 'top' || boundary.dir === 'bottom') &&
- intersectPoint.x >= Data.game.fightAreaMinX &&
- intersectPoint.x <= Data.game.fightAreaMaxX
- ) {
- if (!intersection || intersection.sub(a).mag() < intersectPoint.sub(a).mag())
- intersection = intersectPoint
- }
- }
- })
- return intersection
- }
- public removeBulletEntity(entity: EntityIndex) {
- let comCocosNode = this.getComponent(entity, ComCocosNode)
- let comBullet = this.getComponent(entity, ComBullet)
- if (!comBullet) {
- return
- //console.log('子弹已经移除')
- }
- //1秒后移除弹射特效
- comBullet.ejectionAnis.forEach(aniEntity => {
- let aniEntityCom = this.getComponent(aniEntity, ComFrameAni)
- if (aniEntityCom && aniEntityCom.countDown > 1) aniEntityCom.countDown = 1
- })
- if (comBullet.cObject) {
- cCollider.inst.remove(comBullet.cObject.body)
- comCocosNode.node.removeComponent(comBullet.cObject)
- comBullet.cObject = null
- }
- this.removeNodeEntity(entity)
- }
- rotatePoint(a: cc.Vec2, b: cc.Vec2, angleDegrees: number): cc.Vec2 {
- // 将角度转换为弧度
- const angleRadians = (angleDegrees * Math.PI) / 180
- // 计算cos和sin值
- const cosAngle = Math.cos(angleRadians)
- const sinAngle = Math.sin(angleRadians)
- // 计算新的坐标
- const x_new = (b.x - a.x) * cosAngle - (b.y - a.y) * sinAngle + a.x
- const y_new = (b.x - a.x) * sinAngle + (b.y - a.y) * cosAngle + a.y
- return cc.v2(x_new, y_new)
- }
- bezierPoint(t, a, c, d, b) {
- let x =
- Math.pow(1 - t, 3) * a.x +
- 3 * Math.pow(1 - t, 2) * t * c.x +
- 3 * (1 - t) * Math.pow(t, 2) * d.x +
- Math.pow(t, 3) * b.x
- let y =
- Math.pow(1 - t, 3) * a.y +
- 3 * Math.pow(1 - t, 2) * t * c.y +
- 3 * (1 - t) * Math.pow(t, 2) * d.y +
- Math.pow(t, 3) * b.y
- return cc.v2(x, y)
- }
- getBezierLength(a, c, d, b, numPoints) {
- let length = 0
- let previousPoint = a
- for (let i = 1; i <= numPoints; i++) {
- let t = i / numPoints
- let currentPoint = this.bezierPoint(t, a, c, d, b)
- length += previousPoint.sub(currentPoint).mag()
- previousPoint = currentPoint
- }
- return length
- }
- getEquidistantPoints(a, b, numPoints, group, height?) {
- let {c, d} = this.calculatePointCD(a.x, a.y, b.x, b.y, group, height)
- let points = []
- let totalLength = this.getBezierLength(a, c, d, b, numPoints)
- let segmentLength = totalLength / (numPoints - 1)
- let previousPoint = a
- points.push(previousPoint)
- for (let i = 1; i < numPoints; i++) {
- let targetLength = segmentLength * i
- let low = (i - 1) / numPoints
- let high = i / numPoints
- while (high - low > 1e-5) {
- let mid = (low + high) / 2
- let point = this.bezierPoint(mid, a, c, d, b)
- let length = previousPoint.sub(point).mag()
- if (length < targetLength) {
- low = mid
- } else {
- high = mid
- }
- }
- let point = this.bezierPoint((low + high) / 2, a, c, d, b)
- points.push(point)
- previousPoint = point
- }
- return points
- }
- calculatePointCD(x1, y1, x2, y2, group, height?) {
- let a = cc.v2(x1, y1)
- let b = cc.v2(x2, y2)
- let dir = b.sub(a).normalize()
- let length = a.sub(b).mag()
- let k = Math.max(100000 / length, 50)
- k = Math.min(k, 100)
- if (height) k = height
- // 垂直方向向量
- let vDir = dir.rotate(90 * (Math.PI / 180)).mul(group == Data.game.gFriendBullet ? 1 : -1)
- let c = a.add(vDir.mul(k)).add(dir.mul(length / 3))
- let d = a.add(vDir.mul(k)).add(dir.mul((length * 2) / 3))
- return {c, d}
- }
- //-------------------------------技能-----------------------------------------
- public createSkill(
- fightData: IFightData,
- skillCfg: ISkillConfig,
- skillIndex: number,
- role: EntityIndex,
- pos?: cc.Vec3,
- group?: number,
- ) {
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[skillCfg.layer ? skillCfg.layer : GAME_LAYER.skill]
- comMap.prefabName = GAME_PREFAB_TYPE.skill
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- //提升自己数值技能
- let comSkill = this.addComponent(entity, ComSkill)
- comSkill.skillCfg = skillCfg
- comSkill.skillIndex = skillIndex
- comSkill.fightData = fightData
- comSkill.countDown = skillCfg.duration
- comSkill.role = role
- comSkill.group = group
- comSkill.hurtFrameCompleted = false
- comSkill.dirty = false
- if (role > 0) {
- let comRoleTrans = this.getComponent(role, ComTransform)
- let comRole = this.getComponent(role, ComRole)
- comTrans.x = comRoleTrans.x
- comTrans.y = comRoleTrans.y + comRoleTrans.halfHeight * (skillCfg.offsetPos[0] - 1)
- comSkill.group =
- comRole.group == Data.game.gFriend
- ? skillCfg.isHurt
- ? skillCfg.dirType == SKILL_DIR_TYPE.selfNormal
- ? Data.game.gFriendHurtSkill
- : Data.game.gEnemyHurtSkill
- : Data.game.gFriendGainSkill
- : skillCfg.isHurt
- ? skillCfg.dirType == SKILL_DIR_TYPE.selfNormal
- ? Data.game.gEnemyHurtSkill
- : Data.game.gFriendHurtSkill
- : Data.game.gEnemyGainSkill
- } else {
- if (!pos || !group) Log.error('技能创建失败')
- comTrans.x = pos.x
- comTrans.y = pos.y
- }
- comTrans.x += skillCfg.offsetPos[1]
- comTrans.y += skillCfg.offsetPos[2]
- if (skillCfg.type == SKILL_TYPE.attackBack && skillCfg.effectType.indexOf(SKILL_EFFECT_TYPE.move) >= 0) {
- let comMovable = this.addComponent(entity, ComMovable)
- comMovable.pointIdx = 0
- comMovable.points.length = 0
- comMovable.speed = skillCfg.effectParm[skillCfg.effectType.indexOf(SKILL_EFFECT_TYPE.move)][0]
- comMovable.points.push(
- cc.v2(
- comSkill.group == Data.game.gFriendHurtSkill || comSkill.group == Data.game.gFriendGainSkill
- ? Data.game.fightAreaMaxX
- : Data.game.fightAreaMinX,
- comTrans.y,
- ),
- )
- }
- return entity
- }
- public createSkillByFightData(
- fightData: IFightData,
- skillCfg: ISkillConfig,
- skillIndex: number,
- roles: EntityIndex[],
- ) {
- let isSuccess = false
- roles.forEach((role: EntityIndex) => {
- let comRole = this.getComponent(role, ComRole)
- if (this.isDie(comRole)) return
- this.createSkill(fightData, skillCfg, skillIndex, role)
- isSuccess = true
- })
- return isSuccess
- }
- public createCardBulletSkill(comBullet: ComBullet, role: EntityIndex, pos?: cc.Vec3) {
- //卡牌弹射子弹每次命中目标放技能
- let skillCfg = SkillConfig[comBullet.bulletCfg.skill]
- for (let i = 0; i < skillCfg.effectType.length; i++) {
- let type = skillCfg.effectType[i]
- if (type == SKILL_EFFECT_TYPE.reduce) {
- comBullet.fightData.attack *= 1 - skillCfg.effectParm[i][0] / Data.game.rateNum
- comBullet.fightData.spellAttack *= 1 - skillCfg.effectParm[i][0] / Data.game.rateNum
- comBullet.fightData.realAttack *= 1 - skillCfg.effectParm[i][0] / Data.game.rateNum
- }
- }
- if (role) {
- this.createSkillByFightData(comBullet.fightData, skillCfg, -1, [role])
- } else {
- let skillEntity = this.createSkill(
- comBullet.fightData,
- skillCfg,
- -1,
- 0,
- pos,
- comBullet.group == Data.game.gEnemyBullet
- ? skillCfg.isHurt
- ? Data.game.gEnemyHurtSkill
- : Data.game.gEnemyGainSkill
- : skillCfg.isHurt
- ? Data.game.gFriendHurtSkill
- : Data.game.gFriendGainSkill,
- )
- let tmp = this.getComponent(skillEntity, ComSkill)
- }
- //地板受击
- if (skillCfg.hitID[HIT_ANI_TYPE.floor]) {
- this.createAni(skillCfg.hitID[HIT_ANI_TYPE.floor], role, role ? null : cc.v2(pos))
- }
- }
- public isOneRoleSkill(skillCfg: ISkillConfig): boolean {
- return (
- skillCfg.dirType == SKILL_DIR_TYPE.selfRole ||
- skillCfg.dirType == SKILL_DIR_TYPE.anyRole ||
- skillCfg.dirType == SKILL_DIR_TYPE.minHpRole ||
- skillCfg.dirType == SKILL_DIR_TYPE.baby
- )
- }
- removeSkillEntity(entity) {
- let comSkill = this.getComponent(entity, ComSkill)
- let comCocosNode = this.getComponent(entity, ComCocosNode)
- if (!comSkill || !comCocosNode) return
- cCollider.inst.remove(comSkill.cObject.body)
- comCocosNode.node.removeComponent(comSkill.cObject)
- comSkill.cObject = null
- this.removeNodeEntity(entity)
- }
- //-------------------------------BUFF-----------------------------------------
- public createBuff(buffID, fightData: IFightData) {
- if (!BuffConfig[buffID]) return
- let buff = {buffCfg: BuffConfig[buffID]} as IBuff
- buff.countDown = buff.buffCfg.duration == Data.game.cdMax ? Infinity : buff.buffCfg.duration
- buff.countUp = 0
- buff.hurtFrameCompleted = false
- buff.hurtTimes = 0
- buff.immuneTimes = 0
- buff.curAttrChangeNum = []
- buff.createBaseAttr = Mgr.global.buildIBaseAttr(fightData, !fightData)
- buff.aniEntityArr = []
- return buff
- }
- public addBuff(skillEntity: EntityIndex, buff: IBuff, fightData: IFightData) {
- if (!buff) return
- let comRoleSkill = this.getComponent(skillEntity, ComRole)
- let comRoleTrans = this.getComponent(skillEntity, ComTransform)
- let comCocosNodeSkill = this.getComponent(skillEntity, ComCocosNode)
- let comHasSkillSkill = this.getComponent(skillEntity, ComHasSkill)
- let comSpineNode = this.getComponent(comRoleSkill.spineEntity, ComCocosNode)
- if (!comCocosNodeSkill || !comCocosNodeSkill.loaded || this.isDie(comRoleSkill) || this.isBase(comRoleSkill)) {
- return
- }
- //图腾对象不施加BUFF
- if (comRoleSkill.roleCfg.type == ROLE_TYPE.totem) return
- let sameIDBuffs = comRoleSkill.buffs.filter(buffTmp => buffTmp.buffCfg.ID == buff.buffCfg.ID)
- let buffCfg = buff.buffCfg
- let sameArrIDBuffs = comRoleSkill.buffs.filter(
- buffTmp => buffCfg.arrID > 0 && buffTmp.buffCfg.arrID == buffCfg.arrID,
- )
- let addBuffFuc = (isReplace: boolean = false) => {
- let hasImmune = false
- comRoleSkill.buffs.forEach(buffTmp => {
- let buffCfg = buffTmp.buffCfg
- if (buffCfg.buffType == BUFF_TYPE.negativeImmune) {
- let negativeArr = buffCfg.effectParm[buffCfg.effectType.indexOf(BUFF_EFFECT_TYPE.immuneNegative)]
- if (negativeArr) {
- hasImmune ||=
- negativeArr.includes(NEGATIVE_TYPE.delay) && buff.buffCfg.buffType == BUFF_TYPE.dizzy
- hasImmune ||=
- negativeArr.includes(NEGATIVE_TYPE.slow) &&
- buff.buffCfg.attrRate[buff.buffCfg.attr.indexOf(ATTR_NAME.moveSpeed)] < 0
- }
- }
- })
- if (hasImmune) return
- //光环buff不施放,在处理hasSkill处理
- comRoleSkill.buffs.push(buff)
- //comCocosNodeSkill.events.push(new EventBuffChange(comRoleSkill.buffs, [buff], []))
- for (let aniID of buff.buffCfg.buffUrl) {
- if (!aniID || isReplace) continue
- if (aniID == BUFF_ANI_TYPE.slow) {
- comSpineNode?.events.push(new EventSlowDown(true))
- }
- buff.aniEntityArr.push(this.createAni(aniID, skillEntity))
- }
- buffCfg.buffIcon.forEach(value => {
- console.log('推入buff', value)
- comCocosNodeSkill.events.push(new EventRoleTip(GAME_ROLE_TIP.buffTip, buffCfg.hurtEffect, value))
- })
- if (buff.buffCfg.buffType == BUFF_TYPE.dizzy) {
- let comDizzy = this.getComponent(skillEntity, ComDizzy)
- if (comDizzy && !this.isDie(comRoleSkill)) {
- comDizzy.countDown = buff.buffCfg.attrNum[0]
- for (let i = 0; i < buff.buffCfg.effectType.length; i++) {
- let type = buff.buffCfg.effectType[i]
- if (type == BUFF_EFFECT_TYPE.boss && comRoleSkill.roleCfg.type == MONSTER_TYPE.boss) {
- comDizzy.countDown *= 1 - buff.buffCfg.effectParm[i][0] / Data.game.rateNum
- }
- }
- if (comRoleSkill.entryMap.get(ENTRY.delayReduce)?.num) {
- comDizzy.countDown *= 1 - comRoleSkill.entryMap.get(ENTRY.delayReduce).num / Data.game.rateNum
- }
- if (fightData && fightData.entryMap.get(ENTRY.delayAdd)?.num) {
- comDizzy.countDown *= 1 + fightData.entryMap.get(ENTRY.delayAdd).num / Data.game.rateNum
- }
- //将顶盾的buff去掉
- let findIndex = comRoleSkill.buffs.findIndex(
- value => value.buffCfg.buffType == BUFF_TYPE.shieldReduceHurt,
- )
- if (findIndex != -1) comRoleSkill.buffs.splice(findIndex, 1)
- let comDizzySkillAbel = this.getComponent(skillEntity, ComSkillAbel)
- comDizzySkillAbel.isInShield = false
- //将顶盾的罩子,友军免疫远程攻击buff去掉
- this.removeNodeEntity(comDizzySkillAbel.ani)
- let skillIndex = comRoleSkill.skills.findIndex(v => v.type == SKILL_TYPE.holo)
- if (skillIndex >= 0) {
- let allEntity = Array.from(comHasSkillSkill.skillCObjects[skillIndex].containsBody.keys())
- allEntity = allEntity.filter(entityTmp => !this.isDie(entityTmp))
- allEntity.forEach(v => {
- let tmpComRole = this.getComponent(v, ComRole)
- let findIndex = tmpComRole.buffs.findIndex(
- value => value.buffCfg.buffType == BUFF_TYPE.rangedImmune,
- )
- if (findIndex != -1) {
- console.warn('去掉免疫buff')
- tmpComRole.buffs.splice(findIndex, 1)
- }
- })
- }
- //将技能弹射子弹去除
- if (comDizzySkillAbel.bullets) {
- comDizzySkillAbel.bullets.forEach(v => {
- this.removeBulletEntity(v)
- })
- comDizzySkillAbel.bullets.length = 0
- }
- }
- }
- }
- let replaceBuffFuc = (replaceBuff: IBuff) => {
- //addType==0直接替换,==1替换效果最好的
- if (
- buffCfg.addType == 0 ||
- (buffCfg.addType == 1 && buffCfg.attrRate[0] >= replaceBuff.buffCfg.attrRate[0])
- ) {
- let removeBuffs = comRoleSkill.buffs.splice(comRoleSkill.buffs.indexOf(replaceBuff), 1)
- this.removeBuffAttr(skillEntity, removeBuffs[0])
- addBuffFuc(true)
- //特效继承,时间重置
- buff.aniEntityArr.push(...removeBuffs[0].aniEntityArr)
- for (let aniEntity of buff.aniEntityArr) {
- let comFrameAni = this.getComponent(aniEntity, ComFrameAni)
- if (comFrameAni) comFrameAni.countDown = comFrameAni.aniConfig.duration
- }
- }
- }
- if (buffCfg.arrID > 0) {
- //有buff组,根据叠加和替换规则确定是否叠加和替换
- if (buffCfg.isAdd && (!buffCfg.addNum || (buffCfg.addNum > 0 && sameArrIDBuffs.length < buffCfg.addNum))) {
- //叠加
- addBuffFuc()
- } else if (!buffCfg.isAdd) {
- //不叠加
- if (sameArrIDBuffs.length == 0) {
- addBuffFuc()
- } else {
- replaceBuffFuc(sameArrIDBuffs[0])
- }
- }
- } else {
- //不叠加
- if (sameIDBuffs.length == 0) {
- addBuffFuc()
- } else {
- replaceBuffFuc(sameIDBuffs[0])
- }
- }
- }
- public removeBuffAttr(role: EntityIndex, buff: IBuff) {
- let comRole = this.getComponent(role, ComRole)
- if (this.isDie(comRole)) return
- let buffConfig = buff.buffCfg
- for (let j = 0; j < buffConfig.attr.length; j++) {
- if (buff.curAttrChangeNum[j]) {
- comRole[buffConfig.attr[j]] -= buff.curAttrChangeNum[j]
- if (buffConfig.attr[j] == ATTR_NAME.attackRange) {
- let comFindEnemy = this.getComponent(role, ComFindEnemy)
- if (comFindEnemy.attackCObject.radius != comRole.attackRange) {
- comFindEnemy.attackCObject.updateSphereShape(comRole.attackRange)
- }
- }
- }
- }
- }
- //-------------------------------特效-----------------------------------------
- public createAni(aniID: number, role: EntityIndex, pos?: cc.Vec2) {
- let frameAniConfig = FrameAniConfig[aniID]
- if (!frameAniConfig) {
- console.error('frameAniID不存在', aniID)
- return
- }
- if (frameAniConfig.type == ANI_TYPE.shader) return
- let entity = this.createEntity()
- // 添加nodeconfig
- let comMap = this.addComponent(entity, ComNodeConfig)
- comMap.id = 1
- comMap.layer = GAME_LAYER[frameAniConfig.layer ? frameAniConfig.layer : GAME_LAYER.skill]
- comMap.prefabName = GAME_PREFAB_TYPE.frameAni
- //移除cocosNode
- this.removeComponent(entity, ComCocosNode)
- // 添加transform
- let comTrans = this.addComponent(entity, ComTransform)
- let comFrameAni = this.addComponent(entity, ComFrameAni)
- comFrameAni.countDown = frameAniConfig.duration
- comFrameAni.dirty = false
- comFrameAni.aniConfig = frameAniConfig
- comFrameAni.role = role
- comFrameAni.lineStartPos = null
- comFrameAni.lineStartEntity = 0
- comFrameAni.lineEndEntity = 0
- let comRoleTrans = this.getComponent(role, ComTransform)
- if (pos) {
- comTrans.x = pos.x
- comTrans.y = pos.y
- } else if (comRoleTrans) {
- comTrans.x = comRoleTrans.x
- comTrans.y =
- comRoleTrans.y +
- (frameAniConfig.offsetPos[0] ? comRoleTrans.halfHeight * (frameAniConfig.offsetPos[0] - 1) : 0)
- }
- comTrans.x += frameAniConfig.offsetPos[1]
- comTrans.y += frameAniConfig.offsetPos[2]
- return entity
- }
- //--------------------------------词条-------------------------------------------------
- isGameEntry(type: ENTRY) {
- return type >= ENTRY.ignoreDefense && type <= 100
- }
- initEntry() {
- if (Data.game.gameType != GAME_TYPE.relic) {
- for (let id of Data.user.talents) {
- let talentCfg = TalentConfig[id]
- let type = EntryConfig[talentCfg.entryID].type
- switch (type) {
- case ENTRY.startCostAdd:
- break
- }
- }
- }
- }
- convertEntry2Obj(entryID: number): EntryObj {
- let entryCfg = EntryConfig[entryID]
- let num = 0
- if (entryCfg.parmArr[0] && entryCfg.parmArr.length == 1) num = entryCfg.parmArr[0]
- if (entryCfg.rateArr[0] && entryCfg.rateArr.length == 1) num = entryCfg.rateArr[0]
- let numArrTmp = []
- if (entryCfg.parmArr.length > 1) numArrTmp.push(entryCfg.parmArr)
- if (entryCfg.rateArr.length > 1) numArrTmp.push(entryCfg.rateArr)
- return {num, numArr: numArrTmp, type: entryCfg.type, profession: entryCfg.profession}
- }
- putEntry2Map(comRole: ComRole, entryObj: EntryObj) {
- let map = comRole.entryMap
- if (!this.isGameEntry(entryObj.type) || !entryObj.profession.includes(comRole.roleCfg.profession)) return
- let obj = map.get(entryObj.type)
- if (obj) {
- //叠加规则
- if (entryObj.num > 0) {
- //默认数值相加
- obj.num += entryObj.num
- } else if (entryObj.numArr.length > 0) {
- //数组默认覆盖最好的效果
- let lastNum = obj.numArr[0][obj.numArr[0].length - 1]
- let newLastNum = entryObj.numArr[0][entryObj.numArr[0].length - 1]
- if (newLastNum > lastNum) {
- obj.numArr[0][obj.numArr[0].length - 1] = newLastNum
- }
- }
- } else {
- map.set(entryObj.type, entryObj)
- }
- }
- //--------------------------------改变无敌状态-------------------------------------------------
- changeInvincible(role: EntityIndex, invincible: boolean) {
- let comRole = this.getComponent(role, ComRole)
- if (this.isDie(comRole)) return
- comRole.invincible = invincible
- }
- //--------------------------------绘制碰撞体-------------------------------------------------
- drawDebug(entity: EntityIndex, cObject) {
- let comCocosNode = this.getComponent(entity, ComCocosNode)
- let comTrans = this.getComponent(entity, ComTransform)
- if (!comCocosNode || !comTrans || !cObject || !CC_DEV || !cc.debug.isDisplayStats()) return
- //绘制碰撞体
- let localPoints
- let offset = cc.v2(comTrans.x, comTrans.y).add(cc.v2(cObject.center))
- if (cObject.type == ShapeType.Box) {
- localPoints = []
- localPoints.push(cc.v2(offset.x - cObject.size.x / 2, offset.y + cObject.size.y / 2)) // 左上角
- localPoints.push(cc.v2(offset.x + cObject.size.x / 2, offset.y + cObject.size.y / 2)) // 右上角
- localPoints.push(cc.v2(offset.x + cObject.size.x / 2, offset.y - cObject.size.y / 2)) // 右下角
- localPoints.push(cc.v2(offset.x - cObject.size.x / 2, offset.y - cObject.size.y / 2)) // 左下角
- }
- if (cObject.type == ShapeType.Sphere) {
- localPoints = [cc.v2(comTrans.x, comTrans.y).add(cc.v2(cObject.center))]
- }
- if (localPoints) {
- let color
- let comRole = this.getComponent(entity, ComRole)
- if (comRole) {
- color = comRole.group == Data.game.gFriend ? cc.Color.GREEN : cc.Color.RED
- }
- let comSkill = this.getComponent(entity, ComSkill)
- if (comSkill) {
- color =
- comSkill.group == Data.game.gFriendGainSkill || comSkill.group == Data.game.gFriendHurtSkill
- ? cc.Color.GREEN
- : cc.Color.RED
- }
- comCocosNode.events.push(
- new EventGraphicsDraw(localPoints, cObject.type == ShapeType.Box ? 0 : cObject.radius, color),
- )
- }
- }
- //--------------------------------移除战场上的实体-------------------------------------------------
- removeNodeEntity(entity: EntityIndex) {
- this.putNode(entity)
- this.removeAllComponents(entity)
- this.removeEntity(entity)
- }
- putNode(entity: EntityIndex) {
- let comCocosNode = this.getComponent(entity, ComCocosNode)
- if (comCocosNode) {
- let node = comCocosNode.node
- if (node) {
- let eventProcess = node.getComponent(EventProcess)
- eventProcess.onDetach()
- node.removeFromParent()
- if (this.fightCore) {
- let pool = this.fightCore.gamePool.get(node.name)
- if (pool) {
- this.resetGameNode(node)
- pool.put(node)
- }
- }
- }
- }
- }
- resetGameNode(node) {
- ccUtils.stopAni(node)
- node.stopAllActions()
- node.opacity = 255
- node.angle = 0
- node.scale = 1
- node.position = cc.v2(-10000, -10000)
- let sprite = node.getComponent(cc.Sprite)
- if (sprite) sprite.spriteFrame = null
- let spine = node.getComponent(sp.Skeleton)
- if (spine) spine.skeletonData = null
- let frameAnimation = node.getComponent(FrameAnimation)
- if (frameAnimation) {
- frameAnimation.stop()
- //frameAnimation.spriteAtlas = null
- }
- if (node.name != GAME_PREFAB_TYPE.role) node.children.forEach(v => this.resetGameNode(v))
- }
- }
|