Custom Damage Formula

[VXAce] Tutorial Version 1.0

 

Level : Multi Level

Pernah kepikir ngebuat skill yang memiliki variasi damage yang bisa kamu setel sendiri? Kalo ya, apalagi kalo kamu pake VXAce, berarti kamu sangat beruntung. Disini saya mengajarkan bagaimana cara membuat rumus perhitungan damage dengan logika dan kreatifitasnya kita masing-masing. Skill-skill disini adalah nama-nama skill yang (mungkin) akan saya gunakan pada proyek game saya yang berikutnya, 13th World. Anyway, let's go to the core. :v

Coba kamu buka database RPGVXAce, terus pilih tab Skills, lihat bagian formula pada skill Attack. Pasti ada tulisan seperti ini :

a.atk * 4 - b.def * 2



Itu adalah formula/rumus yang digunakan Ace untuk mengkalkulasi damage dasar dari sebuah serangan biasa. Ingatlah hal ini :

a = user/caster/yang pake skill
b = target/yang kena skill
v = variabel

Ketiga huruf itu yang akan kita gunakan nantinya untuk menulis formula damage buatan sendiri. Dengan contoh diatas, berarti damage yang akan dihasilkan :

attack user X 4 - defense target X 2

Angka 4 dan 2 diformula itu bisa diganti dengan angka berapapun terserah kamu yang pengen ngebuat rumus sendiri. Dicontoh ini saya coba menggunakan kebanyakan
angka-angka itu, males saya bikin angka yang laen, kalopun ada paling cuman sedikit. Let's continue. :3

PENERAPAN SKILL DASAR : 


Itu untuk skill attack biasa doank. Gimana kalo misalnya kita buat skill Shield Attack, damagenya berdasarkan kekuatan defense dari user? Try this :

a.def * 4 - b.def * 2

Gimana kalo Mind Attack, damagenya berdasarkan kekuatan magic dari user?

a.mat * 4 - b.def * 2

Skill Mind Crush, damagenya berdasarkan kekuatan magic dari user dan ditahan/dikurangi dengan kekuatan pertahanan magic dari target :

a.mat * 4 - b.mdf * 2

Skill Speedster, damagenya berdasarkan kekuatan agility dari user :

a.agi * 4 - b.agi * 2

Skill Gravity, damagenya setengah kali dari hp target yang tersisa :
b.hp / 2

Itu contoh penerapan skill dasar dari parameter-parameter dasar yang kita udah tau semuanya. Kalo mau lebih tau lagi tentang parameternya, coba kamu sorot tulisan formula pada bagian skill, ntar muncul popup window penjelasannya.

PENERAPAN SKILL MENENGAH :

Penerapan skill menengah mencakup skill-skill dengan berbagai kondisi percabangan. Kamu pasti tau kan format penulisan di event conditional branch?
Conditional Branch : Kondisinya
    Kalo benar pernyataan disini yang dijalanin
else
    Kalo salah pernyataan disini yang dijalanin
Branch End

Itu versi eventnya. Kalo versi scriptnya kira-kira modelnya seperti ini :
if kondisi
    pernyataan benar
else
    pernyataan salah
end
Wah gimana nulis skill kondisionalnya kalo bisa maken 5 baris gitu doank untuk perintah dasarnya? Tenang-tenang, 5 baris perintah dasar itu kita bisa singkat menjadi seperti ini :
if kondisi ; pernyataan benar ; else ; pernyataan salah ; end

atau kayak gini :

kondisi == kondisinya ? pernyataan benar : pernyataan salah

Tanda titik koma (;) menggantikan penggunaan baris baru pada script nantinya, jadi kita bisa menyingkat berbagai script yang panjang dan yang berbaris-baris dengan tanda titik koma (;). Dalam penulisan damage formula kita akan menggunakan tanda itu dikarenakan kolom damage formula hanyalah satu baris tingginya. :v
Ayo kita coba buat beberapa skill dengan penerapan kondisi-kondisi tersebut.

Skill Reaper Heal, jika target heal adalah Erik (Erik di database actor urutan ke 1) maka efek healingnya jadi 2000 HP, selain Erik hanya 100 HP heal :

b.id? == 1 ? 2000 : 100

