Dagot_Prolaps Опубликовано 21 июля, 2019 Жалоба Поделиться Опубликовано 21 июля, 2019 https://www.nexusmods.com/morrowind/mods/46993?tab=description Улучшатель боя для МВСЕ, основан на луа-скриптах.Надо основательно потестить, возможно удастся интуитивно постичь механизм скриптов, чтобы улучшить их. Ссылка на комментарий Поделиться на другие сайты Поделиться
Scarab-Phoenix Опубликовано 22 июля, 2019 Жалоба Поделиться Опубликовано 22 июля, 2019 100% chance to hitОго, как реалистично, прям новое поколение. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 30 июля, 2019 Автор Жалоба Поделиться Опубликовано 30 июля, 2019 Я понемногу продираюсь через все те дебри кода, который он понаворотил. То что должно было поместиться в одном файле, он разнёс на целых 8 разных файлов. Синтаксис жуткий, читать надо с конца к началу, повсюду перекрёстные ссылки с середины одного файла на функцию где-то в жопе совсем другого файла, да ещё и не ясно где то что делает сама игра, а где то что добавляет скрипт. В общем без литра древнего бренди Дагот не разобраться.Однако потихоньку картина начинает вырисовываться. Я уже смог отменить 100% шанс попасть, не ломая логику самого скрипта. В дальнейшем перспективы таковы, что раскурочив как следует этот мод, я смогу не только модифицировать урон для каждого типа оружия с блекджеком и критами, но и добавить по автоматическому прокасту какого-нибудь баффа на атакующего и дебаффа на поражённого (в виде спеллов) при каждой успешной атаке. Основное ядро мода: --local version = 1.0 -- moduleslocal common = require('ngc.common')local multistrikelocal criticallocal bleedlocal stunlocal momentumlocal attackBonusSpell = "ngc_ready_to_strike" -- set up the always hit spell for playerlocal function updatePlayer(e) if not mwscript.getSpellEffects({reference = tes3.player, spell = attackBonusSpell}) then mwscript.addSpell({reference = tes3.player, spell = attackBonusSpell}) endend -- set up the always hit spell for NPCslocal function onActorActivated(e) local hasSpell = mwscript.getSpellEffects({reference = e.reference, spell = attackBonusSpell}) if not hasSpell then mwscript.addSpell({reference = e.reference, spell = attackBonusSpell}) if common.showDebugMessages then tes3.messageBox({ message = "Adding ready to strike to " .. e.reference.id }) end endend -- clean up after combatlocal function onCombatEnd(e) if (e.actor.reference == tes3.player) then -- reset multistrike counters common.multistrikeCounters = {} common.currentArmorCache = {} -- remove expose weakness on all currently exposed for targetId,spellId in pairs(common.currentlyExposed) do mwscript.removeSpell({reference = targetId, spell = spellId}) end common.currentlyExposed = {} -- remove all bleeds and cancel all timers for targetId,_ in pairs(common.currentlyBleeding) do common.currentlyBleeding[targetId].timer:cancel() end common.currentlyBleeding = {} endend local function damageMessage(damageType, damageDone) if common.config.showMessages then local msgString = damageType if (common.config.showDamageNumbers and damageDone) then msgString = msgString .. " Extra damage: " .. math.round(damageDone, 2) end tes3.messageBox({ message = msgString }) endend -- core damage featureslocal function attackBonusMod(attackBonus) return (((attackBonus - 10) * common.config.attackBonusModifier) / 100)end local function coreBonusDamage(damage, weaponoSkillLevel, attackBonus) local damageMod -- modify damage for weapon skill bonus local weaponSkillMod = ((weaponoSkillLevel * common.config.weaponSkillModifier) / 100) -- modify damage for Fortify Attack bonus local fortifyAttackMod = attackBonusMod(attackBonus) damageMod = damage * (weaponSkillMod + fortifyAttackMod) return damageModend -- vanilla game strength modifierlocal function strengthModifier(physicalDamage, strength) return physicalDamage * (0.5 + (strength / 100))end local function onDamage(e) local attacker = e.attacker local defender = e.mobile local source = e.attackerReference local target = e.reference local sourceActor = attacker local targetActor = defender local damageTaken = e.damage local damageAdded local damageReduced if e.source == 'attack' then if attacker then -- roll for blind first if attacker.blind > 0 then local missChanceRoll = math.random(100) if attacker.blind >= missChanceRoll then -- you blind, you miss if (common.config.showMessages and source == tes3.player) then tes3.messageBox({ message = "Missed!" }) end -- no damage return end end end if defender then -- reduction from sanctuary local scantuaryMod = (((defender.agility.current + defender.luck.current) - 30) * common.config.sanctuaryModifier) / 100 local reductionFromSanctuary if (scantuaryMod >= 0.1) then reductionFromSanctuary = (defender.sanctuary * scantuaryMod) / 100 else reductionFromSanctuary = (defender.sanctuary * 0.1) / 100 -- minimum sanctuary reduction end if reductionFromSanctuary then damageReduced = damageTaken * reductionFromSanctuary damageTaken = damageTaken - damageReduced end end if attacker then -- core damage values local weapon = e.attacker.readiedWeapon local sourceAttackBonus = sourceActor.attackBonus if attacker.actorType == 0 then -- standard creature bonus local fortifyAttackMod = attackBonusMod(sourceAttackBonus) local creatureStrengthMod = ((sourceActor.strength.current * common.config.creatureBonusModifier) / 100) damageAdded = damageTaken * (fortifyAttackMod + creatureStrengthMod) elseif weapon then -- handle player/NPC attacks if weapon.object.type > 8 then -- ranged hit local weaponSkill = sourceActor.marksman.current -- core bonus damage for ranged hits damageAdded = coreBonusDamage(damageTaken, weaponSkill, sourceAttackBonus) elseif weapon.object.type > 6 then -- axe local weaponSkill = sourceActor.axe.current damageAdded = coreBonusDamage(damageTaken, weaponSkill, sourceAttackBonus) if common.config.toggleWeaponPerks then local damageDone = bleed.perform(damageTaken, target, targetActor, weaponSkill) if (damageDone ~= nil and source == tes3.player) then damageMessage("Bleeding!", damageDone) end end elseif weapon.object.type > 5 then -- spear local weaponSkill = sourceActor.spear.current damageAdded = coreBonusDamage(damageTaken, weaponSkill, sourceAttackBonus) if common.config.toggleWeaponPerks then local damageDone = momentum.perform(damageTaken, source, sourceActor, targetActor, weaponSkill) if damageDone ~= nil then if (source == tes3.player and common.config.showDamageNumbers) then damageMessage("Momentum!", damageDone) end damageAdded = damageAdded + damageDone end end elseif weapon.object.type > 2 then -- blunt local weaponSkill = sourceActor.bluntWeapon.current local stunned local damageDone damageAdded = coreBonusDamage(damageTaken, weaponSkill, sourceAttackBonus) if common.config.toggleWeaponPerks then stunned, damageDone = stun.perform(damageTaken, target, targetActor, weaponSkill) if (stunned and source == tes3.player) then damageMessage("Stunned!", damageDone) elseif (source == tes3.player and common.config.showDamageNumbers) then -- just show extra damage for blunt weapon if no stun damageMessage("", damageDone) end damageAdded = damageAdded + damageDone end elseif weapon.object.type > 0 then -- long blade local weaponSkill = sourceActor.longBlade.current damageAdded = coreBonusDamage(damageTaken, weaponSkill, sourceAttackBonus) if common.config.toggleWeaponPerks then common.multistrikeCounters = multistrike.checkCounters(source.id) if common.multistrikeCounters[source.id] == 3 then local damageDone = multistrike.perform(damageTaken, source, weaponSkill) common.multistrikeCounters[source.id] = 0 if source == tes3.player then damageMessage("Multistrike!", damageDone) end damageAdded = damageAdded + damageDone end end elseif weapon.object.type > -1 then -- short blade local weaponSkill = sourceActor.shortBlade.current damageAdded = coreBonusDamage(damageTaken, weaponSkill, sourceAttackBonus) if common.config.toggleWeaponPerks then local damageDone = critical.perform(damageTaken, target, weaponSkill) if damageDone ~= nil then if source == tes3.player then damageMessage("Critical strike!", damageDone) end damageAdded = damageAdded + damageDone end end end end end if damageAdded then -- we already have damageReduced taken into account with damageTaken e.damage = damageTaken + damageAdded if common.config.showDebugMessages then local showReducedDamage = 0 if damageReduced then showReducedDamage = damageReduced end tes3.messageBox({ message = "Final damage: " .. math.round(e.damage, 2) .. ". Reduced: " .. math.round(showReducedDamage, 2) .. ". Added: " .. math.round(damageAdded, 2) }) end elseif damageReduced then -- we don't have any damage added but we still have damage reduced e.damage = e.damage - damageReduced if common.config.showDebugMessages then tes3.messageBox({ message = "Reduced: " .. math.round(damageReduced, 2) }) end end endend local function initialized(e)if tes3.isModActive("Next Generation Combat.esp") then common.loadConfig() -- load modules multistrike = require("ngc.perks.multistrike") critical = require("ngc.perks.critical") bleed = require("ngc.perks.bleed") stun = require("ngc.perks.stun") momentum = require("ngc.perks.momentum") -- register events event.register("loaded", updatePlayer) event.register("cellChanged", updatePlayer) event.register("mobileActivated", onActorActivated) event.register("combatStopped", onCombatEnd) event.register("damage", onDamage) mwse.log("[Next Generation Combat] Initialized version v%d", version) mwse.log(json.encode(common.config, {indent=true}))endendevent.register("initialized", initialized) Ссылка на комментарий Поделиться на другие сайты Поделиться
Муурн Шепард Опубликовано 31 июля, 2019 Жалоба Поделиться Опубликовано 31 июля, 2019 (изменено) То что должно было поместиться в одном файле, он разнёс на целых 8 разных файлов.Нормальная практика в программировании.Синтаксис жуткийLua же. Операторы напомнили мне помесь Pascal и C. Для остального достаточно знать английский язык, чтобы понять, о чем речь.Я уже смог отменить 100% шанс попастьШанс реализован криво, кстати. Если на персонаже висели большие штрафы к атаке или противник очень ловкий и со светочем, то от заклинания на +100 пунктов автоматического попадания не появится. Мне кажется, там стоит улучшить механику с blind'ом. Чтобы ослепленный персонаж получал не только штраф к атаке (как в ванили), но и штраф к защите. Хотя, лучше выпилить этот блок полностью, потому что минус к атаке за слепоту уже учитывается в дефолтной формуле. Изменено 31 июля, 2019 пользователем Муурн Шепард Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 31 июля, 2019 Автор Жалоба Поделиться Опубликовано 31 июля, 2019 (изменено) Мод обновлён, активная блокировка (дожили!) и переделка рукопашного боя.____Боги.... башка закипает!Ну он и понаворотил... Пытаюсь сделать зависимость урона от стамины. Если удастся, то мод можно считать мастхевным. Изменено 31 июля, 2019 пользователем Dagot_Prolaps Ссылка на комментарий Поделиться на другие сайты Поделиться
Муурн Шепард Опубликовано 1 августа, 2019 Жалоба Поделиться Опубликовано 1 августа, 2019 (изменено) А если сделать так? local function damageReductionFromSanctuary(defender, damageTaken) local damageReduced -- reduction from sanctuary local scantuaryMod = (((defender.agility.current + defender.luck.current) - 30) * common.config.sanctuaryModifier) / 100 local reductionFromSanctuary if (scantuaryMod >= 0.1) then reductionFromSanctuary = (defender.sanctuary * scantuaryMod) / 100 else reductionFromSanctuary = (defender.sanctuary * 0.1) / 100 -- minimum sanctuary reduction end if reductionFromSanctuary then damageReduced = damageTaken * reductionFromSanctuary end return damageReduced end local function damageReductionFromFatigue(attacker, damageTaken) local damageReduced -- reduction from fatigue local MaxFatigue = attacker.fatigue.base local CurrentFatigue = attacker.fatigue.current damageReduced = damageTaken - ( CurrentFatigue / MaxFatigue * damageTaken ) tes3.messageBox({ message = "Fatigue Damage Reduction: " .. math.round(damageReduced, 2)}) return damageReduced end if defender and common.config.toggleAlwaysHit then -- reduction from sanctuary local reductionFromSanctuary = damageReductionFromSanctuary(defender, damageTaken) if reductionFromSanctuary then damageTaken = damageTaken - reductionFromSanctuary damageReduced = reductionFromSanctuary end end if attacker and common.config.toggleAlwaysHit then local reductionFromFatigue = damageReductionFromFatigue(attacker, damageTaken) if reductionFromFatigue then damageTaken = damageTaken - reductionFromFatigue damageReduced = reductionfromSanctuary + reductionFromFatigue end end damageAdded = coreBonusDamage(damageTaken, handToHandAttacker.weaponSkill, handToHandAttacker.attackBonus) endСтарые блоки скопировал, чтобы показать, куда совать новые. Изменено 1 августа, 2019 пользователем Муурн Шепард Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 1 августа, 2019 Автор Жалоба Поделиться Опубликовано 1 августа, 2019 Не робит, увы( Бью на нулевой стамине.Сообщения о порезке урона на гигантские суммы (фактически на всю величину урона) появляются, но реальный урон наносится в полном непорезанном объёме. Ссылка на комментарий Поделиться на другие сайты Поделиться
Муурн Шепард Опубликовано 1 августа, 2019 Жалоба Поделиться Опубликовано 1 августа, 2019 (изменено) Поправил на такое. Damage reduced присваивалась локальная переменная из другого блока, могло глючить из-за этого. if attacker and common.config.toggleAlwaysHit then local reductionFromFatigue = damageReductionFromFatigue(attacker, damageTaken) if reductionFromFatigue then damageTaken = damageTaken - reductionFromFatigue damageReduced = damageReduced + reductionFromFatigue end end Хм, включил отладочную информацию, все работает, как надо. Просто из-за высокого навыка штраф почти полностью компенсируется бонусами. Изменено 1 августа, 2019 пользователем Муурн Шепард Ссылка на комментарий Поделиться на другие сайты Поделиться
-=ChieF=- Опубликовано 1 августа, 2019 Жалоба Поделиться Опубликовано 1 августа, 2019 Знаешь что нужно обязательно сделать? Чтобы у разной брони была разная устойчивость к рубящим, режущим и колющим атакам, а у каждого типа оружия были свои фишки для рубящих, режущих и колющих ударов. Впрочем, можно не заморачиваться, а сделать например колющий удар (у оружия любого типа) самым быстрым, но минусом шанса попадания, режущий - с бонусом на шанс попадания, но с наихудшим пробиванием брони, а рубящий - с бонусом урона, но с замедлением. Вот это будет великолепно, и появится смысл в разных ударах. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 1 августа, 2019 Автор Жалоба Поделиться Опубликовано 1 августа, 2019 Чтобы у разной брони была разная устойчивость к рубящим, режущим и колющим атакам, а у каждого типа оружия были свои фишки для рубящих, режущих и колющих ударов. С броней разных типов будет сложно (или невозможно) - что-то не вижу где бы игра могла считать этот параметр.А вот с ударами я нашёл очень интересную фишку. У объекта mobilePlayer есть куча разных считываемых параметров в том числе isJumping, isMovingBack, isMovingForward, isMovingRight...Используя их, можно изменять формулу урона, навешивать на игрока различные баффы в виде спеллов (пока условие выполняется или по таймеру после выполнения условия) и т.д.Но сперва надо разобраться с основной стаминной зависимостью. Автор обещала ввести её в следующем релизе вместе с игровым настроечным меню. Вот тогда мод станет точно мастхевом! Ссылка на комментарий Поделиться на другие сайты Поделиться
Муурн Шепард Опубликовано 1 августа, 2019 Жалоба Поделиться Опубликовано 1 августа, 2019 С броней разных типов будет сложно (или невозможно) - что-то не вижу где бы игра могла считать этот параметр.Тип брони определяется даже стандартными средствами. Направление для атаки ловится через Action Data.Но сперва надо разобраться с основной стаминной зависимостью. Автор обещала ввести её в следующем релизе вместе с игровым настроечным меню. Вот тогда мод станет точно мастхевом!Дык выше же рабочий вариант. Формулу можно прикрутить любую. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 1 августа, 2019 Автор Жалоба Поделиться Опубликовано 1 августа, 2019 Тип брони определяется даже стандартными средствами. Можно конечно считать веса и рассчитать тип по формулам, а что насчёт события damage? Как узнать, по какой части доспеха попал удар? Ссылка на комментарий Поделиться на другие сайты Поделиться
Муурн Шепард Опубликовано 1 августа, 2019 Жалоба Поделиться Опубликовано 1 августа, 2019 Как узнать, по какой части доспеха попал удар?Хм, тут без костылей никак. Можно через развитие навыка, других способов я не вижу. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 2 августа, 2019 Автор Жалоба Поделиться Опубликовано 2 августа, 2019 (изменено) Добавить шанс уклонения от атаки в размере 30%*Ловкость, если защищающийся актёр по время события атаки движется влево или вправо. Обычно режущие удары слабее рубящих - это будет прекрасная компенсация и повод применять именно их. Колющие удары обычно ещё слабее, но используются они при движении назад, что автоматиечески даёт огромные защитные преимущества, позволяя откайчивать врагов и избегать всех его ударов. Поэтому при движении актёра назад дополнительных модификаций не требуется. А вот при движении вперёд надо что-то изменить. Тем более, учитывая то, что обычно используется движение сразу и вперёд и в сторону для нанесения рубящего удара в движении. Изменено 2 августа, 2019 пользователем Dagot_Prolaps Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Для публикации сообщений создайте учётную запись или авторизуйтесь
Вы должны быть пользователем, чтобы оставить комментарий
Создать учетную запись
Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!
Регистрация нового пользователяВойти
Уже есть аккаунт? Войти в систему.
Войти