HeroPlugin.lua 15.6 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
local HeroPlugin = {}


function HeroPlugin.bind(Hero)

	function Hero:mylog(contents)
		contents = contents or {}
		if contents["cint1"] or contents["cint2"] or contents["cint3"] then
			print("heroLog error log have cint1 or cint2 or cint3 ", debug.traceback())
		end
		contents["cint1"] = self:getProperty("id")
		contents["cint2"] = self:getProperty("type")

		self.owner:mylog("hero_action", contents)
	end

	function Hero:getMaxLevel()
		return math.min(#csvdb["unit_expCsv"], csvdb["unit_breakCsv"][self:getProperty("breakL")].levelLimit)
	end


	-- 纯% 的属性
	local PercentAttr = {
		crit = 6, 			-- 暴击
		critHurt = 8, 		-- 暴伤
		vampire = 9, 		-- 吸血
		pierce = 10, 		-- 穿透
	}
	-- base 原, add 增加值 ,atype 增加类型(0 值 1%)
	local function addAttr(base, add, atype, attrName)
		base = base or 0
		add = add or 0
		if PercentAttr[attrName] then
			atype = 0
		end
		if atype == 1 then
			return base * add / 100
		else
			return add
		end
	end

	--角色自身 = 初始 *(1+升级)*(1+突破)*(1+觉醒)+ 天赋升级 + 天赋阶段
	function Hero:getBaseAttrs(params)
		params = params or {}
		local unitData  = csvdb["unitCsv"][self:getProperty("type")]
		local level = params.level or self:getProperty("level")
		local breakL = params.breakL or self:getProperty("breakL")
		local wakeL = params.wakeL or self:getProperty("wakeL")
		local talent = params.talent or self:getProperty("talent")
		local heroCfgId = self:getProperty("type")
		--天赋
		local talentAttrS = {}

		-- 四个基础属性
		local cfgName = "unit_talent_"..heroCfgId.."Csv"
		local curRank = talent:getv(0, 1)
		local curLv = talent:getv(1,1) - 1
		for i, value in ipairs(csvdb[cfgName]) do
			if i <= curRank then
				for lv, cfg in ipairs(value) do
					if i < curRank or lv <= curLv then
						if cfg.effect ~= 99 then
							if not talentAttrS[cfg.effect] then
								talentAttrS[AttsEnumEx[cfg.effect]] = 0
							end
							talentAttrS[AttsEnumEx[cfg.effect]] = cfg.strength
						end
					else
						break
					end
				end
			else
				break
			end
		end
		
		for _, attrName in pairs(AttsEnumEx) do
			if talentAttrS[attrName] then
				talentAttrS[attrName] = addAttr(unitData[attrName], talentAttrS[attrName], 1, attrName)
			end
		end

		-- 信赖属性
		local faithAttr = {}
		local faith = self:getProperty("faith")
		local faithConfig = csvdb["unit_trustCsv"]
		for lvl = 1, #faithConfig do
			if faith >= faithConfig[lvl].exp then
				local add = faithConfig[lvl]["position_"..unitData.position]:toArray(true, "=")
				faithAttr[AttsEnumEx[add[1]]] = (faithAttr[AttsEnumEx[add[1]]] or 0) + add[2]
			end
		end
		for _, attrName in pairs(AttsEnumEx) do
			if faithAttr[attrName] then
				faithAttr[attrName] = addAttr(unitData[attrName], faithAttr[attrName], 1, attrName)
			end
		end

		local attrs = {}
		for _, attName in pairs(AttsEnumEx) do
			attrs[attName] = unitData[attName] or 0
		end
		--升级、突破、觉醒
		local lData = csvdb["unit_expCsv"][level]
		local blData = csvdb["unit_breakCsv"][breakL]
		local wData = csvdb["unit_wakeCsv"][wakeL]
		for attr, value in pairs(attrs) do
			attrs[attr] = attrs[attr] + addAttr(attrs[attr], lData[attr .. "Level"], 1, attr)
			attrs[attr] = attrs[attr] + addAttr(attrs[attr], blData[attr .. "Level"], 1, attr)
			attrs[attr] = attrs[attr] + addAttr(attrs[attr], wData[attr .. "Level"], 1, attr) + (talentAttrS[attr] or 0) + (faithAttr[attr] or 0)
		end

		return attrs
	end


	--当前属性 = 角色属性值 * (1 + 装备套装(百分比) + 铭文套装(百分比))+ (装备(固定)+ 铭文(固定))
	function Hero:getTotalAttrs(params)
		params = params or {}
		local attrs = self:getBaseAttrs()
		-- 装备零件
		local equipAttrs = self:getRuneEquipAttrs()
		local sparkAttrs = self:getSparkAttrs()

		for _, attName in pairs(AttsEnumEx) do
			attrs[attName] = attrs[attName] or 0
			attrs[attName] = attrs[attName] + addAttr(attrs[attName], equipAttrs.percent[attName], 1, attName)
			attrs[attName] = attrs[attName] + addAttr(attrs[attName], equipAttrs.value[attName], 0, attName)
			attrs[attName] = attrs[attName] + addAttr(attrs[attName], sparkAttrs[attName], 0, attName)
		end

		-- 羁绊加成
	   --  if params.activeRelation then
	   --      for k, attName in pairs(AttsEnumEx) do
				-- attrs[attName] = attrs[attName] + addAttr(attrs[attName], params.activeRelation[attName], 1, attName)
	   --      end
	   --  end
		return attrs
	end

	-- 当前零件和装备增加属性
	function Hero:getRuneEquipAttrs()
		local attrs = {value = {}, percent = {}}
		for _, attName in pairs(AttsEnumEx) do
			attrs.value[attName] = 0
			attrs.percent[attName] = 0
		end
		local equipSuits = {}
		-- 装备效果
		for typ,level in pairs(self:getProperty("equip"):toNumMap()) do
			if level > 0 then
				local data = csvdb["equipCsv"][typ][level]
				for k,v in pairs(data.attr1:toNumMap()) do
					attrs.value[AttsEnumEx[k]] = attrs.value[AttsEnumEx[k]] + v
				end
				for k,v in pairs(data.attr2:toNumMap()) do
					attrs.value[AttsEnumEx[k]] = attrs.value[AttsEnumEx[k]] + v
				end
				if data.suit ~= "" then
					if not equipSuits[data.suit] then equipSuits[data.suit] = {} end
					table.insert(equipSuits[data.suit], data)
				end
			end
		end
		-- 装备套装效果
		for suitId,eDatas in pairs(equipSuits) do
			local suitCsv = csvdb["equip_suitCsv"][tonumber(suitId)]
			if suitCsv then 
				local effects = suitCsv.effect:toTableArray(true)
				local count = #eDatas
				if count >= 2 then
					attrs.percent[AttsEnumEx[effects[1][1]]] = attrs.percent[AttsEnumEx[effects[1][1]]] + effects[1][2]
				end
				if count >= 3 then
					attrs.percent[AttsEnumEx[effects[2][1]]] = attrs.percent[AttsEnumEx[effects[2][1]]] + effects[1][2]
				end
				if count >= 4 then
					attrs.percent[AttsEnumEx[effects[3][1]]] = attrs.percent[AttsEnumEx[effects[3][1]]] + effects[3][2]
				end
			end
		end
		-- 零件效果
	    local suits = {}
	    for _, uid in pairs(self:getProperty("rune"):toNumMap()) do
	        if uid > 0 then
	            local rune = self.owner.runeBag[uid]
                if not rune then
                    skynet.error(string.format("rune not exist,uid:%s,hero:%s,roleId:%s", uid, self:getProperty("id"), self:getProperty("roleid")))
                else
                    local csvData = csvdb["runeCsv"][rune:getProperty("type")][rune:getProperty("id")]
                    local runeRareData = csvdb["rune_rareCsv"][csvData.rarity]
                    local buildData = csvdb["rune_buildCsv"][rune:getProperty("level")]
                    for k, v in pairs(rune:getProperty("attrs"):toNumMap()) do
                        local attName = AttsEnumEx[k]
                        --零件的加成属性有特殊需求 填的是 10倍的值
                        --rare的effect不影响 特殊属性

                        --铭文单件普通属性=attr*(1+[rune_build表effect]/100*[rune_rare表effect]/100)
                        --铭文单件特殊属性=attr+[rune_build表effect]

                        local effect = buildData[attName]
                        if not PercentAttr[attName] then
                            effect = buildData[attName] * runeRareData.effect / 100
                        end
                        attrs.value[attName] = attrs.value[attName] + (v / 100) + addAttr(v / 100, effect, 1, attName)
                    end
                    
                    if not suits[csvData.suit] then suits[csvData.suit] = {} end
                    table.insert(suits[csvData.suit],csvData)
                end
	        end
	    end
		-- 零件套装效果
		for suitId,runeDatas in pairs(suits) do
			local suitCsv = csvdb["rune_suitCsv"][tonumber(suitId)]
			if suitCsv then
				local effects = suitCsv.effect:toTableArray(true)
				local count = #runeDatas
				if count >= 2 and AttsEnumEx[effects[1][1]]then
					attrs.percent[AttsEnumEx[effects[1][1]]] = attrs.percent[AttsEnumEx[effects[1][1]]] + effects[1][2]
				end
				if count >= 4 and AttsEnumEx[effects[2][1]] then
					attrs.percent[AttsEnumEx[effects[2][1]]] = attrs.percent[AttsEnumEx[effects[2][1]]] + effects[2][2]
				end
				if count >= 6 and AttsEnumEx[effects[3][1]] then
					attrs.percent[AttsEnumEx[effects[3][1]]] = attrs.percent[AttsEnumEx[effects[3][1]]] + effects[3][2]
				end
			end
		end
		return attrs
	end

	function Hero:getSparkAttrs()
		local attrs = {}
		for _, attName in pairs(AttsEnumEx) do
			attrs[attName] = 0
		end
		for _, data in pairs(self:getProperty("spark") or {}) do
			for k, v in pairs(data.attrs) do
				attrs[AttsEnumEx[k]] = attrs[AttsEnumEx[k]] + v
			end
		end
		return attrs
	end


	-- 战斗力(当前属性)= POWER[(生命 + 防御 * 7 + 闪避 * 4)*(攻击*4 + 命中 * 2)*(1 + 暴击几率/100 * 暴击伤害/100)* 攻击速度 / 60000 ,0.8 ]
	-- function Hero:getBattleValue(activeRelation) -- isReal包括队伍加成
	function Hero:getBattleValue() -- isReal包括队伍加成
	    -- local attrs = self:getTotalAttrs({activeRelation = activeRelation})
	    local attrs = self:getTotalAttrs()
	    local battleValue = ((attrs["hp"] + attrs["def"] * 7 + attrs["miss"] * 4) * (attrs["atk"] * 4 + attrs["hit"] * 2) * (1 + attrs["crit"]/100 * attrs["critHurt"]/100) * attrs["atkSpeed"] / 600000) ^ 0.8
	    return math.floor(battleValue)
	end

	function Hero:saveBattleValue()
		local battleValue = self:getBattleValue()
		if battleValue ~= self:getProperty("battleV") then
			self:setProperty("battleV", battleValue)
		end
		return battleValue
	end

	-- 技能1234 对应必杀技,冒险技,被动技,战斗技
	function Hero:getSkillLevel(idx)
		local level = 1
		for wakeL = 1, self:getProperty("wakeL") do
			local wakeData = csvdb["unit_wakeCsv"][wakeL]
			for _, slot in ipairs(wakeData.skill:toArray(true,"=")) do
				if slot == idx then
					level = level + 1
				end
			end
		end
		return level
	end

	-- 天赋获得的技能
	function Hero:getTalentSkill()
		local TalentEnum = {
			[1] = 1,			-- 血量
			[2] = 2,			-- 攻击
			[3] = 3,			-- 物理防御
			[4] = 4,			-- 命中
			[5] = 5, 			-- 闪避
		}
	    local talentCsv = csvdb["unit_talent_" .. self:getProperty("type") .. "Csv"]
	    local curLv = self:getProperty("talent"):getv(1,1) - 1
	    local curRan = self:getProperty("talent"):getv(0,1)
	    local skills = {}
	    for ran, data in ipairs(talentCsv) do
	        if ran <= curRan then
	            for lv, value in ipairs(data) do
	                if ran < curRan or lv <= curLv then
	                    if not TalentEnum[value.effect] then
	                        skills[value.strength] = true
	                    end
	                else
	                    break
	                end
	            end
	        else
	            break
	        end
	    end
	    return skills
	end

	function Hero:getSkillData(idx)
		local unitData = csvdb["unitCsv"][self:getProperty("type")]
		if idx == 1 then
			return csvdb["skill_specialCsv"][unitData.special]
		elseif idx == 2 then
			return csvdb["adv_battle_specialCsv"][unitData.adv]
		elseif idx == 3 then
			return csvdb["skill_passiveCsv"][unitData.passive]
		elseif idx == 4 then
			return csvdb["skill_blockCsv"][unitData.block]
		end
		return {}
	end

	function Hero:getRunes()
	    local rune = self:getProperty("rune")
	    if not rune or rune == "" then
	        rune = "1=0 2=0 3=0 4=0 5=0 6=0"
	    end
	    local result = rune:toNumMap()
	    for i = 1, 6 do
	        if not result[i] then
	            result[i] = 0
	        end
	    end
	    return result
	end

	-- 101 冒险战斗被动技
	-- 102 挂机战斗被动技
	function Hero:getRuneSkill(skillType)
	    local suits = {}
	    for _,uid in pairs(self:getRunes()) do
	        if uid > 0 then
	            local runeData = self.owner.runeBag[uid]
	            if not runeData then return  end
	            local csvData = csvdb["runeCsv"][runeData:getProperty("type")][runeData:getProperty("id")]
	            if not suits[csvData.suit] then suits[csvData.suit] = {} end
	            table.insert(suits[csvData.suit],csvData)
	        end
	    end

	    for suitId,runes in pairs(suits) do
	        local suitCsv = csvdb["rune_suitCsv"][tonumber(suitId)]
	        if not suitCsv then return  end
	        local effects = suitCsv.effect:toTableArray(true)
	        local count = #runes
	        if count >= 2 and effects[1][1] == skillType then
	            return effects[1][2]
	        end
	        if count >= 4 and effects[2][1] == skillType then
	            return effects[2][2]
	        end
	        if count >= 6 and effects[3][1] == skillType then
	            return effects[3][2]
	        end
	    end
	    return
	end

	-- 添加英雄信赖
	function Hero:addHeroFaith(exp)
		local faith = self:getProperty("faith")
		local config = csvdb["unit_trustCsv"]
		local star = self:getProperty("wakeL")
		local tmpExp = faith + exp
		for lvl = 1, #config do
			if star < config[lvl].star then
				break
			end
			if tmpExp < config[lvl].exp then
				faith = tmpExp
				break
			else
				faith = config[lvl].exp
			end
		end
		self:setProperty("faith", faith)
		self:mylog({desc = "addFaith", int1 = exp})
	end

	--检验天赋树是否合理
	function Hero:checkGeniusTree(genius)
		local maxWakeL = 0
		local star = self:getProperty("wakeL")
		if star < 4 then return maxWakeL end
		if #genius == 0 then return maxWakeL end

		local geniusTree = genius:toNumMap()
		local tmpgenius = ""
		for wakeL, val in pairs(geniusTree) do
			if wakeL < 4 then return maxWakeL end
			if wakeL % 2 == 0 then
				if geniusTree[wakeL+1] and geniusTree[wakeL+1] ~= val then
					return 0, 0, tmpgenius
				end
			end
			maxWakeL = math.max(maxWakeL, wakeL)
			if #tmpgenius == 0 then
				tmpgenius = string.format("%s=%s", tostring(wakeL), tostring(val))
			else
				tmpgenius = string.format("%s %s=%s", tmpgenius, tostring(wakeL), tostring(val))
			end
		end
		return tonumber(maxWakeL), tonumber(geniusTree[maxWakeL]), tmpgenius
	end

	function Hero:increGeniusTree()
		local genius = self:getProperty("genius")
		local wakeL = self:getProperty("wakeL")
		local maxWakeL, awake
		maxWakeL, awake, genius = self:checkGeniusTree(genius)
		if maxWakeL >= 4 and wakeL > maxWakeL and maxWakeL % 2 == 0 then
			maxWakeL = maxWakeL + 1
			if #genius == 0 then
				genius = string.format("%s=%s", tostring(maxWakeL), tostring(awake))
			else
				genius = string.format("%s %s=%s", genius, tostring(maxWakeL), tostring(awake))
			end
		end
		return genius
	end

	function Hero:resetGeniusTree()
		local unit_starTalent_reset = globalCsv["unit_starTalent_reset"]
		local cost = unit_starTalent_reset:toNumMap()
		if not self.owner:checkItemEnough(cost) then return false end

		self.owner:costItems(cost, {log = {desc = "heroGenius", int1 = self:getProperty("id"), int2 = self:getProperty("type")}})
		return true
	end

	function Hero:saveGeniusTree(wakeL, awake)
		local genius = self:getProperty("genius")
		local typ = self:getProperty("type")
		local curWakeL = self:getProperty("wakeL")
		if not wakeL or not awake then
			if self:resetGeniusTree() == true then return "" end
			return genius
		end

		local heroUnit = csvdb["unitCsv"][typ]
		if not heroUnit then return genius end
		if not heroUnit.awake_1 or not heroUnit.awake_2 then return genius end

		if #genius == 0 then
			genius = string.format("%s=%s", tostring(wakeL), tostring(awake))
		else
			genius = string.format("%s %s=%s", genius, tostring(wakeL), tostring(awake))
		end

		local maxWakeL
		maxWakeL, _, genius = self:checkGeniusTree(genius)
		if maxWakeL == 0 then
			genius = self:getProperty("genius")
		else
			if curWakeL > wakeL and wakeL % 2 == 0 then --自动升一级,举例,6星设置4星觉醒技能。自动升级到5星
				genius = string.format("%s %s=%s", genius, tostring(wakeL + 1), tostring(awake))
				maxWakeL, _, genius = self:checkGeniusTree(genius)
			end
		end
		return genius
	end

end


return HeroPlugin