Skill Reaper Suicide, skill yang memberikan damage tertinggi tapi cost caster sebagai tumbalnya. Wah ganas yah skillnya :D :

a.add_state(1); a.atk * 999;

Skill Holy Terence, skill yang berdasarkan kekuatan attack dari Terence (Terence di database aktor urutan ke 3) :

$game_actors[3].atk * 10

Skill Bone Crack, damage akan bertambah 2X ketika switch nomor 1 ON. Kalo switch OFF, damage normal :

$game_switches[1] ? (a.atk - b.def) * 2 : a.atk - b.def

Skill Bone Crush, damage akan bertambah X lipat seiring bertambahnya variabel nomor 1 :

$game_variables[1] * a.atk

bisa juga disingkat kaek gini :

v[1] * a.atk

Skill Fissure, damagenya akan menyisakan 1 HP pada target (skill tidak bisa membunuh target karena akan selalu tersisa 1 HP) :

b.hp - 1

Itu contoh dari penerapan skill tingkat menengah.

PENERAPAN SKILL LANJUT :


Penerapan skill lanjut hanyalah gabungan dari penerapan skill dasar dan menengah yang ditambahkan beberapa logika script yang gile. :3
Coba buat skill yang seperti ini.

Skill Nether Strike, semakin sedikit hp target, semakin sakit damagenya :

a.atk * 5 + ((b.mhp - b.hp)/100) * 5

Angka 100 itu sebenarnya buat ngescale damagenya biar target ga langsung mati saat kena skill. Bisa diganti dengan scale berapapun terserah kamu.

Skill Break Raid, semakin sedikit mp caster, semakin sakit damagenya :

a.mat * 5 + ((a.mmp - a.mp)/100) * 5

Skill Magic Raid, semakin banyak mp caster, semakin sakit damagenya :

a.mat * 2 + a.mp / 2

Skill Power Strike, semakin banyak hp target, semakin sakit damagenya :

a.atk * 2 + a.hp / 2

Skill Dice Gambler, damagenya berdasarkan hasil pelemparan 2 buah dadu. Setiap mata dadu yang muncul, damagenya dikalikan 100. Kalo mata dadu yang muncul adalah mata 1 pada kedua dadu, damagenya jadi 1. Kalo mata dadu yang muncul adalah mata 6 pada kedua dadu, damagenya jadi 9999 :

c=1+rand(6);d=1+rand(6);if c==1 && d==1;1;elsif c==6 && d==6;9999;else;(c+d)*100;end

Sepertinya makin advance aja yah. Saya kasih penjelasan singkat. Variabel c dan d yang ada di formula tadi mewakili dadu pertama(c) dan dadu kedua(d). Ingat yang ditulis sebelumnya diatas, untuk penggunaan variabel jangan gunakan huruf a, b, dan v. Gunakan huruf/kata lain untuk memakai fungsi variabel. Diskill ini memang terlihat advance karena penggunaan variabel dan penggunaan kondisi bercabang dijadikan satu.

Skill Toxic Curse, saat digunakan menyebabkan caster dan target terkena Poison (Poison di database state urutan ke 2) :

a.add_state(2);b.add_state(2);a.atk * 4 - b.def * 2

Formula damagenya diletakkan paling akhir karena kalkulasi diadakan setelah semua requirements terpenuhi. Kalo misalnya formula damagenya kamu tulis di awal, maka yang ada malahan no damage namun tetap kena Poison.

Skill Hunting, kalo digunakan saat equip Shortbow (Shortbow di database weapon urutan ke 31), maka damagenya akan menjadi 5X, selain memakai Shortbow damagenya 2X :

a.weapons.include?($data_weapons[31]) ? a.atk * 5 : a.atk * 2

Sepertinya skill Hunting diatas hanya bisa dipake sama aktor doank, soalnya hanya aktor yang bisa menggunakan equipment weapon. Selebihnya untuk enemy belum dicobain seh. :P

Skill Melting Blood (namanya sama kaek finishernya MaloMyotismon di DMW3 :3 ), damage akan menjadi 3X kalo target terkena status Bleeding (misalnya Bleeding di database state urutan ke 26), selain itu damage normal :

b.state?(26) ? (a.atk * 4 - b.def * 2) * 3 : a.atk * 4 - b.def * 2

