123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- local asset = require "model.asset"
- local equip = require "model.equip"
- local talent = require "model.talent"
- local logger = require "logger"
- local stringify = require "stringify"
- local RATENUM = 10000
- local function nan_to_zero(value)
- -- 检查值是否为 NaN
- local key = tostring(value)
- if key == "nan" or key == "-nan" then
- return 0
- else
- return value
- end
- end
- local this = {}
- local ENTRY = {
- HP = 1,
- attack = 2,
- spellAttack = 3,
- defense = 4,
- spellDefense = 5,
- attackCrit = 6,
- critNum = 7,
- hit = 8,
- dodge = 9,
- attackSpeed = 10,
- moveSpeed = 11,
- realAttack = 12,
- addRoleHP = 13,
- talAddHP = 14,
- talAddattack = 15,
- talAddspellAttack = 16,
- talAdddefense = 17,
- talAddspellDefense = 18,
- equipAddAttack = 19,
- talAddAllDefense = 20,
- HPRate = 21,
- attackRate = 22,
- spellAttackRate = 23,
- defenseRate = 24,
- spellDefenseRate = 25,
- attackCritRate = 26,
- critNumRate = 27,
- hitRate = 28,
- dodgeRate = 29,
- attackSpeedRate = 30,
- moveSpeedRate = 31,
- realAttackRate = 32,
- }
- do
- local o = {}
- for k, v in pairs(ENTRY) do
- o[v] = k
- end
- setmetatable(ENTRY, {__index = o})
- end
- local function toFixed(a, b)
- local num = 10 ^ b
- local ret = math.floor(a * num + 0.5)/num
- return ret
- end
- function this.buildIBaseAttr(cfg, isZero)
- local baseAttr = {
- HP= isZero and 0 or cfg.HP,
- attack= isZero and 0 or cfg.attack,
- spellAttack= isZero and 0 or cfg.spellAttack,
- realAttack= isZero and 0 or cfg.realAttack,
- defense= isZero and 0 or cfg.defense,
- spellDefense= isZero and 0 or cfg.spellDefense,
- attackSpeed= isZero and 0 or cfg.attackSpeed,
- attackCrit= isZero and 0 or cfg.attackCrit,
- critNum= isZero and 0 or cfg.critNum,
- hit= isZero and 0 or cfg.hit,
- dodge= isZero and 0 or cfg.dodge,
- moveSpeed= isZero and 0 or cfg.moveSpeed,
- }
- return baseAttr
- end
- function this.entryBaseAttrAdd(baseAttr, entryID)
- local EntryConfig = asset.EntryConfig_proto
- for _, id in ipairs(entryID) do
- local entryCfg = EntryConfig[id]
- if entryCfg.type >= ENTRY.HP and entryCfg.type <= ENTRY.realAttack then
- local key = ENTRY[entryCfg.type]
- baseAttr[key] = baseAttr[key] + entryCfg.parmArr[1]
- end
- if entryCfg.type == ENTRY.talAddAllDefense then
- baseAttr.defense = baseAttr.defense + entryCfg.parmArr[1]
- baseAttr.spellDefense = baseAttr.spellDefense + entryCfg.parmArr[1]
- end
- end
- end
- function this.initTalentAdd(character)
- local talent_data = talent.get_talent_data(character)
- local EntryConfig = asset.EntryConfig_proto
- local TalentConfig = asset.TalentConfig_proto
- local profession_entrys = {}
- local all_entrys = {}
- local addAllAttrRateArr = {
- [ENTRY.talAddHP] = ENTRY.HP,
- [ENTRY.talAddattack] = ENTRY.attack,
- [ENTRY.talAddspellAttack] = ENTRY.spellAttack,
- [ENTRY.talAdddefense] = ENTRY.defense,
- [ENTRY.talAddspellDefense] = ENTRY.spellDefense,
- }
- for _, talent_conf in pairs(TalentConfig) do
- local data = talent_data[talent_conf.talentType]
- if data and data.id >= talent_conf.ID then
- local conf = EntryConfig[talent_conf.entryID]
- if conf and conf.type then
- if addAllAttrRateArr[conf.type] then
- table.insert(all_entrys, talent_conf.entryID)
- else
- for _, v in ipairs(conf.profession) do
- profession_entrys[v] = profession_entrys[v] or {}
- table.insert(profession_entrys[v], talent_conf.entryID)
- end
- end
- end
- end
- end
- local talentAdds = {}
- local EntryConfig = asset.EntryConfig_proto
- for i = 1, 6 do
- local talentAdd = this.buildIBaseAttr(nil, true)
- local entryIDs = profession_entrys[i] or {}
- this.entryBaseAttrAdd(talentAdd, entryIDs)
- for _, id in ipairs(all_entrys) do
- local entryCfg = EntryConfig[id]
- local key = addAllAttrRateArr[entryCfg.type]
- if key and ENTRY[key] then
- talentAdd[ENTRY[key]] = talentAdd[ENTRY[key]] * (1+ entryCfg.rateArr[1] /RATENUM)
- end
- end
- talentAdds[i] = talentAdd
- end
- return talentAdds
- end
- function this.changeBaseAttr(baseAttr, changeAttr, isAdd)
- baseAttr.HP = isAdd and baseAttr.HP + changeAttr.HP or changeAttr.HP
- baseAttr.attack = isAdd and baseAttr.attack + changeAttr.attack or changeAttr.attack
- baseAttr.attackSpeed = isAdd and baseAttr.attackSpeed + changeAttr.attackSpeed or changeAttr.attackSpeed
- baseAttr.attackCrit = isAdd and baseAttr.attackCrit + changeAttr.attackCrit or changeAttr.attackCrit
- baseAttr.critNum = isAdd and baseAttr.critNum + changeAttr.critNum or changeAttr.critNum
- baseAttr.defense = isAdd and baseAttr.defense + changeAttr.defense or changeAttr.defense
- baseAttr.dodge = isAdd and baseAttr.dodge + changeAttr.dodge or changeAttr.dodge
- baseAttr.hit = isAdd and baseAttr.hit + changeAttr.hit or changeAttr.hit
- baseAttr.spellAttack = isAdd and baseAttr.spellAttack + changeAttr.spellAttack or changeAttr.spellAttack
- baseAttr.spellDefense = isAdd and baseAttr.spellDefense + changeAttr.spellDefense or changeAttr.spellDefense
- baseAttr.realAttack = isAdd and baseAttr.realAttack + changeAttr.realAttack or changeAttr.realAttack
- baseAttr.moveSpeed = isAdd and baseAttr.moveSpeed + changeAttr.moveSpeed or changeAttr.moveSpeed
- return baseAttr
- end
- function this.buildIEquip(equip)
- local ArmorConfig = asset.ArmorConfig_proto
- local curCfg = ArmorConfig[equip.id]
- if (equip.id > 0 and not curCfg) then
- return
- end
- local baseAttr = this.buildIBaseAttr(curCfg)
- --等级加成为固定值
- local lvAddAttr = {"HP", "attack", "spellAttack"}
- for _, attr in ipairs(lvAddAttr) do
- if (baseAttr[attr] and baseAttr[attr] > 0) then
- baseAttr[attr] = baseAttr[attr] + (equip.lv - 1) * curCfg.increaseLv
- end
- end
- baseAttr.entry = curCfg.entry
- return baseAttr
- end
-
- function this.setIBaseAttr(obj, cfg, lvAdd, equips, talentAdd)
- --装备加成
- local attr = this.buildIBaseAttr(nil, true) or {}
- local allEntryArr = {}
- if equips then
- for _, data in pairs(equips) do
- local add_attr = this.buildIEquip(data)
- if add_attr then
- this.changeBaseAttr(attr, add_attr, true)
- if add_attr.entry > 0 then
- table.insert(allEntryArr, add_attr.entry)
- end
- end
- end
- end
- obj.HP = (cfg.HP or 0) * lvAdd + attr.HP
- obj.attack = (cfg.attack or 0) * lvAdd + attr.attack
- obj.attackSpeed = (cfg.attackSpeed or 0) * lvAdd + attr.attackSpeed
- obj.attackCrit = (cfg.attackCrit or 0) * lvAdd + attr.attackCrit
- obj.critNum = (cfg.critNum or 0) * lvAdd + attr.critNum
- obj.defense = (cfg.defense or 0) * lvAdd + attr.defense
- obj.dodge = (cfg.dodge or 0) * lvAdd + attr.dodge
- obj.hit = (cfg.hit or 0) * lvAdd + attr.hit
- obj.spellAttack = (cfg.spellAttack or 0) * lvAdd + attr.spellAttack
- obj.spellDefense = (cfg.spellDefense or 0) * lvAdd + attr.spellDefense
- obj.realAttack = (cfg.realAttack or 0) * lvAdd + attr.realAttack
- obj.moveSpeed = (cfg.moveSpeed or 0) + (attr.moveSpeed or 0)
- if obj.hero then
- local profession = cfg.profession
- if(talentAdd and talentAdd[profession]) then
- this.changeBaseAttr(obj, talentAdd[profession], true)
- end
- end
- local EntryConfig = asset.EntryConfig_proto
- -- 所有角色卡牌基础属性万分比词条加成
- for _, entry in ipairs(allEntryArr) do
- if entry == ENTRY.addRoleHP then
- obj.HP = obj.HP * (1 + EntryConfig[entry].rateArr[1] / RATENUM)
- elseif entry == ENTRY.equipAddAttack then
- obj.attack = obj.attack * (1 + EntryConfig[entry].rateArr[1] / RATENUM)
- end
- end
- obj.HP = math.floor(obj.HP)
- obj.attack = math.floor(obj.attack)
- obj.attackSpeed = math.floor(obj.attackSpeed)
- obj.attackCrit = math.floor(obj.attackCrit)
- obj.critNum = math.floor(obj.critNum)
- obj.defense = math.floor(obj.defense)
- obj.dodge = math.floor(obj.dodge)
- obj.hit = math.floor(obj.hit)
- obj.spellAttack = math.floor(obj.spellAttack)
- obj.spellDefense = math.floor(obj.spellDefense)
- obj.realAttack = math.floor(obj.realAttack)
- obj.moveSpeed = math.floor(obj.moveSpeed)
- end
- function this.getPowerByAttr(obj)
- local defenseCoe = toFixed((1 / toFixed((1 - obj.defense / (obj.defense + 325)), 2)), 2)
- -- 法术防御系数 1 - 法术防御/(法术防御+防御常数)
- local spellDefenseCoe = toFixed((1 / toFixed((1 - obj.spellDefense / (obj.spellDefense + 325)), 2)), 2)
- --攻速系数 攻速/比例值
- local attackSpeedCoe = toFixed((obj.attackSpeed / RATENUM), 2)
- --暴击系数 暴击伤害倍数/比例值 * 暴击率/比例值 * 2
- local critCoe = toFixed((obj.critNum / RATENUM), 2) * toFixed((obj.attackCrit / RATENUM), 2)* 2
- --命中系数 1/攻击CD/比例值 * 命中率/比例值
- local hitCoe = toFixed((1 / toFixed((obj.attackSpeed / RATENUM), 2)), 2) * toFixed((obj.hit / RATENUM), 2)
- --闪避系数 1/(1-闪避率/比例值)
- local dodgeCoe = toFixed((1 / toFixed((1 - obj.dodge / RATENUM), 2)), 2)
-
- defenseCoe = nan_to_zero(defenseCoe)
- spellDefenseCoe = nan_to_zero(spellDefenseCoe)
- attackSpeedCoe = nan_to_zero(attackSpeedCoe)
- critCoe = nan_to_zero(critCoe)
- hitCoe = nan_to_zero(hitCoe)
- dodgeCoe = nan_to_zero(dodgeCoe)
- -- logger.trace(defenseCoe)
- -- logger.trace(spellDefenseCoe)
- -- logger.trace(attackSpeedCoe)
- -- logger.trace(critCoe)
- -- logger.trace(hitCoe)
- -- logger.trace(dodgeCoe)
- -- logger.trace(stringify(obj))
- obj.power =
- obj.attack * (1 + attackSpeedCoe + critCoe + hitCoe) * 2 +
- obj.spellAttack * (1 + attackSpeedCoe + critCoe + hitCoe) * 2 +
- obj.HP * (1 + defenseCoe + spellDefenseCoe + dodgeCoe) * 0.8
- --取地板值
- obj.power = math.floor(obj.power)
- return obj.power
- end
- function this.buildIRole(character, hero)
- local RoleConfig = asset.RoleConfig_proto
- local iRole = {}
- if hero.id > 0 and not RoleConfig[hero.id] then
- return 0
- end
- local baseAttr = this.buildIBaseAttr(RoleConfig[hero.id])
- local talents = this.initTalentAdd(character)
- iRole = {
- cfg = RoleConfig[hero.id],
- hero = hero,
- power = 0,
- equips = {},
- }
- setmetatable(iRole, {__index = baseAttr})
- for k, sid in pairs(hero.equip or {}) do
- if sid and sid ~= "" then
- local equip_data = equip.equip_get(character, sid)
- if equip_data then
- iRole.equips[k] = equip_data
- end
- end
- end
- -- logger.trace(stringify(iRole.equips))
- --比例值(万分比)
- --等级加成 1 + 等级/100
- local lvAdd = 1 + toFixed(((iRole.hero.lv - 1) / 100), 2)
- this.setIBaseAttr(iRole, iRole.cfg, lvAdd, iRole.equips, talents)
- -- 物理防御系数 1 - 物理防御/(物理防御+防御常数)
- return this.getPowerByAttr(iRole)
- end
- function this.buildICard(character, card)
- local iCard
- local CardSkillConfig = asset.CardSkillConfig_proto
- if (card.id > 0 and not CardSkillConfig[card.id]) then
- return 0
- end
- local baseAttr = this.buildIBaseAttr(CardSkillConfig[card.id])
- iCard = {
- cfg= CardSkillConfig[card.id],
- card= card,
- power= 0,
- }
- -- -- -----卡牌战斗力不受装备,天赋加成----
- --等级加成 1 + 等级/比例值
- local lvAdd = 1 + toFixed(((iCard.card.lv - 1) / 100), 2)
- this.setIBaseAttr(iCard, iCard.cfg, lvAdd)
- return this.getPowerByAttr(iCard)
- end
- return {build_role = this.buildIRole, build_card = this.buildICard}
|