Войти на сайт
×
ТЕМА: Дотошность Доктора Бага (Механизмы мейкера Асе)
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 6 мес. назад #112005
|
Ребят, иногда мне охота изучать сам редактор RPG Maker, в моей случаи АСЕ. Сюда я буду выкладывать (скорее всего не часто) свои внимательные наблюдения как работают некоторые механизмы движка, разбор формулов и их применений.
Так же особая благодарность Dmy за предоставленное инфо, описаний параметров. Ссылка на ресурс Первое что хочу разобрать это шанс попаданий и шанс уклонений. Понять как система обрабатывает их, чтобы лучше понимать их механизм. Первое я выложу сюда код, стандартный скрипты мейкера и второе это мое дотошное объяснения алгоритма работы. Мож кому и сгодиться )) Описание параметров шанса попаданий и шанса уклонений: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Шанс попадания (Hit rate) - Коэффициент, на который умножается шанс использования физических умений (навыков). Если персонаж не попадает, это считается промахом. Проверка на промах (miss) производится перед проверкой на уклонение (evaded). Даже если эта проверка успешна, защищающаяся сторона ещё имеет возможность уклониться (в зависимости от параметров eva и mev). Шанс уклонения (Evasion rate) - Определяет шанс уклонения от физических навыков. Проверка на уклонение (evaded) производится после проверки на промах (miss). Чтобы навык сработал, учитываются обе проверки: нападающая сторона не должна промахнуться, а защищающаяся сторона должна не смочь уклониться. Шанс магического уклонения (Шанс уклонения от магии; Magic evasion rate) - Шанс уклонения от магических навыков. Проверка на уклонение (evaded) производится после проверки на промах (miss). Чтобы навык сработал, учитываются обе проверки: нападающая сторона не должна промахнуться, а защищающаяся сторона должна не смочь уклониться. Инфо взято отсюда код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] #--------------------------------------------------------------------------
# * Calculate Hit Rate of Skill/Item Высчитываем шанс попадание навыка/предмета
#--------------------------------------------------------------------------
def item_hit(user, item)
rate = item.success_rate * 0.01 # Get success rate
rate *= user.hit if item.physical? # Physical attack: Multiply hit rate
return rate # Return calculated hit rate
end
#--------------------------------------------------------------------------
# * Calculate Evasion Rate for Skill/Item Высчитываем шанс уклонения от вражеского навыка или предмета
#--------------------------------------------------------------------------
def item_eva(user, item)
return eva if item.physical? # Return evasion if physical attack
return mev if item.magical? # Return magic evasion if magic attack
return 0
end
...
#--------------------------------------------------------------------------
# * Apply Effect of Skill/Item
#--------------------------------------------------------------------------
def item_apply(user, item)
@result.clear
@result.used = item_test(user, item)
@result.missed = (@result.used && rand >= item_hit(user, item))
@result.evaded = (!@result.missed && rand < item_eva(user, item))
if @result.hit?
unless item.damage.none?
@result.critical = (rand < item_cri(user, item))
make_damage_value(user, item)
execute_damage(user)
end
item.effects.each {|effect| item_effect_apply(user, item, effect) }
item_user_effect(user, item)
end
end
#--------------------------------------------------------------------------
# * Determine Final Hit Вычисление финального удара
#--------------------------------------------------------------------------
def hit?
@used && !@missed && !@evaded
end алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] 1) item_hit(user, item) 1. С "item.success_rate" соперника берется шанс успеха. С вкладки навыков. Выше 100% браться не будет, но и ниже 0 отпускаться значение не будет. Умножается на 0.01 значение. Получаем диапазон от 0 до 1. 2. Далее если навык соперника имеет тип эффекта "Физический", то умножается значение на шанс попадания (hit) соперника. Шанс попадание имеет иной область диапазона. От -1 до 1. Значения принимает дробные. 95% попадание равняется 0.95 единиц. Иначе если навык имеет тип эффекта не магический, то шанс попадание игнорируется и не умножается на полученное значение ранее. А возвращается шанс успеха (который был умножен на 0.01) 3. возвращаем полученное число. 2) @result.missed = (@result.used && rand >= item_hit(user, item)) 1. rand - возвращает число в диапазоне от 0 до 1 2. item_hit(user, item) - возвращает диапазон значений от -1 до 1, в зависимости от полученных результатов. 3. если rand больше или равно item_hit(user, item), то получаем истину. 4. @result.missed получает либо истину, либо ложь. 3) item_eva(user, item) 1. если навык врага имеет тип эффекта физический, то берем "шанс уклонения (eva)" героя, иначе если тип эффекта навыка имеет магический характер, то берем "шанс уклонение от магии (mev)" героя. Иначи возвращаем 0. Шанс уклонения и шанс уклонения от магии имеют такой же диапазон что и шанс попадания. От -1 до 1. 4) @result.evaded = ([email protected] && rand < item_eva(user, item)) 1. если rand будет меньше item_eva(user, item), то получаем истину. 2. Если [email protected] не будет являться истинной (то есть ложью), то возвращаем истину. 5) hit? 1. Здесь проверяется на истинность. Последние два условия должны иметь ложь, чтобы условия попадание по цели удара произошло. P.S. параметр hit противника или он же шанс попадания перед подсчетом суммируется, беря значения со всех вещей и заложенных значений самих бойцов. Так что шанс попадания может превысить значения 1 (100%). Можно использовать против монстров кто имеет повышенные шансы уклонения |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 2 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага 5 года 6 мес. назад #112012
|
Doctor_Bug пишет:
Ребят, иногда мне охота изучать сам редактор RPG Maker, в моей случаи АСЕ. Сюда я буду выкладывать (скорее всего не часто) свои внимательные наблюдения как работают некоторые механизмы движка, разбор формулов и их применений. Первое что хочу разобрать это шанс попаданий и шанс уклонений. Понять как система обрабатывает их, чтобы лучше понимать их механизм. Первое я выложу сюда код, стандартный скрипты мейкера и второе это мое дотошное объяснения алгоритма работы. Мож кому и сгодиться )) код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] #--------------------------------------------------------------------------
# * Calculate Hit Rate of Skill/Item Высчитываем шанс попадание навыка/предмета
#--------------------------------------------------------------------------
def item_hit(user, item)
rate = item.success_rate * 0.01 # Get success rate
rate *= user.hit if item.physical? # Physical attack: Multiply hit rate
return rate # Return calculated hit rate
end
#--------------------------------------------------------------------------
# * Calculate Evasion Rate for Skill/Item Высчитываем шанс уклонения от вражеского навыка или предмета
#--------------------------------------------------------------------------
def item_eva(user, item)
return eva if item.physical? # Return evasion if physical attack
return mev if item.magical? # Return magic evasion if magic attack
return 0
end
...
#--------------------------------------------------------------------------
# * Apply Effect of Skill/Item
#--------------------------------------------------------------------------
def item_apply(user, item)
@result.clear
@result.used = item_test(user, item)
@result.missed = (@result.used && rand >= item_hit(user, item))
@result.evaded = (!@result.missed && rand < item_eva(user, item))
if @result.hit?
unless item.damage.none?
@result.critical = (rand < item_cri(user, item))
make_damage_value(user, item)
execute_damage(user)
end
item.effects.each {|effect| item_effect_apply(user, item, effect) }
item_user_effect(user, item)
end
end
#--------------------------------------------------------------------------
# * Determine Final Hit Вычисление финального удара
#--------------------------------------------------------------------------
def hit?
@used && !@missed && !@evaded
end алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] 1) item_hit(user, item) 1. С "item.success_rate" соперника берется шанс успеха. С вкладки навыков. Выше 100% браться не будет, но и ниже 0 отпускаться значение не будет. Умножается на 0.01 значение. Получаем диапазон от 0 до 1. 2. Далее если навык соперника имеет тип эффекта "Физический", то умножается значение на шанс попадания (hit) соперника. Шанс попадание имеет иной область диапазона. От -1 до 1. Значения принимает дробные. 95% попадание равняется 0.95 единиц. Иначе если навык имеет тип эффекта не магический, то шанс попадание игнорируется и не умножается на полученное значение ранее. А возвращается шанс успеха (который был умножен на 0.01) 3. возвращаем полученное число. 2) @result.missed = (@result.used && rand >= item_hit(user, item)) 1. rand - возвращает число в диапазоне от 0 до 1 2. item_hit(user, item) - возвращает диапазон значений от -1 до 1, в зависимости от полученных результатов. 3. если rand больше или меньше item_hit(user, item), то получаем истину. 4. @result.missed получает либо истину, либо ложь. 3) item_eva(user, item) 1. если навык врага имеет тип эффекта физический, то берем "шанс уклонения (eva)" героя, иначе если тип эффекта навыка имеет магический характер, то берем "шанс уклонение от магии (mev)" героя. Иначи возвращаем 0. Шанс уклонения и шанс уклонения от магии имеют такой же диапазон что и шанс попадания. От -1 до 1. 4) @result.evaded = ([email protected] && rand < item_eva(user, item)) 1. если rand будет меньше item_eva(user, item), то получаем истину. 2. Если [email protected] не будет являться истинной (то есть ложью), то возвращаем истину. 5) hit? 1. Здесь проверяется на истинность. Последние два условия должны иметь ложь, чтобы условия попадание по цели удара произошло. Спасибо, Баг. Крайне интересная тема, которой сам интересовался и пытался что-то нарыть. Довольно познавательно. Получается, что если каким-то образом модернизировать этот код, или дописать к нему модуль, то можно сделать механизм псевдорандома? Надо будет разобрать это дело на конкретных примерах, аж интересно стало, как оно реально действует. Разброс Hit Rate, Evasion Rate и Magic Evasion Rate может быть от -1 до 1, потому что в самой базе данных их можно выставлять от -100% до 100, я правильно понимаю? |
Her Third Eye is drawing me closer
Последнее редактирование: 5 года 6 мес. назад от idavollr.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Джекил, Doctor_Bug
|
Дотошность Доктора Бага 5 года 6 мес. назад #112016
|
Да Ид получается значения эти умножаются 0.01
Так и выходит, что к примеру шанс попадания 95% конвертируется в 0.95. Ну а дальше все идет в формуле. Так сейчас выложу наблюдения связанное с крит. ударами. Да эти параметры: Hit Rate, Evasion Rate и Magic Evasion Rate принимают одз (область допустимых значений) (-1,1) |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 6 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Джекил
|
Дотошность Доктора Бага 5 года 6 мес. назад #112017
|
Что ж, давайте разберем как работает шанс критического удара и шанс уклонения от критического удара. Принцип похож как и с шансом попадания и шансом уклонения:
Здесь применяются: Шанс критического удара (CRItical rate, CRI) Шанс уклонения от критического удара (Critical EVasion rate, CEV) Описание: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Шанс критического попадания (Шанс критического удара; Critical rate), Шанс критического уклонения (Шанс уклонения от критического удара; Critical evasion rate) - Если для умения (навыка) разрешён критический урон, вероятность критического удара рассчитывается по формуле: [шанс критического попадания нападающего] * (100% - [шанс критического уклонения защищающегося]). В отличие от шанса попадания и уклонения, проверка на критический удар проводится в один ход. Для критического удара нет отдельных проверок на промах и уклонение. Инфо взято отсюда код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] ----Game_Battler----
#--------------------------------------------------------------------------
# * Calculate Critical Rate of Skill/Item
#--------------------------------------------------------------------------
def item_cri(user, item)
item.damage.critical ? user.cri * (1 - cev) : 0
end
#--------------------------------------------------------------------------
# * Apply Effect of Skill/Item
#--------------------------------------------------------------------------
def item_apply(user, item)
@result.clear
@result.used = item_test(user, item)
@result.missed = (@result.used && rand >= item_hit(user, item))
@result.evaded = (!@result.missed && rand < item_eva(user, item))
if @result.hit?
unless item.damage.none?
@result.critical = (rand < item_cri(user, item))
make_damage_value(user, item)
execute_damage(user)
end
item.effects.each {|effect| item_effect_apply(user, item, effect) }
item_user_effect(user, item)
end
end
----Game_ActionResult----
#--------------------------------------------------------------------------
# * Calculate Damage
#--------------------------------------------------------------------------
def make_damage_value(user, item)
value = item.damage.eval(user, self, $game_variables)
value *= item_element_rate(user, item)
value *= pdr if item.physical?
value *= mdr if item.magical?
value *= rec if item.damage.recover?
value = apply_critical(value) if @result.critical
value = apply_variance(value, item.damage.variance)
value = apply_guard(value)
@result.make_damage(value.to_i, item)
end
#--------------------------------------------------------------------------
# * Apply Critical
#--------------------------------------------------------------------------
def apply_critical(damage)
damage * 3
end алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] 1) item_cri(user, item) 1. Если item.damage.critical равняется истина (значение берется со вкладок редактора: вещи и навыки, с "Крит. урон:"), то происходит следующие: * Шанс критического удара (cri) противника умножается на (единица минус шанс уклонение от критического удара(cev) героя) # user.cri * (1 - cev) * Шанс критического удара и Шанс уклонение от критического удара имеют диапазон чисел от -1 до 1. Иначе возвращается 0 2) @result.critical = (rand < item_cri(user, item)) 1. rand - возвращает число в диапазоне от 0 до 1 2. если rand меньше item_cri(user, item) то возвращаем истину. одз (область допустимого значения) item_cri(user, item) равняется (-1,1) 3) В make_damage_value(user, item): 1. Если @result.critical будет истина, то будет применяться метод apply_critical(value). value - значение высчитывается количества урона или восстановления какого либо характеристики. 2. В apply_critical(damage) помещается значение, которое после умножается на 3 и возвращается. |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 5 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Джекил
|
Дотошность Доктора Бага 5 года 6 мес. назад #112018
|
Пример связанный с шансом попаданием и уклонением: Г (Герой), В (Враг)
Враг атакует героя. Герой имеет вкладки класса такие параметры, как в прочем и сам враг: Шанс попадания: 95% Шанс уклонения: 5% Враг атакует навыком который имеет тип эффекта "Физическая атака", шанс успеха (% успеха) имеет значение 100%. В нашем случаи урон не важен. Далее происходит следующий алгоритм: 1. шанс успеха умножается на 0.01. Шанс успеха имеет одз (0, 100). # rate = 100 * 0.01 = 1 2. Если навык имеет тип эффекта удара физический, то умножаем полученный результат на шанс попадания (в нашем случаи врага), который равняется 95% = 0.95 # rate = 1 * 0.95 = 0.95 3. Возвращаем получаемое число 0.95 4. Далее условие (одно из условий, их там два) будет давать истину если rand будет больше или равно значению 0.95 Напомню rand дает случайное число от 0 до 1. 5. Булевый результат (он же да, либо нет) помещаем в переменную @result.missed. 6. Далее идут подсчеты шанса уклонения героя от врага. - Если навык врага имеет тип эффекта "физическая атака", то берем "шанс уклонения (eva)", иначе если тип эффекта навыка имеет "магическая атака", то берем "шанс уклонение от магии (mev)". Оба эти значения имеют одз (-1,1). В нашем случаи мы берем шанс уклонения 5% = 0.05 7. Далее с помощью rand снова получаем случайное число и если это число будет меньше 0.05, то выражение становится истинным. Результат помещаем в переменную @result.evaded, а также туда помещаем и предыдущий результат, а именно @result.missed. 8. Ну и напоследок. В методе hit?, если последние два выражения (хотя их 3) будут ложными, а это !@missed (@result.missed), !@evaded (@result.evaded), то враг попал по герою, иначе он промахнулся. Ну как то так |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага 5 года 6 мес. назад #112020
|
Doctor_Bug пишет:
Пример связанный с шансом попаданием и уклонением: Г (Герой), В (Враг) Враг атакует героя. Герой имеет вкладки класса такие параметры, как в прочем и сам враг: Шанс попадания: 95% Шанс уклонения: 5% Враг атакует навыком который имеет тип эффекта "Физическая атака", шанс успеха (% успеха) имеет значение 100%. В нашем случаи урон не важен. Далее происходит следующий алгоритм: 1. шанс успеха умножается на 0.01. Шанс успеха имеет одз (0, 100). # rate = 100 * 0.01 = 1 2. Если навык имеет тип эффекта удара физический, то умножаем полученный результат на шанс попадания (в нашем случаи врага), который равняется 95% = 0.95 # rate = 1 * 0.95 = 0.95 3. Возвращаем получаемое число 0.95 4. Далее условие (одно из условий, их там два) будет давать истину если rand будет больше или равно значению 0.95 Напомню rand дает случайное число от 0 до 1. 5. Булевый результат (он же да, либо нет) помещаем в переменную @result.missed. 6. Далее идут подсчеты шанса уклонения героя от врага. - Если навык врага имеет тип эффекта "физическая атака", то берем "шанс уклонения (eva)", иначе если тип эффекта навыка имеет "магическая атака", то берем "шанс уклонение от магии (mev)". Оба эти значения имеют одз (-1,1). В нашем случаи мы берем шанс уклонения 5% = 0.05 7. Далее с помощью rand снова получаем случайное число и если это число будет меньше 0.05, то выражение становится истинным. Результат помещаем в переменную @result.evaded, а также туда помещаем и предыдущий результат, а именно @result.missed. 8. Ну и напоследок. В методе hit?, если последние два выражения (хотя их 3) будут ложными, а это !@missed (@result.missed), !@evaded (@result.evaded), то враг попал по герою, иначе он промахнулся. Ну как то так Натуральный рандом как он есть %). Интересно, а возможно ли какими-то скриптовыми путями заставить игру генерировать скажем среднее арифметическое из двух случайных чисел? Тогда по идее, значение будет стремиться к 50ти, и это значительно повысит возможности маниипуляции с рандомом. А ведь еще можно делать надстройки, когда к шансам добавляются значения. |
Her Third Eye is drawing me closer
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Джекил, Doctor_Bug
|
Дотошность Доктора Бага 5 года 6 мес. назад #112021
|
Создать для это скрипт. Если конечно уже не существует подобный скрипт $_$
|
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага 5 года 5 мес. назад #112176
|
Сегодняшний разбор будет затрагивать такие параметры как контратаки и магического отражения. Они же "Шанс контратаки" (CNT) и "Шанс отражения магии" (MRF)
Описание: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Контратака (Шанс контратаки; Counter attack rate) - Шанс отразить физическую атаку. Контратака возможна, лишь если персонаж может двигаться. Невозможность двигаться определяется состояниями с ограничением «без движения» (в стандартной базе данных таким является только «Нокаут» — ну и «Сон», но он снимается в конце битвы). Магическое отражение (Шанс отражения магии; Magic reflection rate) - Определяет шанс, что заклинание отразится и будет применено к заклинательнице или заклинателю. Влияет только на вероятность, не на урон. Инфо взято отсюда код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] --------------
Scene_Battle
--------------
#--------------------------------------------------------------------------
# * Invoke Skill/Item
#--------------------------------------------------------------------------
def invoke_item(target, item)
if rand < target.item_cnt(@subject, item)
invoke_counter_attack(target, item)
elsif rand < target.item_mrf(@subject, item)
invoke_magic_reflection(target, item)
else
apply_item_effects(apply_substitute(target, item), item)
end
@subject.last_target_index = target.index
end
++++++++++++++++++++++++++++++ Game_Battler +++++++++++++++++++++++++++++++++
#--------------------------------------------------------------------------
# * Calculate Counterattack Rate for Skill/Item
#--------------------------------------------------------------------------
def item_cnt(user, item)
return 0 unless item.physical? # Hit type is not physical
return 0 unless opposite?(user) # No counterattack on allies
return cnt # Return counterattack rate
end
#--------------------------------------------------------------------------
# * Calculate Reflection Rate of Skill/Item
#--------------------------------------------------------------------------
def item_mrf(user, item)
return mrf if item.magical? # Return magic reflection if magic attack
return 0
end
#--------------------------------------------------------------------------
# * Determine if Hostile Relation
#--------------------------------------------------------------------------
def opposite?(battler)
actor? != battler.actor? || battler.magic_reflection
end
#--------------------------------------------------------------------------
# * Determine if Actor or Not
#--------------------------------------------------------------------------
def actor?
return false
end
++++++++++++++++++++++++++++++ Game_Actor +++++++++++++++++++++++++++++++++++
#--------------------------------------------------------------------------
# * Determine if Actor or Not
#--------------------------------------------------------------------------
def actor?
return true
end
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#--------------------------------------------------------------------------
# * Invoke Counterattack
#--------------------------------------------------------------------------
def invoke_counter_attack(target, item)
@log_window.display_counter(target, item)
attack_skill = $data_skills[target.attack_skill_id]
@subject.item_apply(target, attack_skill)
refresh_status
@log_window.display_action_results(@subject, attack_skill)
end
#--------------------------------------------------------------------------
# * Invoke Magic Reflection
#--------------------------------------------------------------------------
def invoke_magic_reflection(target, item)
@subject.magic_reflection = true
@log_window.display_reflection(target, item)
apply_item_effects(@subject, item)
@subject.magic_reflection = false
end алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] 1) Когда боевая сцена узнает кто атакует и чем, информация поступает в метод: invoke_item(target, item) В этом месте target обозначает цель, на кого направлен навык (он же скилл/предмет), а item обозначает навык, либо предмет, который использовал @subject. 1. Первое что проверяется это контратака (CNT), давайте заглянем чуть глубже сути задачи, в метод item_cnt(@subject, item) 2. Этот метод находится в классе Game_Battler. Этот класс является связующим классом для классов героев и врагов. Так что метод item_cnt есть и героев и врагов. Первое условие этого метода проверяет, является item (он же скилл или предмет) физического характера (Тип эффекта: физическая атака), если таковым он не является, возвращаем значение 0 (что в свою очередь означает 0% контратаки) Второе условие этого метода проверяется союзник ли цель или нет. На союзника контратака, соответственно не действует и в этом случаи также вернется значение 0%. Далее если не одна условия не сработала, то возвращается значения "Шанса контратаки" цели в дробных значениях, как шанс попадания и шанс отклонения в ОДЗ (Области Допустимого Значения) (-1,1) 2) Когда условия контратаки пройдены, в роль вступает другое условие, которое проверяет на рандом (rand). Рандом выдает ОДЗ (0,1) и проверяет является меньше значение контратаки (CNT). Если да, то выполняется метод invoke_counter_attack(target, item) и контратака успешно выполняется, иначе контратака не срабатывает. 1. В методе invoke_counter_attack текущий скилл (предмет) меняется на скилл обычной атаки (id = 1) и применяется на @subject (он же атакующий). 3) Следующие в проверки идет метод item_mrf(@subject, item) 1. Здесь лишь одно условие, является ли item (навык/предмет) магического характера (Тип эффекта: магическая атака), если нет, то значения "Шанса магического отражения" является 0, он же 0%, иначе отправляется значение цели "Шанс отражения магии" в дробных значениях ОДЗ (-1,1) 4) Далее идет похожие условие под пунктом 2. Рандом проверяет значения "Шанса магического отражения", если рандом окажется меньше, то условие действий является успешной, срабатывает метод invoke_magic_reflection(target, item), иначе, оно игнорируется 1. В методе invoke_magic_reflection текущий скилл (предмет) применяется на @subject (он же атакующий). На этом сегодня пожалуй все. Они простенькие на вид. Разобраться в них не составит труда |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 5 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага 5 года 5 мес. назад #112180
|
Архиполезная тема. Поможет нам помнить, что и зачем. Я бы только добавил конкретики в название, например(Роль параметров в мэйкере)
|
Не мертво то, что в вечности пребудет. со смертью времени и смерть умрет.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Doctor_Bug
|
Дотошность Доктора Бага 5 года 5 мес. назад #112191
|
Сегодняшняя тема будет затрагивать регенерация хп, мп и тп. Разберем как работают эти параметры в скриптах Мейкера.
Скорость регенерации HP (HRG) Скорость регенерации MP (MRG) Скорость регенерации TP (TRG) Описание: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Регенерация HP (Скорость регенерации HP; HP regeneration rate), Регенерация MP (Скорость регенерации MP; MP regeneration rate), Регенерация TP (Скорость регенерации TP; TP regeneration rate) - Сколько процентов соответствующих очков (HP, MP или TP) восстанавливаются за один ход битвы. Если значения будут отрицательными, на каждом ходу соответствующие очки будут отниматься. Инфо взято отсюда Код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] ------------------
Game_Battler
------------------
#--------------------------------------------------------------------------
# * Regenerate HP
#--------------------------------------------------------------------------
def regenerate_hp
damage = -(mhp * hrg).to_i
perform_map_damage_effect if $game_party.in_battle && damage > 0
@result.hp_damage = [damage, max_slip_damage].min
self.hp -= @result.hp_damage
end
#--------------------------------------------------------------------------
# * Get Maximum Value of Slip Damage
#--------------------------------------------------------------------------
def max_slip_damage
$data_system.opt_slip_death ? hp : [hp - 1, 0].max
end
#--------------------------------------------------------------------------
# * Effect When Taking Damage on Map
#--------------------------------------------------------------------------
def perform_map_damage_effect
end
#--------------------------------------------------------------------------
# * Regenerate MP
#--------------------------------------------------------------------------
def regenerate_mp
@result.mp_damage = -(mmp * mrg).to_i
self.mp -= @result.mp_damage
end
#--------------------------------------------------------------------------
# * Regenerate TP
#--------------------------------------------------------------------------
def regenerate_tp
self.tp += 100 * trg
end
#--------------------------------------------------------------------------
# * Regenerate All
#--------------------------------------------------------------------------
def regenerate_all
if alive?
regenerate_hp
regenerate_mp
regenerate_tp
end
end
#--------------------------------------------------------------------------
# * Processing at End of Turn
#--------------------------------------------------------------------------
def on_turn_end
@result.clear
regenerate_all
update_state_turns
update_buff_turns
remove_states_auto(2)
end
---------------------------
Game_Actor
---------------------------
#--------------------------------------------------------------------------
# * End of Turn Processing on Map Screen
#--------------------------------------------------------------------------
def turn_end_on_map
if $game_party.steps % steps_for_turn == 0
on_turn_end
perform_map_damage_effect if @result.hp_damage > 0
end
end
#--------------------------------------------------------------------------
# * Number of Steps Regarded as One Turn in Battle
#--------------------------------------------------------------------------
def steps_for_turn
return 20
end
#--------------------------------------------------------------------------
# * Execute Damage Effect on Map
#--------------------------------------------------------------------------
def perform_map_damage_effect
$game_map.screen.start_flash_for_damage
end
--------------------------
Game_Screen
--------------------------
#--------------------------------------------------------------------------
# * Start Flash (for Poison/Damage Floor)
#--------------------------------------------------------------------------
def start_flash_for_damage
start_flash(Color.new(255,0,0,128), 8)
end
--------------------------
Scene_Battle
--------------------------
#--------------------------------------------------------------------------
# * End Turn
#--------------------------------------------------------------------------
def turn_end
all_battle_members.each do |battler|
battler.on_turn_end
refresh_status
@log_window.display_auto_affected_status(battler)
@log_window.wait_and_clear
end
BattleManager.turn_end
process_event
start_party_command_selection
end
#--------------------------------------------------------------------------
# * Battle Action Processing
#--------------------------------------------------------------------------
def process_action
return if scene_changing?
if !@subject || !@subject.current_action
@subject = BattleManager.next_subject
end
return turn_end unless @subject
if @subject.current_action
@subject.current_action.prepare
if @subject.current_action.valid?
@status_window.open
execute_action
end
@subject.remove_current_action
end
process_action_end unless @subject.current_action
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
if BattleManager.in_turn?
process_event
process_action
end
BattleManager.judge_win_loss
end
#--------------------------------------------------------------------------
# * Forced Action Processing
#--------------------------------------------------------------------------
def process_forced_action
if BattleManager.action_forced?
last_subject = @subject
@subject = BattleManager.action_forced_battler
BattleManager.clear_action_force
process_action
@subject = last_subject
end
end
-----------------
BattleManager
-----------------
#--------------------------------------------------------------------------
# * Determine if Turn Is Ending
#--------------------------------------------------------------------------
def self.turn_end?
@phase == :turn_end
end
#--------------------------------------------------------------------------
# * End Turn
#--------------------------------------------------------------------------
def self.turn_end
@phase = :turn_end
@preemptive = false
@surprise = false
end
#--------------------------------------------------------------------------
# * Determine if Turn Is Executing
#--------------------------------------------------------------------------
def self.in_turn?
@phase == :turn
end Алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] 1) Начнем пожалуй разбор с метода on_turn_end, который находится в двух местах. Первое этот метод исполняется на карте, а второй в боевых сценах. В этом методе происходит вычислений регенерации параметров (hp, mp, tp), но об этом позже. Разберем запуск метода с карты: 1. Этот метод срабатывает на карте в том случаи, когда игрок сделает 20 шагов. 2. Далее этот метод отправляет нас в другой метод, в котором происходит высчитывание генерации, при условии, если персонаж (каждый по очереди) жив (не имеет статуса без сознания и еще какого условия). Всё это дело происходит в методе regenerate_all. теперь разберем каждый метод по отдельности, их тут три штуки. Начнем пожалуй с regenerate_hp regenerate_hp: 1] Первое что происходит, это высчитывание значения, который помещается в локальную переменную damage damage = -(максимум_hp * скорость_регенерацию_hp) максимум_hp берется в единицах, указанный в редакторе (или в игре, при росте персонажа или врага), а вот скорость_регенерацию_hp имеет ОДЗ равное (-1,1)(hrg). Иными словами максимум_hp умножается на дробное, либо целое число. 2] Следующая строчка поставила меня в тупик, так как по сути выполнение условий приводит к пустому методу, хотя этот метод переписывается в другом классе и там он срабатывает примерно схожим условием. Метод perform_map_damage_effect в классе Героев, создает вспышку мелькание экрана красного цвета и то он срабатывает если игрок наступает на тайл с "Урон от наступления", а не от отрицательного значения регенерации (мол имитация яда). 3] Далее damage помещается сюда: [damage, max_slip_damage], здесь выбирается минимальное значение из двух значений, первое это damage, второе max_slip_damage. Этот результат будет помещен в переменную @result.hp_damage 4] В max_slip_damage проверяется условие, если в редакторе включен параметр "Урон от яда может убить", то будет возвращаться hp героя в единицах (не дробное число), иначи будет возвращаться: hp без одной единицы, либо 0. Возвращаться будет большие значение. 5] Последняя строчка, в ней будет вычитаться результат (@result.hp_damage) из hp существа (будь то герой или враг). hp - @result.hp_damage regenerate_mp: 1] Здесь похожая формула как и в методе regenerate_hp. Берется максимум MP умножается на дробное (либо целое) число (ОДЗ (-1,1), mrg) и умножается на минус: -(mmp * mrg).to_i Далее результат помещается в переменную @result.mp_damage 2] Ну а дальше с mp существа (героя или врага) отнимается полученный ранее результат @result.mp_damage regenerate_tp: Здесь все просто. Число 100 умножается на Скорость регенерации TP, который имеет ОДЗ (-1,1), а далее плюсуется TP существа (героя или врага) 2) Вернемся методу on_turn_end, а именно там, где запускается в бою. Здесь все просто, он запускается когда каждое существо сделало свой ход (будь то герой или враг), и только после запускает цепочку методов связанный с регенерацией хп, мп и тп. Теперь мы разобрали вторичные характеристики полностью. На сегодня это все =) |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 5 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: VarVarKa
|
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 5 мес. назад #112213
|
Сегодняшний разбор будет интересен, мы разберем метод где обрабатывается большинство вычислений связанный с уроном (дамагом)
Будут затронуты такие параметры как: Действия атрибутов (Эффект элемента) Атрибуты атаки (Элемент атаки) Наносимый физический урон (Получение физического урона) (pdr) Наносимый магический урон (Получение магического урона) (mdr) Степень эффекта восстановления (Эффект восстановления) (rec) Критический удар (Про неё написан пост выше) (cri) Разброс Степень защитного эффекта (Эффективность защиты) (grd) Но начнем все по порядку, каждый пост будет разбирать по отдельности некоторые части этого метода. Код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] ---------------------------
Пример
---------------------------
a = 5
b = 3
@formula = 'a + b'
def eval(a, b)
return Kernel.eval(@formula)
end
puts eval(a, b) # 8
---------------------------
RPG::UsableItem::Damage
---------------------------
def eval(a, b, v)
[Kernel.eval(@formula), 0].max * sign rescue 0
end
def sign
recover? ? -1 : 1
end
def recover?
[3,4].include?(@type)
end
-----------------
Game_Battler
-----------------
#--------------------------------------------------------------------------
# * Calculate Damage
#--------------------------------------------------------------------------
def make_damage_value(user, item)
value = item.damage.eval(user, self, $game_variables)
value *= item_element_rate(user, item)
value *= pdr if item.physical?
value *= mdr if item.magical?
value *= rec if item.damage.recover?
value = apply_critical(value) if @result.critical
value = apply_variance(value, item.damage.variance)
value = apply_guard(value)
@result.make_damage(value.to_i, item)
end
#--------------------------------------------------------------------------
# * Get Element Modifier for Skill/Item
#--------------------------------------------------------------------------
def item_element_rate(user, item)
if item.damage.element_id < 0
user.atk_elements.empty? ? 1.0 : elements_max_rate(user.atk_elements)
else
element_rate(item.damage.element_id)
end
end
#--------------------------------------------------------------------------
# * Get Maximum Elemental Adjustment Amount
# elements : An array of attribute IDs
# Returns the most effective adjustment of all elemental alignments.
#--------------------------------------------------------------------------
def elements_max_rate(elements)
elements.inject([0.0]) {|r, i| r.push(element_rate(i)) }.max
end
#--------------------------------------------------------------------------
# * Applying Guard Adjustment
#--------------------------------------------------------------------------
def apply_guard(damage)
damage / (damage > 0 && guard? ? 2 * grd : 1)
end Алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Начнем с первой строчки: value = item.damage.eval(user, self, $game_variables) 1) item.damage.eval это параметр, который берется с "Формулы" в редакторе Мейкера в разделе навыка, либо вещи. Здесь берется строка, который пользователь водит для вычисления урона, либо восстановления от навыка. Сам метод этих навыков/вещей берет с класса библиотеки RGSS, а именно с класса RPG::UsableItem::Damage. Заметьте аргументы который принимает этот метод: user - Это нападающий (может быть герой или враг) self - Это целевой объект, существо на которого нападают (может быть герой или враг) $game_variables - Ну и массив внутригровых переменных. В классе RPG::UsableItem::Damage метод eval выглядит так: def eval(a, b, v)
[Kernel.eval(@formula), 0].max * sign rescue 0
end В переменную @formula помещается строка, но Kernel.eval превращает строку в исполняемый код, а заранее полученный аргументы приобретают свою силу и вступают в свою роль, будучи прочитанные в строке. Я указал там пример, как примерно работает подобная конструкция. 2) Далее по формуле высчитывается урон (или восстановление) и выбирается из полученного результата и 0 максимальное число. Если отрицательное число, возвращается 0, иначе возвратиться урон (или восстановление). 3) Дальше умножается на метод sign, который в зависимости от типа урона, возвращает либо 1, либо -1. Случая если тип урона является "Восстановление HP" или "Восстановление MP", то результат умножается на -1, иначе умножается на 1. 4) Ну и после весь полученный результат помещается в локальную переменную value. Первую строку мы разобрали. P.S. В a и b в формуле урона, можно указывать не только такие параметры как atk, mat, def, mdf, agi, luk, hp, mp, mhp, mmp, tp, level, но, а также дополнительные параметры, такие как "Вторичные характеристики" и "Особые умения". Так же указав метод этих характеристик в формуле урона. Ну и напоследок, чтобы воспользоваться переменной, используете v[x], где х равен индификатору переменной, учтите переменная здесь начинается с 0. v[0] - переменная 0001. |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 5 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: VarVarKa
|
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 5 мес. назад #112220
|
Ну что же, давайте займемся познанием мира магии, тонкости ваших навыков в магическом понимании. Продолжаем разбор метода make_damage_value. Переходим наследующую строчку к методу item_element_rate.
Описание: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Эффект элемента (в VX Ace — Действие атрибутов) - Определяет, насколько эффективны атаки с определённым элементом против этого персонажа или противника. Значение по умолчанию — 100%, т.е. применяется значение, заданное в настройках умения. Большие значения делают атаки эффективнее, меньшие — слабее. Элемент атаки (в VX Ace — Атрибут атаки) - Определяет элемент обычной атаки. Инфо взято отсюда Алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] В методе item_element_rate происходит проверка на атрибуты атаки и действие атрибутов. 1) Первое что происходит, это проверка навыка или предмета на Атрибут. Если атрибут является "Обычная атака" то выполняется первое условие, иначе второе условие. "Обычная атака" имеет id "-1". Давайте пропустим пока первое условие и перейдем ко второму, к методу element_rate 2) Этот метод принимает аргумент "Атрибута", его id. 3) Далее происходит поиск всех "Действующих атрибутов" цели, на кого был направлен навык/предмет. Превращая их в массив данных с действующими атрибутами. 4) После происходит умножения их друг на друга, начиная с дробного числа "1.0". Сами действующие атрибуты имеют дробное значение их ОДЗ равен (0,10.0). К примеру "Действующий атрибут" -> "Огня" равен 200%, делим на 100, получаем 2.0 А теперь приведем не большой пример. Боец не имея экипировки, его "Действующие атрибуты" к огню равен 1.0 Его меч имеет какое то сопротивление к огню. Его действующий атрибут к огню имеет 0.7 (70%). Его доспех также имеет действующий атрибут к огню равный 0.3 (30%) Далее простым подсчетом узнаем общие сопротивление к огненным атакам противника 1.0 (умножается по умолчанию) * 0.7 * 0.3 = 0.21 Если к примеру, у врага огненный скилл имеет 100 урона, то после умножаем его на полученный результат. 100 * 0.21 = 21 урона получит боец. 5) Когда в методе element_rate происходит вычисление всех полученных действующих атрибутов (переумножение всех чисел), после число отправляется к переменной value и умножается на него. Так а теперь вернемся к первому условию метода item_element_rate. 1) Если же навык или предмет имеет атрибут атаки "Обычная атака" то... 2) То мы попадаем еще на одно условие. Здесь проверяется если у нападающего не прописаны атрибуты атаки, то этот метод вернет число 1.0, а вот если у пользователя имеется атрибуты атаки то здесь начинается самое интересное. Переходим к методу elements_max_rate 3) В методе elements_max_rate перебирают все атрибуты атаки нападающего, далее проверяют каждый атрибут атаки на цели по их действующим атрибутам, находят самый высокий по значениям действующие атрибут цели и выводят результат. Иными словами Мейкер находит у цели самый слабый действующие атрибут, если конечно атакующий имеет соответственный атрибут атаки и после результат передает переменной value, заранее умножив на него. Код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] #--------------------------------------------------------------------------
# * Calculate Damage
#--------------------------------------------------------------------------
def make_damage_value(user, item)
value = item.damage.eval(user, self, $game_variables)
value *= item_element_rate(user, item)
value *= pdr if item.physical?
value *= mdr if item.magical?
value *= rec if item.damage.recover?
value = apply_critical(value) if @result.critical
value = apply_variance(value, item.damage.variance)
value = apply_guard(value)
@result.make_damage(value.to_i, item)
end
#--------------------------------------------------------------------------
# * Get Element Modifier for Skill/Item
# * item.damage.element_id - Является элементом атаки. Начиная от -1 (Обычная атака), 0 (Нет), 1 (Поглощение) и далее...
#--------------------------------------------------------------------------
def item_element_rate(user, item)
if item.damage.element_id < 0 # Если обычный удар, выполняем это условие
user.atk_elements.empty? ? 1.0 : elements_max_rate(user.atk_elements) # * проверяет игрока на атрибут атаки, если есть, выполняется второе условие
else
element_rate(item.damage.element_id)
end
end
#--------------------------------------------------------------------------
# * Get Maximum Elemental Adjustment Amount
# elements : An array of attribute IDs
# Returns the most effective adjustment of all elemental alignments.
# * Сюда отправляется массив с id атрибутами атаки
# Возвращает наиболее эффективный элемент атаки из всех элементных атак
#--------------------------------------------------------------------------
def elements_max_rate(elements)
elements.inject([0.0]) {|r, i| r.push(element_rate(i)) }.max
end
#~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o~~o
#--------------------------------------------------------------------------
# * Get Attack Element
#--------------------------------------------------------------------------
def atk_elements
features_set(FEATURE_ATK_ELEMENT)
end
#--------------------------------------------------------------------------
# * Calculate Set Sum of Features
# * Вытаскиваем нужные элементы по data_id и создаем навый массив
#--------------------------------------------------------------------------
def features_set(code)
features(code).inject([]) {|r, ft| r |= [ft.data_id] }
end
#--------------------------------------------------------------------------
# * Get Feature Object Array (Feature Codes Limited)
# * Вытаскиваем нужные элементы по code и создаем навый массив
#--------------------------------------------------------------------------
def features(code)
all_features.select {|ft| ft.code == code }
end
#--------------------------------------------------------------------------
# * Get Element Rate
#--------------------------------------------------------------------------
def element_rate(element_id)
features_pi(FEATURE_ELEMENT_RATE, element_id)
end
#--------------------------------------------------------------------------
# * Calculate Complement of Feature Values
#--------------------------------------------------------------------------
def features_pi(code, id)
features_with_id(code, id).inject(1.0) {|r, ft| r *= ft.value }
end
|
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 5 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 5 мес. назад #112230
|
Раз ты заинтересовался механизмом работы мейкера, посмотри, как работает мукерский рандом?
Такое ощущение, что даже при шансах 90% слишком много проигрышей. |
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 5 мес. назад #112231
|
PanzerCat пишет:
Раз ты заинтересовался механизмом работы мейкера, посмотри, как работает мукерский рандом? Такое ощущение, что даже при шансах 90% слишком много проигрышей. Про рандом было сказано выше уже. Это шанс попадания, уворота, и так далее. В мукере натуральный рандом, он работает просто через генерацию случайного числа. Отсюда и все проблемы с ним. |
Her Third Eye is drawing me closer
Последнее редактирование: 5 года 5 мес. назад от idavollr.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Doctor_Bug
|
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 5 мес. назад #112232
|
Я могу написать не большой скрипт который заменит простой рандом на средне арифметическое значение. Ну по крайне мере, те места могу заменить, которые знаю =)
|
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Администратор запретил публиковать записи гостям.
|
Дотошность Доктора Бага (Механизмы мейкера Асе) 5 года 5 мес. назад #112289
|
В этой теме мы будем добивать метод make_damage_value. Посмотрим какие еще параметры входят в этот метод.
Наше значение value модифицируется различными параметрами, то приумножая, то приуменьшая собственное значение. Сегодняшняя тема будет задевать такие параметры: Описание: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Получение физического урона (Наносимый физический урон, Physical damage rate) - Влияет на то, насколько легко атаковать персонажа физически. Урон, наносимый умениями с типом удара «Физическая атака» (в терминологии VX Ace: навыками с типом эффекта «Физическая атака»), умножается на этот коэффициент. Получение магического урона (Наносимый магический урон, Magical damage rate) - Влияет на то, насколько легко атаковать персонажа магией. Урон, наносимый умениями с типом удара «Магическая атака» (в терминологии VX Ace: навыками с типом эффекта «Магическая атака»), умножается на этот коэффициент Эффект восстановления (Степень эффекта восстановления, Recovery effect rate) - Определяет, насколько легко восстановить HP (очки здоровья) или MP (очки магии) персонажа. При использовании исцеляющих умений или предметов количество очков умножается на этот коэффициент. Эффективность защиты (Степень защитного эффекта, Guard effect rate) - Определяет эффективность защиты персонажа. Если героиня или герой защищается, урон от атак делится на 2*[этот коэффициент]. Чтобы узнать, защищается ли героиня или герой, движок проверяет наличие особенности «Спец-поведение: Защита». При выборе пункта «Защита» применяется умение №2, которое при стандартных настройках накладывает состояние №2 «Защита». А это состояние даёт особенность «Спец-поведение: Защита». Инфо взято отсюда Алгоритм: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] 1) В условие if item.physical? проверяется, имеет ли навык/предмет тип эффекта: физического атака. Если да, то умножаем значение value на "Физический наносимый урон" (pdr), который так же как и действующие эффекты, собираются с героя/врага и умножаются друг на друга. Его ОДЗ, равна (0,10.0), если в процентах то ОДЗ равна (0%, 1000%). Тем самым преувеличивая силу навыков/предметов физического характера. 2) Это условие if item.magical? идентична условию выше. Только здесь проверяется тип эффекта: магической атаки. И если условие совпадает, умножается на "Магический наносимый урон" (mdr). Имеет такой же способ подсчитывание, что и физический наносимый урон. Подобные значения можно использовать для усиление героев или врагов, их навыки физического и магического характера. Если эти условия не совпадают, имею тип эффекта: на цели, то они тупа пропускаются, и переменная value идет дальше. 3) Следующие условие if item.damage.recover?, проверяет имеет ли навык/предмет тип урона: восстановление HP или восстановление MP, если да, то умножаем переменную value на "Степень эффекта восстановления" (rec). Этот параметр идентичен параметрам: "Физический наносимый урон" и "Магический наносимый урон". Также подсчитывается. И имеют такое же ОДЗ. value = apply_critical(value) if @result.critical - эту строчку мы пропустим, она разбиралась ранее, в предыдущих разборах. 4) Углубимся немного в следующую строчку, а именно в метод apply_variance(value, item.damage.variance) item.damage.variance - сюда кладется значение взятая с редактора Мейкера, с вкладки "Разброс", и имеет одз (0,100), не дробное число! В переменную damage, кладется значение value. Метод abs возвращает абсолютное число, иными словами, если число окажется отрицательным, он переведет в положительное число. После идет такая формула: damage.abs * variance / 100 (значение value, положительное число) * (разброс) / 100 Далее из полученного результата, выбирается самое максимальное число. Либо этот полученный результат, либо 0. И обязательно это число превратить в целое число, отбросить дроби. Результат поместится в локальную переменную amp. Если методу rand передать в качестве аргумента целое число, то rand будет генерировать случайные числа в диапазоне от 0 до n-1. Что в принципе и происходит в следующей формуле. rand(amp + 1) - генерирует случайное число, в полученной диапазоне. Напоследок отнимается еще и amp. rand(amp + 1) + rand(amp + 1) - amp После чего полученный результат кладется в переменную var Последней строчкой этого метода является условие, которое проверяет переменную damage(он же value), является ли он положительным числом, либо просто 0, если да, то прибавляется значение var к damage(он же value), иначе отнимается. 5) Метод apply_guard(value). В условие этого метода (damage > 0 && guard? ? 2 * grd : 1), идет проверка: если damage(он же value) будет больше 0 и если герой/враг защищается, то "Степень защитного эффекта" (grd) умножается на 2, иначе будет возвращено число 1. "Степень защитного эффекта" (grd) имеет ОДЗ, как и "Физический наносимый урон" и похожие параметры. Ну а после полученный результат делим на damage(он же value). "Степень защитного эффекта" - приумножает защиту оппонента, думаю этот параметр хорошо подойдет для щитов. Хотя его можно применять в любом месте. 6) После прохождение value всех модификаций, его отправляют в метод make_damage, причем избавляя его от дробных значений. Но, а про метод make_damage мы поговорим позже, в основном там уже происходит распределений эффекта на параметры. Код: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] -----------------
Game_Battler
-----------------
#--------------------------------------------------------------------------
# * Calculate Damage
#--------------------------------------------------------------------------
def make_damage_value(user, item)
value = item.damage.eval(user, self, $game_variables)
value *= item_element_rate(user, item)
value *= pdr if item.physical?
value *= mdr if item.magical?
value *= rec if item.damage.recover?
value = apply_critical(value) if @result.critical
value = apply_variance(value, item.damage.variance)
value = apply_guard(value)
@result.make_damage(value.to_i, item)
end
#--------------------------------------------------------------------------
# * Applying Variance
#--------------------------------------------------------------------------
def apply_variance(damage, variance)
amp = [damage.abs * variance / 100, 0].max.to_i
var = rand(amp + 1) + rand(amp + 1) - amp
damage >= 0 ? damage + var : damage - var
end
#--------------------------------------------------------------------------
# * Applying Guard Adjustment
#--------------------------------------------------------------------------
def apply_guard(damage)
damage / (damage > 0 && guard? ? 2 * grd : 1)
end Вывод: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Для усиления навыков как войнам, так и магам отлично подходят такие параметры как "Физический наносимый урон" и "Магический наносимый урон", а "Степень эффекта восстановления" подойдет для целителей или каким побрякушкам которые будут усиливать исцеление или пополнение манны (главное чтобы в навыках/предметах был тип урона восстановление HP или восстановление MP). Ну а "Степень защитного эффекта" подойдет для воинов-танков, которые собирают на себя врагов и защищают всю группу. Надеюсь мои разборы не покажутся слишком сложными, спасибо что уделили этому время. |
Баг изучает Godot Engine. А слушает эту музыку ~~> Мое сердце
Последнее редактирование: 5 года 5 мес. назад от Doctor_Bug.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Snake Fightin
|
Время создания страницы: 0.685 секунд