Skill Union Attack, damage akan menjadi 5X kalo saat Erik menggunakan skill ini ada Natalie di party (Erik dan Natalie di database aktor masing-masing urutan ke 1 dan 2), selain itu damage normal :

a==$game_actors[1]&&$game_party.members.include?($game_actors[2]) ? (a.atk * 4 - b.def * 2) * 5 : a.atk * 4 - b.def * 2

Skill diatas (kayaknya lagi) tidak bisa digunakan oleh enemy dikarenakan deklarasi $game_actors yang hanya dikhususkan untuk aktor saja damagenya.

Skill Final Strike, damage maksimalnya dibatasi hanya sampe 5000 damage doank :

[a.atk * 4 - b.def * 2, 5000].min

Maksud dari .min itu adalah program mengambil nilai terendah dahulu sebagai array indeks pertama, kemudian nilai tertinggi di array indeks kedua, lalu mengevaluasi setiap nilai di array tersebut dengan .min, kalau-kalau saja nilai indeks pertama > nilai indeks kedua. Kalau memang melewati, maka nilai indeks kedua yang akan dijalankan.

Skill Final Crush, damage minimalnya dibatasi sampe 1 doank, untuk menghindari no damage saat def target > atk caster :

[a.atk * 4 - b.def * 2, 1].max

Maksud dari .max itu adalah program mengambil nilai tertinggi dahulu sebagai array indeks pertama, kemudian nilai terendah di array indeks kedua, lalu mengevaluasi setiap nilai di array tersebut dengan .max, kalau-kalau saja nilai indeks pertama < nilai indeks kedua. Kalau memang melewati, maka nilai indeks kedua yang akan dijalankan.

Skill Rain Shot, mentarget 3 battler secara acak. Setiap damage yang diberikan ke target, 1/2 nya akan ngeheal caster :

c=2*(a.atk-b.def);a.hp+=c/2;c

Variabel c mewakili damagenya. Baris kedua adalah penambahan HP untuk aktor berdasarkan damage(variabel c) yang kena ke target. Baris ketiga eksekusi damagenya.
Karena target battler adalah 3 secara acak, formula diatas akan berulang.

Skill Hell Stack, jika target terkena Poison, Blind, Silence, dan Confusion (urutannya di database state nomor 2,3,4,5), setiap state yang terkena target akan menambah damagenya 100 :

c=4*a.atk-2*b.def;for d in [2,3,4,5];if b.state?(d);c+=100;end;end;c

Baris pertama cek formula biasa, return hasilnya. Baris kedua cek array states apa saja yang akan diikutsertakan dalam penambahan damage. Baris ketiga cek apakah setiap state yang disertakan tadi ada pada target. Baris keempat penambahan damagenya jika memang state yang diikutsertakan ada pada target. Baris terakhir eksekusi damage.

Skill Venom Strike, skill yang meracuni target jika digunakan saat HP target dibawah 50%. Persentase kemungkinan terkena Poison adalah 50% :

c=rand(2);b.add_state(2) if b.hp<=b.mhp/2 and c==1;a.atk * 4 - b.def * 2

Variabel c untuk random persentasenya. Baris kedua HANYA AKAN DIJALANKAN kalo HP target dibawah 50%. Baris ketiga eksekusi damagenya.

PENERAPAN SKILL EXTREME


Kok tingkat extreme?
Ya dibilang extreme karena saatnya kita nyentuh SCRIPT. :3
Misalnya, game kamu punya skill Dice Gambler dengan level, jadi ada Dice Gambler level 1, level 2, level 3, level 4, level 5. Terus kalkulasi damagenya ga beda jauh dengan skill Dice Gambler Level 1. Akhirnya, dengan formula yang hampir sama kamu akan copas formulanya di skill level 2, 3, 4, dan 5. Terus tiba-tiba
kamu pengen rubah base damagenya Dice Gambler Level 1. Berarti skill level setelahnya harus copas lagi donk formulanya? :3 Ribet banget yah. :D :D
Untuk mempersingkat waktu penulisan formula, kamu bisa mendeklarasikan sebuah metode baru untuk kalkulasi damage formulanya di class Game_Battler. Kenapa harus di Game_Battler? Liat struktur data dari RGSS3 :

