--存放那些和system没什么关系的数据--- local RecordComponent = class("RecordComponent") local rawget = rawget local ZERO = FP.Const.Zero local FP_ONE = FP.Const.One local MissileGroupType_MUSOU = LuaConst.EMissileGroupType.MUSOU local MissileGroupType_ADJUTANT = LuaConst.EMissileGroupType.ADJUTANT function RecordComponent:initialize(entity) self.Entity = entity if entity.isHero or entity.isAdjuntant then self.overrideSkillDataDic = {} self.overrideCallDataDic = {} self.overrideMissileDataDic = {} self.overrideTrackerDataDic = {} end --被xxx杀死。如果是召唤物杀的,则会算作是主人,KillerEntity为主人 self.KillerEntity = nil --是否卸载 self.IsUnload = false --大变身计时 self.ChangeAvatarTimer = nil --换将的倒计时,单位:毫秒 self.SwitchTimer = -1 --被动指令,(缓存一定要执行的代码而已);主动的cmd都用input self.PassivitySpecialCommand = LuaConst.SpecialCommandType.None --这一条命杀敌数,3v3用到 self.KillNum = 0 --一场战斗,最高的连杀数,3v3用到 self.MaxKillNum = 0 --一场战斗,总的杀敌数,3v3用到 self.TotalKillNum = 0 --一场战斗 死亡次数,3v3用到 self.DeadCount = 0 -- 攻防时间(帧数),3v3用到 self.ConfrontTimeFrame = 0 --受伤次数 self.BeHurtCount = FP.newV1(0) self.hpSubTimeStamp = nil --玩家上一次掉血的时间戳,并不是当前单位的,而是玩家的。在切将时toEntity会从fromEntity继承这个值 self.OwnerPlayerID = nil -- 自己属于哪个玩家的 self.lastHpLoss = FP.newV1(0) --上次掉血量的绝对值, 一定大于0,不会等于0 self.longestHpLossIntervalFrame = 0 --整场战斗最长的受伤间隔帧数,仅统计英雄单位, 切将时时间也会继承(比如A单位已经5秒未受伤,切到B单位时从5秒开始增长) self.HpLossRecord = {} self.LifeStealRecord = {} --状态记录数组,每个元素都是1帧的状态,目前只会有 hp、sa、cdList(闪避、技能1、技能2、技能3)、pos (数值都是number类型,从定点数里拿的,不会导致不一致)。 self.stateRecordsTail指向最新的1帧的状态,整个stateRecords循环使用 --如果为nil,表示不记录状态,否则记录状态. self.stateRecords = nil --状态记录数组的尾指针,记录了当前插入数据的位置,小于等于 self.stateRecordFrameCount self.stateRecordsTail = nil --状态记录的缓存数量 self.stateRecordFrameCount = nil self.VariableDic = {} --变量字典 self.InstantSkillAttackEnterRecords = {} --瞬时技能释放记录。元素是一个table:{skillID,frameStamp} self.BlindFlagRecordList = {} --致盲标记记录列表 元素是table:{buffID,entityID} self.BlindFlagCount = 0 --致盲标记数量 --当大于0时,表示处于【致盲】状态,【致盲】状态下,发出的子弹无法碰撞到敌人 --- 记录子弹的伤害系数 key=子弹id,val=子弹伤害系数-是FP(如1.1增加10%)。 ---注意:如果是所有子弹都造成伤害加成则不要设置这个,应该直接修改 属性 findmgvar。 self.MissileDmgFactorDic = {} self.MissileGroupDmgFactorDic = {} -- 与MissileDmgFactorDic基本相同,只是key是missileData.GroupID if self.Entity:IsHero() then self.heroDeadRecordList = {} --英雄死亡记录列表,如果self.Entity是英雄,则这个列表记录了这个英雄单位每一次的死亡信息。 死亡信息:{frame=死亡帧数, killer=击杀者} self.lastKilledByHeroRecord = nil --玩家上次被英雄杀死的死亡信息, 如果切将,toEntity会继承fromEntity的信息 end self.lastHitByMusouOrAdjutantFrame = 9999999 self.lastHitByMusouOrAdjutantMissileData = nil end function RecordComponent:AddMissileDmgFactor(missileId, dmgFactor) if self.MissileDmgFactorDic[missileId] then self.MissileDmgFactorDic[missileId]:Mul(dmgFactor) else self.MissileDmgFactorDic[missileId] = FP.newV1(dmgFactor) end end function RecordComponent:RemoveMissileDmgFactor(missileId, dmgFactor) self.MissileDmgFactorDic[missileId]:Div(dmgFactor) if self.MissileDmgFactorDic[missileId] == FP_ONE then self.MissileDmgFactorDic[missileId] = nil end end function RecordComponent:ClearMissileDmgFactor(missileId) self.MissileDmgFactorDic[missileId] = nil end function RecordComponent:AddMissileGroupDmgFactor(missileGroupId, dmgFactor) if self.MissileGroupDmgFactorDic[missileGroupId] then self.MissileGroupDmgFactorDic[missileGroupId]:Mul(dmgFactor) else self.MissileGroupDmgFactorDic[missileGroupId] = FP.newV1(dmgFactor) end end function RecordComponent:RemoveMissileGroupDmgFactor(missileGroupId, dmgFactor) self.MissileGroupDmgFactorDic[missileGroupId]:Div(dmgFactor) if self.MissileGroupDmgFactorDic[missileGroupId] == FP_ONE then self.MissileGroupDmgFactorDic[missileGroupId] = nil end end function RecordComponent:ClearMissileGroupDmgFactor(missileGroupId) self.MissileGroupDmgFactorDic[missileGroupId] = nil end function RecordComponent:AddInstantSkillAttackEnterRecord(skillID, frameStamp) local record = {skillID = skillID, frameStamp = frameStamp} table.insert(self.InstantSkillAttackEnterRecords, record) end function RecordComponent:GetLatestInstantSkillAttackEnterRecord(skillID) for i=#self.InstantSkillAttackEnterRecords,1,-1 do if self.InstantSkillAttackEnterRecords[i].skillID == skillID then return self.InstantSkillAttackEnterRecords[i] end end end function RecordComponent:AddHpLossRecord(delta) if delta < ZERO then if self.Entity:IsHero() then self:RefreshLongestHpLossIntervalFrame() end local clientHandleFrame = LogicUpdateManager._clientHandleFrame self.hpSubTimeStamp = clientHandleFrame self.BeHurtCount:Add(1) self.HpLossRecord[clientHandleFrame] = self.HpLossRecord[clientHandleFrame] or FP.newV1(0) self.HpLossRecord[clientHandleFrame] = self.HpLossRecord[clientHandleFrame]:Add(delta) end end function RecordComponent:AddLifeStealRecord(delta) if delta > ZERO then local clientHandleFrame = LogicUpdateManager._clientHandleFrame self.LifeStealRecord[clientHandleFrame] = self.LifeStealRecord[clientHandleFrame] or FP.newV1(0) self.LifeStealRecord[clientHandleFrame] = self.LifeStealRecord[clientHandleFrame]:Add(delta) end end function RecordComponent:RefreshLongestHpLossIntervalFrame() local interval = LogicUpdateManager._clientHandleFrame - (self.hpSubTimeStamp or 0) if interval > self.longestHpLossIntervalFrame then self.longestHpLossIntervalFrame = interval end end --返回最近second秒内的总掉血(会忽略加血,比如最近1秒掉过100点血,又恢复了100点血,会返回-100) --会返回负数的FP function RecordComponent:GetHpLossWithin(second) -- local frame = second * LuaConst.LogicFrameRate -- local curFrame = LogicUpdateManager._clientHandleFrame -- if frame > curFrame then -- frame = curFrame -- end -- local hpLoss = FP.newV1(0) -- for i=1,frame do -- if self.HpLossRecord[curFrame - i + 1] then -- hpLoss = hpLoss:Add(self.HpLossRecord[curFrame - i + 1]) -- end -- end -- return hpLoss return self:GetSumWithinSecondByRecord(second, self.HpLossRecord) end function RecordComponent:GetLifeStealWithin(second) return self:GetSumWithinSecondByRecord(second, self.LifeStealRecord) end --返回second秒内,record记录的值的和 function RecordComponent:GetSumWithinSecondByRecord(second, record) local frame = second * LuaConst.LogicFrameRate local curFrame = LogicUpdateManager._clientHandleFrame if frame > curFrame then frame = curFrame end local sum = FP.newV1(0) for i=0,frame-1 do if record[curFrame - i] then sum = sum:Add(record[curFrame - i]) end end return sum end function RecordComponent:TryGetBlindFlagRecordIndex(buffID, entityID) for i,record in ipairs(self.BlindFlagRecordList) do if record.buffID == buffID and record.entityID == entityID then return i end end end function RecordComponent:AddBlindFlag(buffID, entityID) if not self:TryGetBlindFlagRecordIndex(buffID, entityID) then table.insert(self.BlindFlagRecordList,{buffID = buffID, entityID = entityID}) self.BlindFlagCount = self.BlindFlagCount + 1 end end function RecordComponent:CancelBlindFlag(buffID, entityID) local index = self:TryGetBlindFlagRecordIndex(buffID, entityID) if index then self.BlindFlagCount = self.BlindFlagCount - 1 table.remove(self.BlindFlagRecordList, index) if self.BlindFlagCount < 0 then logging.error(LTAG.ERROR, "HYW : 警告! 致盲标记小于0了!!! 强制恢复成0 buffID : ", buffID) self.BlindFlagCount = 0 end else logging.error(LTAG.ERROR, "HYW : 警告! 试图删除不存在的BlindFlag buffID : ", buffID) end end function RecordComponent:SetOwnerPlayerID(playerID) self.OwnerPlayerID = playerID end function RecordComponent:GetOwnerPlayerID() return self.OwnerPlayerID end function RecordComponent:SetPosTraceEntity(entity) self.posTraceEntity = entity end --设置本单位最后伤害过的单位 function RecordComponent:SetLastHurtEnemy(enemyEntity) self.lastHurtEnemy = enemyEntity end --设置本单位最后被哪个单位伤害过 function RecordComponent:SetLastHurtMeEnemy(enemyEntity) self.lastHurtMeEnemy = enemyEntity end --可能返回空,如果不为空,一般是返回一个整数number function RecordComponent:GetVariable(key) return self.VariableDic[key] end function RecordComponent:GetVariableFromMaster(key) local master = self.Entity:GetMasterEntity() if master then return master.components.record:GetVariable(key) else return self:GetVariable(key) end end local _tempV1 = FP.newV1(0) function RecordComponent:VariableAdd(key,delta) local curValue = self.VariableDic[key] or 0 _tempV1:Reset(delta) --使用定点数trim,这样仅加法的话存number也不会出问题 _tempV1:Add(curValue) self.VariableDic[key] = FP.tonumberV1(_tempV1) end function RecordComponent:VariableSet(key, value) self.VariableDic[key] = value end function RecordComponent:ClearVariable(key) self.VariableDic[key] = nil end function RecordComponent:OnLogicUpdate() if self.stateRecords then local cdList = {} for belongID,updateData in pairs(self.Entity.components.skillBase.CurUpdateDataGroup) do --pairs safe 数据查询和复制,复制到固定顺序的列表里 local keyPosition = self.Entity:GetSkillData(belongID).KeyPosition if keyPosition == LuaConst.ESkillKeyPosition.Dodge then cdList[1] = updateData.CD[1] elseif keyPosition == LuaConst.ESkillKeyPosition.Skill1 then cdList[2] = updateData.CD[1] cdList[5] = updateData.ChargeCount elseif keyPosition == LuaConst.ESkillKeyPosition.Skill2 then cdList[3] = updateData.CD[1] cdList[6] = updateData.ChargeCount elseif keyPosition == LuaConst.ESkillKeyPosition.Skill3 then cdList[4] = updateData.CD[1] cdList[7] = updateData.ChargeCount end end self.stateRecords[self.stateRecordsTail] = { self.Entity:GetAttrValue(LuaConst.RealtimeAttrType.hp)[1], self.Entity:GetAttrValue(LuaConst.RealtimeAttrType.sa)[1], cdList, self.Entity:GetLogicPos():cloneV2(), } self.stateRecordsTail = self.stateRecordsTail + 1 if self.stateRecordsTail > self.stateRecordFrameCount then self.stateRecordsTail = self.stateRecordsTail - self.stateRecordFrameCount end end end function RecordComponent:OnHPChange(realDelta, value, op, hpChangeType, missileData) if op == "sub" then self:AddHpLossRecord(realDelta) end if realDelta < ZERO then self.lastHpLoss:Reset(realDelta):Mul(-1) if missileData and (missileData.GroupID == MissileGroupType_MUSOU or missileData.GroupID == MissileGroupType_ADJUTANT) then self.lastHitByMusouOrAdjutantMissileData = missileData self.lastHitByMusouOrAdjutantFrame = LogicUpdateManager._clientHandleFrame end end if hpChangeType == LuaConst.EHpChangeType.LIFE_STEAL then self:AddLifeStealRecord(realDelta) end end function RecordComponent:OnSwitchHeroFrom(fromEntity) local fromHpSubTimeStamp = fromEntity.components.record.hpSubTimeStamp if fromHpSubTimeStamp then local toHpSubTimeStamp = self.hpSubTimeStamp if toHpSubTimeStamp == nil or toHpSubTimeStamp < fromHpSubTimeStamp then self.hpSubTimeStamp = fromHpSubTimeStamp end end local fromEntityKilledRecord = fromEntity.components.record.lastKilledByHeroRecord if fromEntityKilledRecord then if self.lastKilledByHeroRecord then if fromEntityKilledRecord.frame > self.lastKilledByHeroRecord.frame then self.lastKilledByHeroRecord = fromEntityKilledRecord end else self.lastKilledByHeroRecord = fromEntityKilledRecord end end end function RecordComponent:OnDead() self.lastDeadFrame = LogicUpdateManager._clientHandleFrame if self.Entity:IsHero() then local record = { frame = LogicUpdateManager._clientHandleFrame, } table.insert(self.heroDeadRecordList, record) if self.KillerEntity then record.killer = self.KillerEntity:GetOriginEntity() if record.killer:IsHero() and record.killer ~= self.Entity then self.lastKilledByHeroRecord = record end end end end function RecordComponent:AddRetinueBornAreaListRecord(list, masterEntityPos) self.retinueBornAreaList = list self.retinueBornAreaMasterPosX = masterEntityPos.x[1] self.retinueBornAreaMasterPosZ = masterEntityPos.z[1] end function RecordComponent:GetRetinueBornAreaListRecord(masterEntityPos) if self.retinueBornAreaMasterPosX == masterEntityPos.x[1] and self.retinueBornAreaMasterPosZ == masterEntityPos.z[1] then return self.retinueBornAreaList end end function RecordComponent:BindToMissile(missile) self.bindingMissile = missile end function RecordComponent:StartStateRecord(frameCount) self.stateRecordFrameCount = frameCount self.stateRecords = {} self.stateRecordsTail = 1 end --hp、sa、cdList(闪避、技能1、技能2、技能3、技能1充能数、技能2充能数、技能3充能数)、pos (数值都是number类型,从定点数里拿的rawValue,是定点数的数值*1000的值,不会导致不一致) function RecordComponent:GetOldestStateRecord() if self.stateRecordsTail then local index = self.stateRecordsTail + 1 if index > #self.stateRecords then index = 1 elseif index > self.stateRecordFrameCount then index = index - self.stateRecordsTail end if self.stateRecords[index] then return unpack(self.stateRecords[index]) end end end function RecordComponent:_OverrideDataCell(dataSheetName, overrideDataDic, dataID, columnName, value, tableIndex, tableName) if overrideDataDic == nil then logging.error(LTAG.ERROR, "HYW : 只有英雄或副将才可以覆盖数据,如果要求怪物也能覆盖需要联系程序提需求 怪物ID :", self.Entity:GetCharacterID()) return end local overrideData = overrideDataDic[dataID] if overrideData == nil then overrideData = {} setmetatable(overrideData, { __index = DataSheetManager[dataSheetName]:GetDataByID(dataID)}) overrideDataDic[dataID] = overrideData end if tableIndex > 0 then tableName = tableName .. "_Table" local tableList = rawget(overrideData, tableName) if tableList == nil then tableList = {} for i,v in ipairs(overrideData[tableName]) do tableList[i] = v end overrideData[tableName] = tableList end local dataTable = tableList[tableIndex] if dataTable == DataSheetManager[dataSheetName]:GetDataByID(dataID)[tableName][tableIndex] then dataTable = {} setmetatable(dataTable, { __index = DataSheetManager[dataSheetName]:GetDataByID(dataID)[tableName][tableIndex]}) tableList[tableIndex] = dataTable end if DataSheetUtil.IsColumnFP(dataSheetName, columnName, tableName) then value = self:ConvertValueToFP(value) end dataTable[columnName] = value else if DataSheetUtil.IsColumnFP(dataSheetName, columnName) then value = self:ConvertValueToFP(value) end overrideData[columnName] = value end end function RecordComponent:ConvertValueToFP(value) if type(value) == "table" then for i,v in ipairs(value) do value[i] = FP.newV1(v) end else value = FP.newV1(value) end return value end function RecordComponent:OverrideSkillDataCell(skillID, columnName, value, tableIndex, tableName) --[[ if self.overrideSkillDataDic == nil then logging.error(LTAG.ERROR, "HYW : 只有英雄才可以覆盖数据,如果要求怪物也能覆盖需要联系程序提需求") return end local overrideSkillData = self.overrideSkillDataDic[skillID] if overrideSkillData == nil then overrideSkillData = {} setmetatable(overrideSkillData, { __index = DataSheetManager.SkillData:GetDataByID(skillID)}) self.overrideSkillDataDic[skillID] = overrideSkillData end if tableIndex then tableName = tableName .. "_Table" local tableList = rawget(overrideSkillData, tableName) if tableList == nil then tableList = {} for i,v in ipairs(overrideSkillData[tableName]) do tableList[i] = v end overrideSkillData[tableName] = tableList end local dataTable = tableList[tableIndex] if dataTable == DataSheetManager.SkillData:GetDataByID(skillID)[tableName][tableIndex] then dataTable = {} setmetatable(dataTable, { __index = DataSheetManager.SkillData:GetDataByID(skillID)[tableName][tableIndex]}) tableList[tableIndex] = dataTable end if DataSheetUtil.IsColumnFP("SkillData", columnName, tableName) then value = FP.newV1(value) end dataTable[columnName] = value else if DataSheetUtil.IsColumnFP("SkillData", columnName) then value = FP.newV1(value) end overrideSkillData[columnName] = value end --]] self:_OverrideDataCell("SkillData", self.overrideSkillDataDic, skillID, columnName, value, tableIndex, tableName) self.Entity.components.skillBase:OnOverrideSkillDataCell(skillID) end function RecordComponent:OverrideCallDataCell(callID, columnName, value, tableIndex, tableName) --[[ if self.overrideCallDataDic == nil then logging.error(LTAG.ERROR, "HYW : 只有英雄才可以覆盖数据,如果要求怪物也能覆盖需要联系程序提需求") return end local overrideCallData = self.overrideCallDataDic[callID] if overrideCallData == nil then overrideCallData = {} setmetatable(overrideCallData, { __index = DataSheetManager.CallBulletData:GetDataByID(callID)}) self.overrideCallDataDic[callID] = overrideCallData end if tableIndex then tableName = tableName .. "_Table" local tableList = rawget(overrideCallData, tableName) if tableList == nil then tableList = {} for i,v in ipairs(overrideCallData[tableName]) do tableList[i] = v end overrideCallData[tableName] = tableList end local dataTable = tableList[tableIndex] if dataTable == DataSheetManager.CallBulletData:GetDataByID(callID)[tableName][tableIndex] then dataTable = {} setmetatable(dataTable, { __index = DataSheetManager.CallBulletData:GetDataByID(callID)[tableName][tableIndex]}) tableList[tableIndex] = dataTable end if DataSheetUtil.IsColumnFP("CallBulletData", columnName, tableName) then value = FP.newV1(value) end dataTable[columnName] = value else if DataSheetUtil.IsColumnFP("CallBulletData", columnName) then value = FP.newV1(value) end overrideCallData[columnName] = value end --]] self:_OverrideDataCell("CallBulletData", self.overrideCallDataDic, callID, columnName, value, tableIndex, tableName) end function RecordComponent:OverrideMissileDataCell(missileID, columnName, value, tableIndex, tableName) --[[ if self.overrideMissileDataDic == nil then logging.error(LTAG.ERROR, "HYW : 只有英雄才可以覆盖数据,如果要求怪物也能覆盖需要联系程序提需求") return end local overrideMissileData = self.overrideMissileDataDic[missileID] if overrideMissileData == nil then overrideMissileData = {} setmetatable(overrideMissileData, { __index = DataSheetManager.MissileData:GetDataByID(missileID)}) self.overrideMissileDataDic[missileID] = overrideMissileData end if tableIndex then tableName = tableName .. "_Table" local tableList = rawget(overrideMissileData, tableName) if tableList == nil then tableList = {} for i,v in ipairs(overrideMissileData[tableName]) do tableList[i] = v end overrideMissileData[tableName] = tableList end local dataTable = tableList[tableIndex] if dataTable == DataSheetManager.MissileData:GetDataByID(missileID)[tableName][tableIndex] then dataTable = {} setmetatable(dataTable, { __index = DataSheetManager.MissileData:GetDataByID(missileID)[tableName][tableIndex]}) tableList[tableIndex] = dataTable end if DataSheetUtil.IsColumnFP("MissileData", columnName, tableName) then value = FP.newV1(value) end dataTable[columnName] = value else if DataSheetUtil.IsColumnFP("MissileData", columnName) then value = FP.newV1(value) end overrideMissileData[columnName] = value end --]] self:_OverrideDataCell("MissileData", self.overrideMissileDataDic, missileID, columnName, value, tableIndex, tableName) end function RecordComponent:OverrideTrackerDataCell(trackerID, columnName, value, tableIndex, tableName) --[[ if self.overrideTrackerDataDic == nil then logging.error(LTAG.ERROR, "HYW : 只有英雄才可以覆盖数据,如果要求怪物也能覆盖需要联系程序提需求") return end local overrideTrackerData = self.overrideTrackerDataDic[trackerID] if overrideTrackerData == nil then overrideTrackerData = {} setmetatable(overrideTrackerData, { __index = DataSheetManager.TrackerData:GetDataByID(trackerID)}) self.overrideTrackerDataDic[trackerID] = overrideTrackerData end if tableIndex then tableName = tableName .. "_Table" local tableList = rawget(overrideTrackerData, tableName) if tableList == nil then tableList = {} for i,v in ipairs(overrideTrackerData[tableName]) do tableList[i] = v end overrideTrackerData[tableName] = tableList end local dataTable = tableList[tableIndex] if dataTable == DataSheetManager.TrackerData:GetDataByID(trackerID)[tableName][tableIndex] then dataTable = {} setmetatable(dataTable, { __index = DataSheetManager.TrackerData:GetDataByID(trackerID)[tableName][tableIndex]}) tableList[tableIndex] = dataTable end if DataSheetUtil.IsColumnFP("TrackerData", columnName, tableName) then value = FP.newV1(value) end dataTable[columnName] = value else if DataSheetUtil.IsColumnFP("TrackerData", columnName) then value = FP.newV1(value) end overrideTrackerData[columnName] = value end --]] self:_OverrideDataCell("TrackerData", self.overrideTrackerDataDic, trackerID, columnName, value, tableIndex, tableName) end function RecordComponent:AfterAttackEnter(skillData) if skillData.ID == skillData.BelongTo then self.lastBelongToSkillID = skillData.ID --记录最近一次使用的技能ID(仅限BelongTo等于自身ID的技能) end end return RecordComponent