Game_BattlerBase -> Game_Battler -> Game_Actor
                                         |
                                         |
                                        V
                               Game_Enemy
                  
Yang battle kan aktor dan enemy, ingat ya bukan NPC lho. :P
Aktor dan enemy di struktur data mempunyai pewarisan metode dari Game_Battler dan Game_BattlerBase, dengan kata lain apa saja yang kamu tulis di Game_BattlerBase ama Game_Battler bakalan bisa digunakan oleh aktor dan enemy.
Lha kok ga ditulis di Game_BattlerBase aja?
Kalo gitu coba ke script editor, tekan Ctrl + Shift + F , ketikan di kolom pencarian def atk. Nemunya di Game_BattlerBase, baris ke 59 kan? Metode def atk untuk mengambil parameter attack power dari aktor dan enemy, begitu juga def parameter-parameter yang lain. Emang sih pengambilan parameter dilakukan di Game_BattlerBase, TAPI daritadi kan kita ngebahas tentang DAMAGE, sementara kalkulasi damage dilakukan di Game_Battler. Maka, nantinya kamu  harus nulis damage formulanya di Game_Battler. Kan pewarisan utamanya berasal dari Game_BattlerBase, jadi ga usah takut Game_Battler ga ada metode def atk, karena sudah diturunkan kepada Game_Battler lewat pewarisannya Game_BattlerBase. :)

Kita ambil saja contoh skill Dice Gambler (saya suka liat kondisi skillnya, ajib dah :P). Line sepanjang itu kita akan singkat dengan membuat metode baru di script, tepatnya di class Game_Battler seperti yang sudah saya jelaskan diatas. Coba insert script baru, terus tuliskan seperti ini :

class Game_Battler < Game_BattlerBase
    def skill_dice_gambler(a,b)
        c = 1 + rand(6)
        d = 1 + rand(6)
        if c == 1 && d == 1
            return 1
        elsif c == 6 && d == 6
            return 9999
        else
            return (c+d) * 100
        end
    end
end

Lebih enak dibaca lewat script daripada cuman satu baris box formula yah? Wkwkwkwkwkwkk. :D :D
Berarti daritadi kamu cuman mau ngerjain saya dengan nulis formula yang susah dibaca ntu?
Eh eh, enak saja, ini cuman mempermudah doank dalam penulisan formula. Kalo kamu kagak tau logika formulanya, masa harus langsung sentuh script? :P
Sekarang dengan deklarasi skill_dice_gambler(a,b) didalam script, maka penulisan damage formulanya akan lebih pendek lagi. Coba deh kamu tulis seperti ini di damage formula box skill Dice Gambler :

a.skill_dice_gambler(a,b)

Formulanya sekarang pendek bener kan? :v :v
Yang dilakukan skill saat box formula isinya bukan lagi kalkulasi damage, adalah mencari tulisan metode yang sama persis dengan metode skill yang kamu tulis tadi (skill_dice_gambler) beserta argumen didalamnya (a,b). Skill mencarinya di Game_Battler, karena disitulah kalkulasi damage terjadi. Saat ketemu, akan dievaluasi satu per satu isinya apakah berisi formula damage atau tidak. Kalo ya, damage dijalankan, kalo tidak, error. :3

Misalkan itu adalah untuk skill Dice Gambler Level 1. Kalo damage skill Dice Gambler Level 2 gimana donk? Pastilah damagenya akan lain lagi donk, lebih besar dari damage level 1. Okay, kita akan merubah sedikit dari script yang sudah kita tulis tadi diatas. Akan ditambahkan beberapa variabel tambahan :

class Game_Battler < Game_BattlerBase
    def skill_dice_gambler(a,b,dmg_min,dmg_max,dmg_normal)
        c = 1 + rand(6)
        d = 1 + rand(6)
        if c == 1 && d == 1
            return dmg_min
        elsif c == 6 && d == 6
            return dmg_max
        else
            return (c+d) * dmg_normal
        end
    end
end

Karena damage minimal level 1 adalah 1, damage maksimalnya adalah 9999, damage normalnya adalah dikalikan 100, maka untuk level 2 kita misalkan :
- Damage minimal(saat kedua mata dadu adalah 1) = 50
- Damage maksimal(saat kedua mata dadu adalah 6) = 99999
- Damage normal(saat kedua mata dadu tidak sama-sama 1 dan 6) = X 200

Kita tuliskan seperti ini di box formula skill Dice Gambler Level 2 :

a.skill_dice_gambler(a,b,50,99999,200)

Perhatikan baik-baik, sebelumnya kan kita nulis formulanya seperti ini :

a.skill_dice_gambler(a,b)

Sekarang kita nulis formulanya seperti ini :

a.skill_dice_gambler(a,b,50,99999,200)

Perbedaannya adalah pada argumen yang disertakan (argumen itu apa saja yang ada didalam tanda kurung saat deklarasi metode baru). Argumen sebelumnya hanya berisi a dan b, sementara argumen selanjutnya (setelah diedit) menjadi a, b, dmg_min, dmg_max, dmg_norml. 3 variabel yang terakhir itu yang akan kita gunakan untuk mendeklarasikan damage minimal, maksimal, dan damage normalnya (nama variabel terserah, yang penting jangan tabrakan dengan variabel yang sudah ada sebelumnya). Liat juga bagian perhitungan damagenya :

Yang lama :
    if c == 1 && d == 1
        return 1
    elsif c == 6 && d == 6
        return 9999
    else
        return (c+d) * 100
    end

Yang baru :
    if c == 1 && d == 1
        return dmg_min
    elsif c == 6 && d == 6
        return dmg_max
    else
        return (c+d) * dmg_normal
    end

Saat script mengembalikan (return) nilai yang sudah dievaluasi ke kalkulasi damage, sebelumnya kita hanya menuliskan angka statis yang tidak bisa dirubah-rubah. Versi lamanya ada angka 1 sebagai damage minimal, 9999 sebagai damage maksimal, 100 sebagai damage normal. Versi barunya tidak ada angka disitu, KARENA angka damagenya kita sudah sertakan saat pemanggilan metode damage di box formula. Liat kan ada angka 50, 99999, dan 200 di damage formulanya. Coba liat urutan argumen yang sudah kita edit sebelumnya :

(a,b,dmg_min,dmg_max,dmg_normal)

Maka urutan angka tersebut saat disimpan di variabel dan diterjemahkan ke dalam script akan menjadi :
- dmg_min = 50
- dmg_max = 99999
- dmg_normal = 200

Versi barunya, saat return nilai, script mencari variabel dmg_min, dmg_max, dan dmg_normal yang sudah berisi nilai tadi itu. Tulisan skill_dice_gambler juga bisa kamu ganti-ganti, terserah kamu, misalnya lempar_dadu, atau ga dadu_gila. Cara manggilnya, sesuaikan dengan nama metode yang kamu rubah tadi itu. Misalnya nama metodenya jadi seperti ini :

def dadu_gila(a,b,dmg_min,dmg_max,dmg_normal)
blablabla sampe selesai scriptnya

Berarti kamu nulisnya di box formula :

a.dadu_gila(a,b,50,99999,200)

Simpel kan?
Simpel kepala lo, panjang tau. :v :v
Disarankan untuk menggunakan script versi baru dari skill Dice Gambler, karena akan lebih bervariasi damagenya dibanding versi lama. :)
Itu hanya untuk skill Dice Gambler, skill lain gimana donk?
Okay, well dengan deklarasi metode di class yang sama kamu juga bisa bikin metode perhitungan damage yang berbeda-beda. Tapi ingat, tulis deklarasi metode baru SETELAH akhir (end) dari deklarasi metode sebelumnya, kalo ga error ditanggung pembeli. Nama metodenya juga ga boleh sama. :3 :3
Saya kasih contoh, misalnya skill Melting Blood kita mau buatin deklarasi metodenya di script. Script sebelumnya seperti ini :

class Game_Battler < Game_BattlerBase
    def skill_dice_gambler(a,b,dmg_min,dmg_max,dmg_normal)
        c = 1 + rand(6)
        d = 1 + rand(6)
        if c == 1 && d == 1
            return dmg_min
        elsif c == 6 && d == 6
            return dmg_max
        else
            return (c+d) * dmg_normal
        end
    end # <----- tekan enter di ujung end ini, karena ini end dari metode skill_dice_gambler
end

Sekarang bakalan seperti ini :

class Game_Battler < Game_BattlerBase
    def skill_dice_gambler(a,b,dmg_min,dmg_max,dmg_normal)
        c = 1 + rand(6)
        d = 1 + rand(6)
        if c == 1 && d == 1
            return dmg_min
        elsif c == 6 && d == 6
            return dmg_max
        else
            return (c+d) * dmg_normal
        end
    end
  
end

Udah ada tempat kosong kan? Mari menulis deklarasi metode baru. :)

class Game_Battler < Game_BattlerBase
    def skill_dice_gambler(a,b,dmg_min,dmg_max,dmg_normal)
        c = 1 + rand(6)
        d = 1 + rand(6)
        if c == 1 && d == 1
            return dmg_min
        elsif c == 6 && d == 6
            return dmg_max
        else
            return (c+d) * dmg_normal
        end
    end
  
    def skill_melting_blood(a,b,state_id,dmg_max)
        if b.state?(state_id)
            return (a.atk * 4 - b.def * 2) * dmg_max
        else
            return a.atk * 4 - b.def * 2
        end
    end
end

Kemudian, dengan contoh diatas kita akan asumsikan state Bleeding adalah state urutan ke 26 di database, dan saat target terkena state Bleeding, damagenya akan dikalikan dengan 10. Jadi, nulisnya di box formula skill Melting Blood :

a.skill_melting_blood(a,b,26,10)

Gimana? Ribet kan? :3 :3
Emang gitu kalo bikin script, rada ribet sendiri. Tapi kalo kamu sudah tau metode yang seperti ini, akan lebih mudah lagi nantinya untuk kamu yang ga usah mikir jauh-jauh menuhin baris di box formula, mendingan penuhin baris di script aja dengan formulanya. :P :P

Deklarasi metode-metode formula seperti diatas bisa juga dilakukan di class Game_Actor dan Game_Enemy, mengingat pewarisan utama dari kedua class tersebut adalah Game_Battler dan Game_BattlerBase. Tapi jangan sampe tumpang tindih ya, kamu udah nulis metode skill di Game_Battler, terus nulis lagi di Game_Actor. :v
Dan juga, kalo kamu nulis metodenya hanya di Game_Actor doank, berarti skill tersebut hanya untuk aktor, tidak boleh disertakan di action listnya enemy, atau ga bakalan error. Begitu juga sebaliknya untuk Game_Enemy. Makanya tadi nulisnya di Game_Battler, karena pewarisan metodenya adalah untuk Game_Actor dan Game_Enemy, jadi aktor dan enemy bisa menggunakan skill yang sama.

Tambahan sedikit, untuk skill physical dan magical juga bisa dibuatin kondisinya didalam script. Ini contohnya (kita tambah saja baris baru di script sebelumnya):

class Game_Battler < Game_BattlerBase
    def skill_dice_gambler(a,b,dmg_min,dmg_max,dmg_normal)
        c = 1 + rand(6)
        d = 1 + rand(6)
        if c == 1 && d == 1
            return dmg_min
        elsif c == 6 && d == 6
            return dmg_max
        else
            return (c+d) * dmg_normal
        end
    end
  
    def skill_melting_blood(a,b,state_id,dmg_max)
        if b.state?(state_id)
            return (a.atk * 4 - b.def * 2) * dmg_max
        else
            return a.atk * 4 - b.def * 2
        end
    end
  
    def physical_magical(a,b,magical=false)
        return a.mat * 4 - b.def * 2 if magical
        return a.atk * 4 - b.def * 2
    end
end

Sekarang tulis seperti ini di formula dari normal attack :

physical_magical(a,b)

Lha, itu kan ada 3 argumen, kok ditulis cuman 2? :3
Ya, karena argumen ketiga sudah ada nilai defaultnya yaitu false.
Itu lagi, magical dari mana tuh? Saya cari def magical ga ketemu-ketemu.
Well, magical disini kan hanya variabel bung. :v :v
Kalo mau set damagenya ke magical, tinggal tambah argumen true di akhir dari argumen tadi.

Phew, panjang juga tutorialnya. Anyway, selamat berkreasi dengan damagemu sendiri. :P :P

Sumber :
http://cobbtocs.co.uk/wp/?p=271
http://cobbtocs.co.uk/wp/?p=286

Post a Comment