Initial support for Genetic, Sorcerer and Elemental Summons. Special Thanks to 3CeAM for the base.

Notice this revision onwards requires you to update your char sql table and add the elemental sql table (check sql-files/upgrade_svn15885_log.sql)
If you step by any bugs, let us know at http://rathena.org/board/tracker/ Thank you very much.
ARRIBA ARRIBA.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@15885 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
shennetsind 2012-04-20 18:05:14 +00:00
parent 9003fa4eca
commit a1612031a6
44 changed files with 4367 additions and 3409 deletions

View File

@ -87,6 +87,7 @@ groups: (
inherit: ( /*empty list*/ )
commands: {
/* no commands by default */
warp: true
}
permissions: {
/* without this basic permissions regular players could not

27
db/elemental_db.txt Normal file
View File

@ -0,0 +1,27 @@
//ID,Sprite_Name,Name,LV,HP,SP,Range1,ATK1,ATK2,DEF,MDEF,STR,AGI,VIT,INT,DEX,LUK,Range2,Range3,Scale,Race,Element,Speed,aDelay,aMotion,dMotion
// Monster Elementals
2114,EL_AGNI_S,Agni,100,5000,1,1,100,100,10,10,1,1,1,1,1,1,5,12,0,0,83,200,504,1020,360
2115,EL_AGNI_M,Agni,100,7500,1,1,250,250,25,25,1,1,1,1,1,1,5,12,1,0,83,200,504,1020,360
2116,EL_AGNI_L,Agni,100,10000,1,1,500,500,50,50,1,1,1,1,1,1,5,12,2,0,83,200,504,1020,360
2117,EL_AQUA_S,Aqua,100,5000,1,1,100,100,10,10,1,1,1,1,1,1,5,12,0,0,81,200,504,1020,360
2118,EL_AQUA_M,Aqua,100,7500,1,1,250,250,25,25,1,1,1,1,1,1,5,12,1,0,81,200,504,1020,360
2119,EL_AQUA_L,Aqua,100,10000,1,1,500,500,50,50,1,1,1,1,1,1,5,12,2,0,81,200,504,1020,360
2120,EL_VENTUS_S,Ventus,100,5000,1,4,100,100,10,10,1,1,1,1,1,1,5,12,0,0,84,200,504,1020,360
2121,EL_VENTUS_M,Ventus,100,7500,1,4,250,250,25,25,1,1,1,1,1,1,5,12,1,0,84,200,504,1020,360
2122,EL_VENTUS_L,Ventus,100,10000,1,4,500,500,50,50,1,1,1,1,1,1,5,12,2,0,84,200,504,1020,360
2123,EL_TERA_S,Tera,100,5000,1,1,100,100,10,10,1,1,1,1,1,1,5,12,0,0,82,200,504,1020,360
2124,EL_TERA_M,Tera,100,7500,1,1,250,250,25,25,1,1,1,1,1,1,5,12,1,0,82,200,504,1020,360
2125,EL_TERA_L,Tera,100,10000,1,1,500,500,50,50,1,1,1,1,1,1,5,12,2,0,82,200,504,1020,360
//2114,EL_AGNI_S,Agni ,100,5000,500 ,1,250,250 ,10,10, 25,25,25,25,25,25, 10,12,0,0,83,200,504,1020,360
//2115,EL_AGNI_M,Agni ,100,7500,750 ,1,500,500 ,25,25, 50,50,50,50,50,50, 10,12,1,0,83,200,504,1020,360
//2116,EL_AGNI_L,Agni ,100,10000,1000 ,1,1000,1000 ,50,50, 100,100,100,100,100,100, 10,12,2,0,83,200,504,1020,360
//2117,EL_AQUA_S,Aqua ,100,5000,500 ,1,250,250 ,10,10, 25,25,25,25,25,25, 10,12,0,0,81,200,504,1020,360
//2118,EL_AQUA_M,Aqua ,100,7500,750 ,1,500,500 ,25,25, 50,50,50,50,50,50, 10,12,1,0,81,200,504,1020,360
//2119,EL_AQUA_L,Aqua ,100,10000,1000 ,1,1000,1000 ,50,50, 100,100,100,100,100,100, 10,12,2,0,81,200,504,1020,360
//2120,EL_VENTUS_S,Ventus ,100,5000,500 ,4,250,250 ,10,10, 25,25,25,25,25,25, 10,12,0,0,84,200,504,1020,360
//2121,EL_VENTUS_M,Ventus ,100,7500,750 ,4,500,500 ,25,25, 50,50,50,50,50,50, 10,12,1,0,84,200,504,1020,360
//2122,EL_VENTUS_L,Ventus ,100,10000,1000 ,4,1000,1000 ,50,50, 100,100,100,100,100,100, 10,12,2,0,84,200,504,1020,360
//2123,EL_TERA_S,Tera ,100,5000,500 ,1,250,250 ,10,10, 25,25,25,25,25,25, 10,12,0,0,82,200,504,1020,360
//2124,EL_TERA_M,Tera ,100,7500,750 ,1,500,500 ,25,25, 50,50,50,50,50,50, 10,12,1,0,82,200,504,1020,360
//2125,EL_TERA_L,Tera ,100,10000,1000 ,1,1000,1000 ,50,50, 100,100,100,100,100,100, 10,12,2,0,82,200,504,1020,360

51
db/elemental_skill_db.txt Normal file
View File

@ -0,0 +1,51 @@
//ElementalID,SkillID,SkillLevel,ReqMode
//Spirit Modes (1 = Passive, 2 = Defensive, 4 = Agressive)
//
// EL_AGNI_S
2114,8413,1,1 //EL_PYROTECHNIC,Pyrotechnic
2114,8401,1,2 //EL_CIRCLE_OF_FIRE,Circle of Fire
2114,8425,1,4 //EL_FIRE_ARROW,Fire Arrow
// EL_AGNI_M
2115,8414,1,1 //EL_HEATER,Heater
2115,8402,1,2 //EL_FIRE_CLOAK,Fire Cloak
2115,8426,1,4 //EL_FIRE_BOMB,Fire Bomb
// EL_AGNI_L
2116,8415,1,1 //EL_TROPIC,Tropic
2116,8403,1,2 //EL_FIRE_MANTLE,Fire Mantle
2116,8428,1,4 //EL_FIRE_WAVE,Fire Wave
// EL_AQUA_S
2117,8416,1,1 //EL_AQUAPLAY,Aqua Play
2117,8404,1,2 //EL_WATER_SCREEN,Water Screen
2117,8430,1,4 //EL_ICE_NEEDLE,Ice Needle
// EL_AQUA_M
2118,8417,1,1 //EL_COOLER,Cooler
2118,8405,1,2 //EL_WATER_DROP,Water Drop
2118,8431,1,4 //EL_WATER_SCREW,Water Screw
// EL_AQUA_L
2119,8418,1,1 //EL_CHILLY_AIR,Cool Air
2119,8406,1,2 //EL_WATER_BARRIER,Water Barrier
2119,8433,1,4 //EL_TIDAL_WEAPON,Tidal Weapon
// EL_VENTUS_S
2120,8419,1,1 //EL_GUST,Gust
2120,8407,1,2 //EL_WIND_STEP,Wind Step
2120,8434,1,4 //EL_WIND_SLASH,Wind Slasher
// EL_VENTUS_M
2121,8420,1,1 //EL_BLAST,Blast
2121,8408,1,2 //EL_WIND_CURTAIN,Wind Curtain
2121,8435,1,4 //EL_HURRICANE,Hurricane Rage
// EL_VENTUS_L
2122,8421,1,1 //EL_WILD_STORM,Wild Storm
2122,8409,1,2 //EL_ZEPHYR,Zephyr
2122,8437,1,4 //EL_TYPOON_MIS,Typhoon Missile
// EL_TERA_S
2123,8422,1,1 //EL_PETROLOGY,Petrology
2123,8410,1,2 //EL_SOLID_SKIN,Solid Skin
2123,8439,1,4 //EL_STONE_HAMMER,Stone Hammer
// EL_TERA_M
2124,8423,1,1 //EL_CURSED_SOIL,Cursed Soil
2124,8411,1,2 //EL_STONE_SHIELD,Stone Shield
2124,8440,1,4 //EL_ROCK_CRUSHER,Rock Launcher
// EL_TERA_L
2125,8424,1,1 //EL_UPHEAVAL,Upheaval
2125,8412,1,2 //EL_POWER_OF_GAIA,Power of Gaia
2125,8442,1,4 //EL_STONE_RAIN,Stone Rain

View File

@ -442,3 +442,85 @@
//-- Poison Fatigue <-- GC_RESEARCHNEWPOISON Lv6, 1 Izidor, 1 Medicine Bowl, 10 Sticky Poison, 1 Poison Kit
12724,25,2024,6,709,1,7134,1,7565,10,7931,1
//==============================================
//==============================================
// Genetic Foods And Potions (LV= 26 -> 29)
//==============================================
//---- Change Material --- ItemLV=26 -----------
//-- Phracon [8] <-- GN_CHANGEMATERIAL Lv1, 40 Glass Bead, 45 Spawn
1010,26,2494,1,746,40,908,45
//-- Witch Starsand [2] <-- GN_CHANGEMATERIAL Lv1, 15 Blue Porcelain, 10 InsectFeeler
1061,26,2494,1,735,15,928,10
//-- Throwable HP Increase Potion (Small) [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 HP Potions (Small)
13275,26,2494,1,6297,10,12422,10
//-- Throwable HP Increase Potion (Medium) [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 HP Potions (Medium)
13276,26,2494,1,6297,10,12423,10
//-- Throwable HP Increase Potion (Large) [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 HP Potions (Large)
13277,26,2494,1,6297,10,12424,10
//-- Throwable SP Increase Potion (Small) [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 SP Potions (Small)
13278,26,2494,1,6297,10,12425,10
//-- Throwable SP Increase Potion (Medium) [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 SP Potions (Medium)
13279,26,2494,1,6297,10,12426,10
//-- Throwable SP Increase Potion (Large) [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 SP Potions (Large)
13280,26,2494,1,6297,10,12427,10
//-- Throwable Enrich White Potion Z [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 Enrich White Potion Z
13281,26,2494,1,6297,10,12428,10
//-- Vitata 500 [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 Vitata 500
13282,26,2494,1,6297,10,12436,10
//-- Enrich Celermine Juice [10] <-- GN_CHANGEMATERIAL Lv1, 10 Throwing Bottle, 10 Enrich Celermine Juice
13283,26,2494,1,6297,10,12437,10
//---- Mix Cooking --- ItemLV=27 ---------------
//-- Savage BBQ <-- GN_MIX_COOKING Lv1, Mix Cook Book, 1 Melange Pot, 1 Savage Meat, 1 Cooking Skewer, 1 Black Charcoal
12429,27,2495,1,11022,0,6248,1,6249,1,6250,1,6251,1
//-- Wug Blood Cocktail <-- GN_MIX_COOKING Lv1, Mix Cook Book, 1 Melange Pot, 3 Wolf Blood, 2 Cold Ice
12430,27,2495,1,11022,0,6248,1,6252,3,6253,2
//-- Minor Brisket <-- GN_MIX_COOKING Lv1, Mix Cook Book, 1 Melange Pot, 2 Beef Head Meat, 1 Large Cookpot
12431,27,2495,1,11022,0,6248,1,6254,2,6255,1
//-- Siroma Icetea <-- GN_MIX_COOKING Lv1, Mix Cook Book, 1 Melange Pot, 3 Ice Fragment, 2 Ice Crystal, 1 Comodo Tropic Fruit
12432,27,2495,1,11022,0,6248,1,6256,3,6257,2,6258,1
//-- Drocera Herb Stew <-- GN_MIX_COOKING Lv1, Mix Cook Book, 3 Red Herb, 3 White Herb, 3 Blue Herb, 1 Melange Pot, 1 Large Cookpot, 1 Drocera Tentacle
12433,27,2495,1,11022,0,507,3,509,3,510,3,6248,1,6255,1,6259,3
//-- Petti Tail Noodle <-- GN_MIX_COOKING Lv1, Mix Cook Book, 1 Melange Pot, 2 Petti Tail, 1 Fine Noodle, 1 Cool Gravy
12434,27,2495,1,11022,0,6248,1,6260,2,6261,1,6262,1
//---- Create Bomb --- ItemLV=28 ---------------
//-- Apple Bomb <-- GN_MAKEBOMB Lv1, Apple Bomb CB, 1 Apple, 1 Scell, 1 Detonator, 1 Gun Powder
13260,28,2496,1,6279,0,512,1,911,1,1051,1,6244,1
//-- Coconut Bomb <-- GN_MAKEBOMB Lv1, Coconut Bomb CB, 1 Detonator, 1 Coconut Fruit, 2 Gun Powder
13261,28,2496,1,6281,0,1051,1,6263,1,6244,2
//-- Melon Bomb <-- GN_MAKEBOMB Lv1, Melon Bomb CB, 1 Sticky Mucus, 1 Detonator, 2 Gun Powder, 1 Melon
13262,28,2496,1,6282,0,938,1,1051,1,6244,2,6264,1
//-- Pineapple Bomb <-- GN_MAKEBOMB Lv1, Pinepple Bomb CB, 1 Cactus Needle, 1 Detonator, 3 Gun Powder, 1 Pineapple
13263,28,2496,1,6280,0,952,1,1051,1,6244,3,6265,1
//-- Banana Bomb <-- GN_MAKEBOMB Lv1, Banana Bomb CB, 1 Banana, 1 Detonator, 4 Gun Powder, 1 Mould Powder
13264,28,2496,1,6283,0,513,1,1051,1,6244,4,7001,1
//---- Special Pharmacy --- ItemLV=29 ----------
//-- Seed Of Horny Plant <-- GN_S_PHARMACY Lv1, Plant Genetic Grow, 10 Prickly Fruit
6210,29,2497,1,6284,0,576,10
//-- Bloodsuck Plant Seed <-- GN_S_PHARMACY Lv1, Plant Genetic Grow, 10 Root Of Maneater
6211,29,2497,1,6284,0,1033,10
//-- Bomb Mushroom Spore <-- GN_S_PHARMACY Lv1, Plant Genetic Grow, 10 Mushroom Spore, 2 Gun Powder, 5 Poison Spore
6212,29,2497,1,6284,0,921,10,6244,2,7033,5
//-- HP Increase Potion (Small) <-- GN_S_PHARMACY Lv1, Increase Stamina Study, 10 White Herb, 5 Monster's Feed, 10 Empty Bottle, 1 Hot Sauce
12422,29,2497,1,11023,0,509,10,528,5,713,10,7455,1
//-- HP Increase Potion (Medium) <-- GN_S_PHARMACY Lv1, Increase Stamina Study, 10 Yellow Herb, 10 White Herb, 10 Empty Bottle, 1 Hot Sauce
12423,29,2497,1,11023,0,508,10,509,10,713,10,7455,1
//-- HP Increase Potion (Large) <-- GN_S_PHARMACY Lv1, Increase Stamina Study, 15 White Herb, 3 Fruit Of Mastela, 1 Holy Water, 10 Empty Bottle, 1 Hot Sauce
12424,29,2497,1,11023,0,509,15,522,3,523,1,713,10,7455,1
//-- SP Increase Potion (Small) <-- GN_S_PHARMACY Lv1, Vital Drink CB, 10 Grape, 10 Lemon, 10 Empty Bottle, 1 Sweet Sauce
12425,29,2497,1,11024,0,514,10,568,10,713,10,7453,1
//-- SP Increase Potion (Medium) <-- GN_S_PHARMACY Lv1, Vital Drink CB, 10 Blue Herb, 10 Honey, 10 Empty Bottle, 1 Sweet Sauce
12426,29,2497,1,11024,0,510,10,518,10,713,10,7453,1
//-- SP Increase Potion (Large) <-- GN_S_PHARMACY Lv1, Vital Drink CB, 15 Blue Herb, 10 Royal Jelly, 10 Empty Bottle, 1 Sweet Sauce
12427,29,2497,1,11024,0,510,15,526,10,713,10,7453,1
//-- Enrich White Potion Z <-- GN_S_PHARMACY Lv1, Quality Potion Book, 20 White Potion, 10 White Herb, 1 Alchol, 10 Empty Cylinder
12428,29,2497,1,6285,0,504,20,509,10,970,1,1092,10
//-- Vitata 500 <-- GN_S_PHARMACY Lv1, Quality Potion Book, 10 Blue Herb, 10 Grape, 10 Honey, 10 Empty Cylinder
12436,29,2497,1,6285,0,510,10,514,10,518,10,1092,10
//-- Enrich Celermine Juice <-- GN_S_PHARMACY Lv1, Quality Potion Book, 5 Center Potion, 5 Awakening Potion, 10 Empty Cylinder, 5 Hot Sauce
12437,29,2497,1,6285,0,645,5,656,5,1092,10,7455,5
//-- Cure Free <-- GN_S_PHARMACY Lv1, Quality Potion Book, 20 Green Herb, 1 Fruit Of Mastela, 5 Panacea, 1 Leaf Of Yggdrasil, 10 Empty Cylinder
12475,29,2497,1,6285,0,511,20,522,1,525,5,610,1,1092,10
//===============================================

View File

@ -1783,61 +1783,61 @@
//===== Elemental Skills =======================
//-- EL_CIRCLE_OF_FIRE
//8401,0,0,0,-1,0,0
8401,0,0,0,-1,0,0
//-- EL_FIRE_CLOAK
//8402,0,0,0,-1,0,0
8402,0,0,0,-1,0,0
//-- EL_FIRE_MANTLE
//8403,0,0,0,15000,0,0
8403,0,0,0,15000,0,0
//-- EL_WATER_SCREEN
//8404,0,0,0,-1,0,0
8404,0,0,0,-1,0,0
//-- EL_WATER_DROP
//8405,0,0,0,-1,0,0
8405,0,0,0,-1,0,0
//-- EL_WATER_BARRIER
//8406,1000,0,0,15000,0,0
8406,1000,0,0,15000,0,0
//-- EL_WIND_STEP
//8407,0,0,0,-1,0,0
8407,0,0,0,-1,0,0
//-- EL_WIND_CURTAIN
//8408,0,0,0,-1,0,0
8408,0,0,0,-1,0,0
//-- EL_ZEPHYR
//8409,0,0,0,15000,0,0
8409,0,0,0,15000,0,0
//-- EL_STONE_SHIELD
//8411,0,0,0,-1,0,0
8411,0,0,0,-1,0,0
//-- EL_POWER_OF_GAIA
//8412,0,0,0,15000,0,0
8412,0,0,0,15000,0,0
//-- EL_PYROTECHNIC
//8413,0,0,0,-1,0,0
8413,0,0,0,-1,0,0
//-- EL_HEATER
//8414,0,0,0,-1,0,0
8414,0,0,0,-1,0,0
//-- EL_TROPIC
//8415,0,0,0,-1,0,0
8415,0,0,0,-1,0,0
//-- EL_AQUAPLAY
//8416,0,0,0,-1,0,0
8416,0,0,0,-1,0,0
//-- EL_COOLER
//8417,0,0,0,-1,0,0
8417,0,0,0,-1,0,0
//-- EL_CHILLY_AIR
//8418,0,0,0,-1,0,0
8418,0,0,0,-1,0,0
//-- EL_GUST
//8419,0,0,0,-1,0,0
8419,0,0,0,-1,0,0
//-- EL_BLAST
//8420,0,0,0,-1,0,0
8420,0,0,0,-1,0,0
//-- EL_WILD_STORM
//8421,0,0,0,-1,0,0
8421,0,0,0,-1,0,0
//-- EL_PETROLOGY
//8422,0,0,0,-1,0,0
8422,0,0,0,-1,0,0
//-- EL_CURSED_SOIL
//8423,0,0,0,-1,0,0
8423,0,0,0,-1,0,0
//-- EL_UPHEAVAL
//8424,0,0,0,-1,0,0
8424,0,0,0,-1,0,0
//-- EL_TIDAL_WEAPON
//8433,0,0,0,-1,0,0
8433,0,0,0,-1,0,0
//-- EL_TYPOON_MIS
//8437,0,0,0,15000,0,0
8437,0,0,0,15000,0,0
//-- EL_STONE_HAMMER
//8439,0,0,0,5000,0,0
8439,0,0,0,5000,0,0
//-- EL_ROCK_CRUSHER
//8440,0,0,0,15000,0,0
8440,0,0,0,15000,0,0
//-- EL_ROCK_CRUSHER_ATK
//8441,0,0,0,15000,0,0
8441,0,0,0,15000,0,0
//==========================================
//===== Guild Skills =======================

View File

@ -944,256 +944,62 @@
2434,0,6,4,0,0x3,5,5,1,yes,0,0x4000,0,none,0, WM_UNLIMITED_HUMMING_VOICE,Unlimited Humming Voice
2516,11,6,1,-1,0x2,5,5,1,no,0,0,0,weapon,0, WM_SEVERE_RAINSTORM_MELEE,Severe Rainstorm Melee
//2021,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_VENOMIMPRESS,
//2022,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_CROSSIMPACT,
//2023,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_DARKILLUSION,
//2024,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_RESEARCHNEWPOISON,
//2025,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_CREATENEWPOISON,
//2026,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_ANTIDOTE,
//2027,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_POISONINGWEAPON,
//2028,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_WEAPONBLOCKING,
//2029,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_COUNTERSLASH,
//2030,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_WEAPONCRUSH,
//2031,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_VENOMPRESSURE,
//2032,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_POISONSMOKE,
//2033,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_CLOAKINGEXCEED,
//2034,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_PHANTOMMENACE,
//2035,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_HALLUCINATIONWALK,
//2036,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_ROLLINGCUTTER,
//2037,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GC_CROSSRIPPERSLASHER,
//2038,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_JUDEX,
//2039,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_ANCILLA,
//2040,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_ADORAMUS,
//2041,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_CLEMENTIA,
//2042,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_CANTO,
//2043,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_CHEAL,
//2044,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_EPICLESIS,
//2045,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_PRAEFATIO,
//2046,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_ORATIO,
//2047,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_LAUDAAGNUS,
//2048,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_LAUDARAMUS,
//2049,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_EUCHARISTICA,
//2050,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_RENOVATIO,
//2051,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_HIGHNESSHEAL,
//2052,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_CLEARANCE,
//2053,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_EXPIATIO,
//2054,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_DUPLELIGHT,
//2055,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_DUPLELIGHT_MELEE,
//2056,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_DUPLELIGHT_MAGIC,
//2057,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_SILENTIUM,
//2201,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_WHITEIMPRISON,
//2202,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_SOULEXPANSION,
//2203,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_FROSTMISTY,
//2204,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_JACKFROST,
//2205,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_MARSHOFABYSS,
//2206,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_RECOGNIZEDSPELL,
//2207,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_SIENNAEXECRATE,
//2208,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_RADIUS,
//2209,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_STASIS,
//2210,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_DRAINLIFE,
//2211,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_CRIMSONROCK,
//2212,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_HELLINFERNO,
//2213,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_COMET,
//2214,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_CHAINLIGHTNING,
//2216,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_EARTHSTRAIN,
//2217,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_TETRAVORTEX,
//2222,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_SUMMONFB,
//2223,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_SUMMONBL,
//2224,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_SUMMONWB,
//2229,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_SUMMONSTONE,
//2230,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_RELEASE,
//2231,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_READING_SB,
//2232,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WL_FREEZE_SP,
//2233,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_ARROWSTORM,
//2234,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_FEARBREEZE,
//2235,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_RANGERMAIN,
//2236,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_AIMEDBOLT,
//2237,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_DETONATOR,
//2238,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_ELECTRICSHOCKER,
//2239,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_CLUSTERBOMB,
//2240,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_WUGMASTERY,
//2241,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_WUGRIDER,
//2242,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_WUGDASH,
//2243,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_WUGSTRIKE,
//2244,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_WUGBITE,
//2245,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_TOOTHOFWUG,
//2246,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_SENSITIVEKEEN,
//2247,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_CAMOUFLAGE,
//2248,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_RESEARCHTRAP,
//2249,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_MAGENTATRAP,
//2250,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_COBALTTRAP,
//2251,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_MAIZETRAP,
//2252,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_VERDURETRAP,
//2253,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_FIRINGTRAP,
//2254,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RA_ICEBOUNDTRAP,
//2255,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_MADOLICENCE,
//2256,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_BOOSTKNUCKLE,
//2257,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_PILEBUNKER,
//2258,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_VULCANARM,
//2259,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_FLAMELAUNCHER,
//2260,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_COLDSLOWER,
//2261,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_ARMSCANNON,
//2262,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_ACCELERATION,
//2263,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_HOVERING,
//2264,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_F_SIDESLIDE,
//2265,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_B_SIDESLIDE,
//2266,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_MAINFRAME,
//2267,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_SELFDESTRUCTION,
//2268,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_SHAPESHIFT,
//2269,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_EMERGENCYCOOL,
//2270,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_INFRAREDSCAN,
//2271,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_ANALYZE,
//2272,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_MAGNETICFIELD,
//2273,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_NEUTRALBARRIER,
//2274,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_STEALTHFIELD,
//2275,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_REPAIR,
//2276,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_TRAININGAXE,
//2277,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_RESEARCHFE,
//2278,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_AXEBOOMERANG,
//2279,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_POWERSWING,
//2280,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_AXETORNADO,
//2281,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_SILVERSNIPER,
//2282,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_MAGICDECOY,
//2283,0,0,0,0,0,0,9,0,no,0,0,0,none,0 NC_DISJOINT,
//2284,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_FATALMENACE,
//2285,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_REPRODUCE,
//2286,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_AUTOSHADOWSPELL,
//2287,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_SHADOWFORM,
//2288,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_TRIANGLESHOT,
//2289,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_BODYPAINT,
//2290,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_INVISIBILITY,
//2291,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_DEADLYINFECT,
//2292,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_ENERVATION,
//2293,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_GROOMY,
//2294,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_IGNORANCE,
//2295,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_LAZINESS,
//2296,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_UNLUCKY,
//2297,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_WEAKNESS,
//2298,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_STRIPACCESSARY,
//2299,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_MANHOLE,
//2300,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_DIMENSIONDOOR,
//2301,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_CHAOSPANIC,
//2302,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_MAELSTROM,
//2303,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_BLOODYLUST,
//2304,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SC_FEINTBOMB,
//2307,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_CANNONSPEAR,
//2308,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_BANISHINGPOINT,
//2309,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_TRAMPLE,
//2310,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_SHIELDPRESS,
//2311,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_REFLECTDAMAGE,
//2312,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_PINPOINTATTACK,
//2313,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_FORCEOFVANGUARD,
//2314,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_RAGEBURST,
//2315,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_SHIELDSPELL,
//2316,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_EXEEDBREAK,
//2317,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_OVERBRAND,
//2318,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_PRESTIGE,
//2319,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_BANDING,
//2320,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_MOONSLASHER,
//2321,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_RAYOFGENESIS,
//2322,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_PIETY,
//2323,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_EARTHDRIVE,
//2324,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_HESPERUSLIT,
//2325,0,0,0,0,0,0,9,0,no,0,0,0,none,0 LG_INSPIRATION,
//2326,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_DRAGONCOMBO,
//2327,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_SKYNETBLOW,
//2328,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_EARTHSHAKER,
//2329,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_FALLENEMPIRE,
//2330,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_TIGERCANNON,
//2332,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_RAMPAGEBLASTER,
//2333,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_CRESCENTELBOW,
//2334,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_CURSEDCIRCLE,
//2335,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_LIGHTNINGWALK,
//2336,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_KNUCKLEARROW,
//2337,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_WINDMILL,
//2338,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_RAISINGDRAGON,
//2340,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_ASSIMILATEPOWER,
//2341,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_POWERVELOCITY,
//2343,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_GATEOFHELL,
//2344,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_GENTLETOUCH_QUIET,
//2345,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_GENTLETOUCH_CURE,
//2346,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_GENTLETOUCH_ENERGYGAIN,
//2347,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_GENTLETOUCH_CHANGE,
//2348,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_GENTLETOUCH_REVITALIZE,
//2350,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WA_SWING_DANCE,
//2351,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WA_SYMPHONY_OF_LOVER,
//2352,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WA_MOONLIT_SERENADE,
//2381,0,0,0,0,0,0,9,0,no,0,0,0,none,0 MI_RUSH_WINDMILL,
//2382,0,0,0,0,0,0,9,0,no,0,0,0,none,0 MI_ECHOSONG,
//2383,0,0,0,0,0,0,9,0,no,0,0,0,none,0 MI_HARMONIZE,
//2412,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_LESSON,
//2413,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_METALICSOUND,
//2414,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_REVERBERATION,
//2417,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_DOMINION_IMPULSE,
//2418,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_SEVERE_RAINSTORM,
//2419,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_POEMOFNETHERWORLD,
//2420,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_VOICEOFSIREN,
//2421,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_DEADHILLHERE,
//2422,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_LULLABY_DEEPSLEEP,
//2423,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_SIRCLEOFNATURE,
//2424,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_RANDOMIZESPELL,
//2425,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_GLOOMYDAY,
//2426,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_GREAT_ECHO,
//2427,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_SONG_OF_MANA,
//2428,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_DANCE_WITH_WUG,
//2429,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_SOUND_OF_DESTRUCTION,
//2430,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_SATURDAY_NIGHT_FEVER,
//2431,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_LERADS_DEW,
//2432,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_MELODYOFSINK,
//2433,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_BEYOND_OF_WARCRY,
//2434,0,0,0,0,0,0,9,0,no,0,0,0,none,0 WM_UNLIMITED_HUMMING_VOICE,
//2443,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_FIREWALK,
//2444,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_ELECTRICWALK,
//2445,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_SPELLFIST,
//2446,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EARTHGRAVE,
//2447,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_DIAMONDDUST,
//2448,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_POISON_BUSTER,
//2449,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_PSYCHIC_WAVE,
//2450,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_CLOUD_KILL,
//2451,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_STRIKING,
//2452,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_WARMER,
//2453,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_VACUUM_EXTREME,
//2454,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_VARETYR_SPEAR,
//2455,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_ARRULLO,
//2456,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EL_CONTROL,
//2457,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_SUMMON_AGNI,
//2458,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_SUMMON_AQUA,
//2459,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_SUMMON_VENTUS,
//2460,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_SUMMON_TERA,
//2461,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EL_ACTION,
//2462,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EL_ANALYSIS,
//2463,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EL_SYMPATHY,
//2464,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EL_CURE,
//2465,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_FIRE_INSIGNIA,
//2466,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_WATER_INSIGNIA,
//2467,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_WIND_INSIGNIA,
//2468,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SO_EARTH_INSIGNIA,
//2535,0,0,0,0,0,0,9,0,no,0,0,0,none,0 ALL_BUYING_STORE,
//2474,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_TRAINING_SWORD,
//2475,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_REMODELING_CART,
//2476,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_CART_TORNADO,
//2477,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_CARTCANNON,
//2478,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_CARTBOOST,
//2479,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_THORNS_TRAP,
//2480,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_BLOOD_SUCKER,
//2481,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_SPORE_EXPLOSION,
//2482,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_WALLOFTHORN,
//2483,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_CRAZYWEED,
//2485,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_DEMONIC_FIRE,
//2486,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_FIRE_EXPANSION,
//2490,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_HELLS_PLANT,
//2492,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_MANDRAGORA,
//2493,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_SLINGITEM,
//2494,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_CHANGEMATERIAL,
//2495,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_MIX_COOKING,
//2496,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_MAKEBOMB,
//2497,0,0,0,0,0,0,9,0,no,0,0,0,none,0 GN_S_PHARMACY,
//2515,0,0,0,0,0,0,9,0,no,0,0,0,none,0 AB_SECRAMENT,
//2517,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_HOWLINGOFLION,
//2518,0,0,0,0,0,0,9,0,no,0,0,0,none,0 SR_RIDEINLIGHTNING,
//****
// SO Sorcerer
2443,0,6,4,3,0,0,5,1,yes,0,0,8:10:12:14:16,magic,0, SO_FIREWALK,Fire Walk //CHECK Video and data shows each cell only hits once.
2444,0,6,4,4,0,0,5,1,yes,0,0,8:10:12:14:16,magic,0, SO_ELECTRICWALK,Electric Walk
2445,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SO_SPELLFIST,Spell Fist
2446,9,6,2,2,0,0,5,-3,yes,0,0,0,magic,0, SO_EARTHGRAVE,Earth Grave
2447,9,6,2,1,0,0,5,-5,yes,0,0,0,magic,0, SO_DIAMONDDUST,Diamond Dust
2448,9,6,1,5,0x2,1:1:1:1:2,5,1,yes,0,0,0,magic,0, SO_POISON_BUSTER,Poison Buster
2449,9,6,2,0,0,0,5,1,yes,0,0,0,magic,0, SO_PSYCHIC_WAVE,Psychic Wave
2450,9,6,2,5,0,0,5,1,yes,0,0,0,magic,0, SO_CLOUD_KILL,Cloud Kill
2451,9,6,16,0,0x1,0,5,1,yes,0,0,0,none,0, SO_STRIKING,Striking //CHECK Data shows a % for increased successful refine rate. Is this true?
2452,9,6,2,3,0x1,0,5,1,yes,0,0,0,magic,0, SO_WARMER,Warmer
2453,9,6,2,0,0x1,0,5,1,yes,0,0,0,magic,0, SO_VACUUM_EXTREME,Vacuum Extreme
2454,9,6,1,4,0x2,1:1:2:2:3,5,1,yes,0,0,0,magic,0, SO_VARETYR_SPEAR,Varetyr Spear
2455,9,6,1,0,0x3,1:1:2:2:3,5,1,yes,0,0,0,magic,0, SO_ARRULLO,Arrullo
2456,0,6,4,0,0x1,0,4,1,yes,0,0,0,none,0, SO_EL_CONTROL,Spirit Control
2457,0,6,4,3,0x1,0,3,1,yes,0,0,0,none,0, SO_SUMMON_AGNI,Summon Fire Spirit Agni
2458,0,6,4,1,0x1,0,3,1,yes,0,0,0,none,0, SO_SUMMON_AQUA,Summon Water Spirit Aqua
2459,0,6,4,4,0x1,0,3,1,yes,0,0,0,none,0, SO_SUMMON_VENTUS,Summon Wind Spirit Ventus
2460,0,6,4,2,0x1,0,3,1,yes,0,0,0,none,0, SO_SUMMON_TERA,Summon Earth Spirit Tera
2461,5,6,1,0,0x1,0,1,1,no,0,0,0,none,0, SO_EL_ACTION,Elemental Action
2462,0,6,4,0,0x1,0,2,1,yes,0,0,0,none,0, SO_EL_ANALYSIS,Four Spirit Analysis
2463,0,0,0,0,0,0,5,0,no,0,0,0,none,0, SO_EL_SYMPATHY,Spirit Sympathy
2464,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, SO_EL_CURE,Spirit Recovery
2465,9,6,2,3,0x1,0,3,1,yes,0,0,1,magic,0, SO_FIRE_INSIGNIA,Fire Insignia //CHECK All 4 insignia skills can be targeted and animations work
2466,9,6,2,1,0x1,0,3,1,yes,0,0,1,magic,0, SO_WATER_INSIGNIA,Water Insignia // but its effects havent been coded yet.
2467,9,6,2,4,0x1,0,3,1,yes,0,0,1,magic,0, SO_WIND_INSIGNIA,Wind Insignia
2468,9,6,2,2,0x1,0,3,1,yes,0,0,1,magic,0, SO_EARTH_INSIGNIA,Earth Insignia
// Unknown
//2533,0,0,0,0,0,0,9,0,no,0,0,0,none,0 ALL_ODINS_RECALL,
//****
// GN Genetic
2474,0,0,0,0,0,0,5,0,no,0,0,0,none,0, GN_TRAINING_SWORD,Sword Training
2475,0,0,0,0,0,0,5,0,no,0,0,0,none,0, GN_REMODELING_CART,Cart Remodeling
2476,0,6,4,-1,0x2,2,5,1,no,0,0,0,weapon,2, GN_CART_TORNADO,Cart Tornado
2477,7:8:9:10:11,6,1,-1,0x2,1:1:2:2:3,5,1,yes,0,0,0,weapon,0, GN_CARTCANNON,Cart Cannon
2478,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, GN_CARTBOOST,Cart Boost
2479,9,6,2,0,0,0,5,1,yes,0,0x80,5,misc,0, GN_THORNS_TRAP,Thorn Trap
2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0, GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm....
2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0, GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm.
2482,11,6,16,0,0,0,5,1,yes,0,0,1,weapon,2, GN_WALLOFTHORN,Wall of Thorns
2483,11,6,2,0,0x3,4,10,1,yes,0,0,0,weapon,0, GN_CRAZYWEED,Crazy Weed
2484,0,6,2,2,0x2,2,10,1,no,0,0,0,weapon,0, GN_CRAZYWEED_ATK,Crazy Weed Attack
2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0, GN_DEMONIC_FIRE,Demonic Fire
2486,9,6,2,0,0,0,5,1,yes,0,0,0,none,0, GN_FIRE_EXPANSION,Fire Expansion //CHECK FIX ME!!!! Level 1 is reducing the damage. Should increase it by 50%
2487,9,6,2,0,0,0,1,1,no,0,0,0,none,0, GN_FIRE_EXPANSION_SMOKE_POWDER,Fire Expansion Smoke Powder
2488,9,6,2,0,0,0,1,1,no,0,0,0,none,0, GN_FIRE_EXPANSION_TEAR_GAS,Fire Expansion Tear Gas
2489,11,6,1,0,0,0,10,1:2:3:4:5:6:7:8:9:10,no,0,0,0,weapon,0, GN_FIRE_EXPANSION_ACID,Fire Expansion Acid
2490,9,6,2,0,0x3,1,5,1,yes,0,0x80,2:3:4:5:6,none,0, GN_HELLS_PLANT,Hell's Plant
2491,0,6,1,0,0x90,0,5,1,no,0,0,0,misc,0, GN_HELLS_PLANT_ATK,Hell's Plant Attack
2492,0,6,4,0,0x3,6:7:8:9:10,5,1,yes,0,0,0,none,0, GN_MANDRAGORA,Howling of Mandragora
2493,11,6,16,0,0x1,0,1,1,yes,0,0,0,none,0, GN_SLINGITEM,Sling Item
2494,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, GN_CHANGEMATERIAL,Change Material
2495,0,6,4,0,0x1,0,2,1,no,0,0,0,none,0, GN_MIX_COOKING,Mix Cooking
2496,0,6,4,0,0x1,0,2,1,no,0,0,0,none,0, GN_MAKEBOMB,Create Bomb
2497,0,6,4,0,0x1,0,10,1,no,0,0,0,none,0, GN_S_PHARMACY,Special Pharmacy
2498,11,6,1,0,0,0,1,1,no,0,0,0,weapon,0, GN_SLINGITEM_RANGEMELEEATK,Sling Item Attack
// Episode 13.3
//2533,0,0,4,0,0x1,0,1,0,no,0,0,0,none,0, ALL_ODINS_RECALL,Odin's Recall
@ -1261,49 +1067,49 @@
8239,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0, MER_BLESSING,Blessing
8240,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0, MER_INCAGI,Increase Agility
// Summons skills.
//8416,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_AQUAPLAY,
//8420,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_BLAST,
//8418,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_CHILLY_AIR,
//8401,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_CIRCLE_OF_FIRE,
//8417,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_COOLER,
//8423,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_CURSED_SOIL,
//8425,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_ARROW,
//8426,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_BOMB,
//8427,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_BOMB_ATK,
//8402,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_CLOAK,
//8403,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_MANTLE,
//8428,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_WAVE,
//8429,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_FIRE_WAVE_ATK,
//8419,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_GUST,
//8414,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_HEATER,
//8435,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_HURRICANE,
//8436,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_HURRICANE_ATK,
//8430,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_ICE_NEEDLE,
//8422,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_PETROLOGY,
//8412,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_POWER_OF_GAIA,
//8413,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_PYROTECHNIC,
//8440,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_ROCK_CRUSHER,
//8441,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_ROCK_CRUSHER_ATK,
//8410,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_SOLID_SKIN,
//8439,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_STONE_HAMMER,
//8442,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_STONE_RAIN,
//8411,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_STONE_SHIELD,
//8433,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_TIDAL_WEAPON,
//8415,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_TROPIC,
//8437,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_TYPOON_MIS,
//8438,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_TYPOON_MIS_ATK,
//8424,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_UPHEAVAL,
//8406,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WATER_BARRIER,
//8405,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WATER_DROP,
//8404,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WATER_SCREEN,
//8431,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WATER_SCREW,
//8432,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WATER_SCREW_ATK,
//8421,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WILD_STORM,
//8408,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WIND_CURTAIN,
//8434,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WIND_SLASH,
//8407,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_WIND_STEP,
//8409,0,0,0,0,0,0,9,0,no,0,0,0,none,0 EL_ZEPHYR,
// Elemental Spirits Skills
8401,0,6,4,3,0,0,1,1,no,0,0,0,weapon,2, EL_CIRCLE_OF_FIRE,Circle of Fire
8402,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_FIRE_CLOAK,Fire Cloak
8403,0,6,4,3,0,0,1,1,no,0,0,3,magic,2, EL_FIRE_MANTLE,Fire Mantle
8404,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_WATER_SCREEN,Water Screen
8405,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_WATER_DROP,Water Drop
8406,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_WATER_BARRIER,Water Barrier
8407,0,6,4,0,0x1,0,1,1,no,0,0,0,none,5, EL_WIND_STEP,Wind Step
8408,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_WIND_CURTAIN,Wind Curtain
8409,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_ZEPHYR,Zephyr
8410,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_SOLID_SKIN,Solid Skin
8411,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_STONE_SHIELD,Stone Shield
8412,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_POWER_OF_GAIA,Power of Gaia
8413,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_PYROTECHNIC,Pyrotechnic
8414,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_HEATER,Heater
8415,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_TROPIC,Tropic
8416,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_AQUAPLAY,Aqua Play
8417,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_COOLER,Cooler
8418,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_CHILLY_AIR,Cool Air
8419,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_GUST,Gust
8420,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_BLAST,Blast
8421,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_WILD_STORM,Wild Storm
8422,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_PETROLOGY,Petrology
8423,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_CURSED_SOIL,Cursed Soil
8424,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, EL_UPHEAVAL,Upheaval
8425,6,6,1,3,0,0,1,1,no,0,0,0,magic,0, EL_FIRE_ARROW,Fire Arrow
8426,6,6,1,3,0,1,1,1,no,0,0,0,magic,0, EL_FIRE_BOMB,Fire Bomb
8427,6,6,1,3,0,1,1,1,no,0,0,0,weapon,0, EL_FIRE_BOMB_ATK,Fire Bomb Attack
8428,6,6,1,3,0,1,1,1,no,0,0,0,magic,0, EL_FIRE_WAVE,Fire Wave
8429,6,6,1,3,0,1,1,1,no,0,0,0,weapon,0, EL_FIRE_WAVE_ATK,Fire Wave Attack
8430,9,6,1,1,0,0,1,1,no,0,0,0,magic,0, EL_ICE_NEEDLE,Ice Needle
8431,9,6,1,1,0,1,1,1,no,0,0,0,magic,0, EL_WATER_SCREW,Water Screw
8432,9,6,1,1,0,1,1,1,no,0,0,0,weapon,0, EL_WATER_SCREW_ATK,Water Screw Attack
8433,9,6,1,1,0,1,1,1,no,0,0,0,weapon,0, EL_TIDAL_WEAPON,Tidal Weapon
8434,11,6,1,4,0,0,1,1,no,0,0,0,weapon,0, EL_WIND_SLASH,Wind Slasher
8435,11,6,1,4,0,1,1,1,no,0,0,0,weapon,0, EL_HURRICANE,Hurricane Rage
8436,7,6,1,4,0,0,1,1,no,0,0,0,magic,0, EL_HURRICANE_ATK,Hurricane Rage Attack
8437,11,6,1,4,0,1,1,1,no,0,0,0,weapon,0, EL_TYPOON_MIS,Typhoon Missile
8438,11,6,1,4,0,1,1,1,no,0,0,0,magic,0, EL_TYPOON_MIS_ATK,Typhoon Missile Attack
8439,5,6,1,2,0,0,1,1,no,0,0,0,weapon,0, EL_STONE_HAMMER,Stone Hammer
8440,3,6,1,2,0,1,1,1,no,0,0,0,weapon,0, EL_ROCK_CRUSHER,Rock Launcher
8441,5,6,1,2,0,1,1,1,no,0,0,0,magic,0, EL_ROCK_CRUSHER_ATK,Rock Launcher Attack
8442,9,6,1,2,0,1,1,-5,no,0,0,0,weapon,0, EL_STONE_RAIN,Stone Rain
10000,0,0,0,0,0,0,1,0,no,0,0x10,0,none,0, GD_APPROVAL,Official Guild Approval
10001,0,0,0,0,0,0,1,0,no,0,0x10,0,none,0, GD_KAFRACONTRACT,Kafra Contract

View File

@ -724,6 +724,61 @@
2433,0,0,120:130:140:150:160,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WM_WARCRY_OF_BEYOND#Warcry of Beyond#
2434,0,0,120:130:140:150:160,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice#
//****
// SO Sorcerer
2443,0,0,30:34:38:42:46,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_FIREWALK#Fire Walk#
2444,0,0,30:34:38:42:46,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_ELECTRICWALK#Electric Walk#
2445,0,0,40:44:48:52:56,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_SPELLFIST#Spell Fist#
2446,0,0,62:70:78:86:94,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_EARTHGRAVE#Earth Grave#
2447,0,0,50:56:62:68:74,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_DIAMONDDUST#Diamond Dust#
2448,0,0,70:90:110:130:150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_POISON_BUSTER#Poison Buster#
2449,0,0,48:56:64:70:78,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_PSYCHIC_WAVE#Psychic Wave#
2450,0,0,48:56:64:70:78,0,0,0,99,0,0,none,0,716,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_CLOUD_KILL#Cloud Kill#
2451,0,0,50:55:60:65:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_STRIKING#Striking#
2452,0,0,40:52:64:76:88,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_WARMER#Warmer#
2453,0,0,34:42:50:58:66,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_VACUUM_EXTREME#Vacuum Extreme#
2454,0,0,55:62:69:76:83,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_VARETYR_SPEAR#Varetyr Spear#
2455,0,0,30:35:40:45:50,0,0,0,99,0,0,none,0,715,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_ARRULLO#Arrullo#
2456,0,0,10,0,0,0,99,0,0,elementalspirit,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_EL_CONTROL#Spirit Control#
2457,0,0,100:150:200,0,0,0,99,0,0,none,0,990,3,990,6,994,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_SUMMON_AGNI#Summon Fire Spirit Agni#
2458,0,0,100:150:200,0,0,0,99,0,0,none,0,991,3,991,6,995,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_SUMMON_AQUA#Summon Water Spirit Aqua#
2459,0,0,100:150:200,0,0,0,99,0,0,none,0,992,3,992,6,996,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_SUMMON_VENTUS#Summon Wind Spirit Ventus#
2460,0,0,100:150:200,0,0,0,99,0,0,none,0,993,3,993,6,997,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_SUMMON_TERA#Summon Wind Spirit Tera#
2461,0,0,50,0,0,0,99,0,0,elementalspirit,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_EL_ACTION#Elemental Action#
2462,0,0,10:20,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_EL_ANALYSIS#Four Spirit Analysis#
2464,0,0,10,0,0,0,99,0,0,elementalspirit,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_EL_CURE#Spirit Recovery#
2465,0,0,22:30:38,0,0,0,99,0,0,none,0,6360,1:2:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_FIRE_INSIGNIA#Fire Insignia#
2466,0,0,22:30:38,0,0,0,99,0,0,none,0,6361,1:2:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia#
2467,0,0,22:30:38,0,0,0,99,0,0,none,0,6362,1:2:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia#
2468,0,0,22:30:38,0,0,0,99,0,0,none,0,6363,1:2:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia#
//****
// GN Genetic
2476,0,0,30,0,0,0,99,0,0,cart,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_CART_TORNADO#Cart Tornado#
2477,0,0,40:42:46:48:50,0,0,0,99,8,1,cart,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_CARTCANNON#Cart Cannon#
2478,0,0,20:24:28:32:36,0,0,0,99,0,0,cart,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_CARTBOOST#Cart Boost#
2479,0,0,22:26:30:34:38,0,0,0,99,0,0,none,0,6210,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_THORNS_TRAP#Thorn Trap#
2480,0,0,30:35:40:45:50,0,0,0,99,0,0,none,0,6211,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_BLOOD_SUCKER#Blood Sucker#
2481,0,0,55:60:65:70:75,0,0,0,99,0,0,none,0,6212,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_SPORE_EXPLOSION#Spore Explosion#
2482,0,0,40:50:60:70:80,0,0,0,99,0,0,none,0,6210,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_WALLOFTHORN#Wall of Thorns#
2483,0,0,24:28:32:36:40:44:48:52:56:60,0,0,0,99,0,0,none,0,6210,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_CRAZYWEED#Crazy Weed#
2484,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_CRAZYWEED_ATK#Crazy Weed Attack#
2485,0,0,24:28:32:36:40,0,0,0,99,0,0,none,0,7135,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_DEMONIC_FIRE#Demonic Fire#
2486,0,0,30:35:40:45:50,0,0,0,99,0,0,none,0,6216,1,6213,1,6214,1,6215,1,7136,1,0,0,0,0,0,0,0,0,0,0 //GN_FIRE_EXPANSION#Fire Expansion#
2487,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_FIRE_EXPANSION_SMOKE_POWDER#Fire Expansion Smoke Powder#
2488,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_FIRE_EXPANSION_TEAR_GAS#Fire Expansion Tear Gas#
2489,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_FIRE_EXPANSION_ACID#Fire Expansion Acid#
2490,0,0,40:45:50:55:60,0,0,0,99,0,0,none,0,7137,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_HELLS_PLANT#Hell's Plant#
2491,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_HELLS_PLANT_ATK#Hell's Plant Attack#
2492,0,0,40:45:50:55:60,0,0,0,99,0,0,none,0,6217,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_MANDRAGORA#Howling of Mandragora#
2493,0,0,4,0,0,0,99,9,1,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_SLINGITEM#Sling Item#
2494,0,0,5,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_CHANGEMATERIAL#Change Material#
2495,0,0,5:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking#
2496,0,0,5:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb#
2497,0,0,12,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy#
2498,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_SLINGITEM_RANGEMELEEATK#Sling Item Attack#
//2533,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_ODINS_RECALL#Odin's Recall#
2534,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RETURN_TO_ELDICASTES#Return To Eldicastes#
2535,0,0,1,0,0,0,99,0,0,none,0,6377,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store
@ -789,3 +844,47 @@
8238,0,0,20:20:20:25:25:25:30:30:30:35,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //MER_KYRIE
8239,0,0,28:32:36:40:44:48:52:56:60:64,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //MER_BLESSING
8240,15,0,18:21:24:27:30:33:36:39:42:45,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //MER_INCAGI
// Elemental Spirits Skills
8401,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_CIRCLE_OF_FIRE#Circle of Fire#
8402,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_CLOAK#Fire Cloak#
8403,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_MANTLE#Fire Mantle#
8404,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WATER_SCREEN#Water Screen#
8405,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WATER_DROP#Water Drop#
8406,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WATER_BARRIER#Water Barrier#
8407,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WIND_STEP#Wind Step#
8408,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WIND_CURTAIN#Wind Curtain#
8409,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_ZEPHYR#Zephyr#
8410,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_SOLID_SKIN#Solid Skin#
8411,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_STONE_SHIELD#Stone Shield#
8412,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_POWER_OF_GAIA#Power of Gaia#
8413,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_PYROTECHNIC#Pyrotechnic#
8414,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_HEATER#Heater#
8415,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_TROPIC#Tropic#
8416,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_AQUAPLAY#Aqua Play#
8417,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_COOLER#Cooler#
8418,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_CHILLY_AIR#Cool Air#
8419,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_GUST#Gust#
8420,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_BLAST#Blast#
8421,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WILD_STORM#Wild Storm#
8422,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_PETROLOGY#Petrology#
8423,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_CURSED_SOIL#Cursed Soil#
8424,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_UPHEAVAL#Upheaval#
8425,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_ARROW#Fire Arrow#
8426,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_BOMB#Fire Bomb#
8427,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_BOMB_ATK#Fire Bomb Attack#
8428,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_WAVE#Fire Wave#
8429,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_FIRE_WAVE_ATK#Fire Wave Attack#
8430,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_ICE_NEEDLE#Ice Needle#
8431,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WATER_SCREW#Water Screw#
8432,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WATER_SCREW_ATK#Water Screw Attack#
8433,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_TIDAL_WEAPON#Tidal Weapon#
8434,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_WIND_SLASH#Wind Slasher#
8435,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_HURRICANE#Hurricane Rage#
8436,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_HURRICANE_ATK#Hurricane Rage Attack#
8437,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_TYPOON_MIS#Typhoon Missile#
8438,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_TYPOON_MIS_ATK#Typhoon Missile Attack#
8439,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_STONE_HAMMER#Stone Hammer#
8440,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_ROCK_CRUSHER#Rock Launcher#
8441,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_ROCK_CRUSHER_ATK#Rock Launcher Attack#
8442,0,0,80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //EL_STONE_RAIN#Stone Rain#

File diff suppressed because it is too large Load Diff

View File

@ -128,12 +128,36 @@
2418,0xdb, , 0, 5, 300,enemy, 0x800 //WM_SEVERE_RAINSTORM
2419,0xde, , 0, 1,1000,enemy, 0x010 //WM_POEMOFNETHERWORLD
2443,0xdc, , 0, 0,1000,enemy, 0x00A //SO_FIREWALK
2444,0xdd, , 0, 0,1000,enemy, 0x00A //SO_ELECTRICWALK
2446,0x86, , 0, 3:3:3:4:4,1000,enemy, 0x018 //SO_EARTHGRAVE
2447,0x86, , 0, 3:3:3:4:4,1000,enemy, 0x018 //SO_DIAMONDDUST
2449,0xdf, , 0, 3:3:4:4:5,500,enemy, 0x018 //SO_PSYCHIC_WAVE
2450,0xe0, , 3, 0, 500,enemy, 0x010 //SO_CLOUD_KILL
2452,0xe4, , 0, 3,3000,all, 0x010 //SO_WARMER
2465,0xf1, , 0, 1,1000,all, 0x010 //SO_FIRE_INSIGNIA
2466,0xf2, , 0, 1,1000,all, 0x010 //SO_WATER_INSIGNIA
2467,0xf3, , 0, 1,1000,all, 0x010 //SO_WIND_INSIGNIA
2468,0xf4, , 0, 1,1000,all, 0x010 //SO_EARTH_INSIGNIA
2479,0xe5, , 0, 1,1000,enemy, 0x000 //GN_THORNS_TRAP
2482,0xe6,0x7f, -1, 1, -1,all, 0x000 //GN_WALLOFTHORN
2485,0xe7, , 0, 3,1000,enemy, 0x098 //GN_DEMONIC_FIRE
2487,0xe8, , 0, 3,1000,enemy, 0x000 //GN_FIRE_EXPANSION_SMOKE_POWDER
2488,0xe9, , 0, 3,1000,enemy, 0x000 //GN_FIRE_EXPANSION_TEAR_GAS
2490,0xea, , 0, 1,1000,all, 0x000 //GN_HELLS_PLANT
8208,0x86, , 0, 2,1000,enemy, 0x080 //MA_SHOWER
8209,0x90, , 0, 1,1000,enemy, 0x006 //MA_SKIDTRAP
8210,0x93, , 0, 0,1000,enemy, 0x006 //MA_LANDMINE
8211,0x95, , 0, 1,1000,enemy, 0x006 //MA_SANDMAN
8212,0x97, , 0, 1,1000,enemy, 0x006 //MA_FREEZINGTRAP
8403,0xed, , -1, 1,1000,enemy, 0x018 //EL_FIRE_MANTLE
8406,0xee, , 0, 1, -1,friend,0x018 //EL_WATER_BARRIER
8409,0xef, , 0, 1, -1,friend,0x018 //EL_ZEPHYR
8412,0xf0, , 0, 1, -1,friend,0x018 //EL_POWER_OF_GAIA
10006,0xc1, , 2, 0, -1,guild, 0x040 //GD_LEADERSHIP
10007,0xc2, , 2, 0, -1,guild, 0x040 //GD_GLORYWOUNDS
10008,0xc3, , 2, 0, -1,guild, 0x040 //GD_SOULCOLD

View File

@ -80,6 +80,7 @@ CREATE TABLE IF NOT EXISTS `char` (
`guild_id` int(11) unsigned NOT NULL default '0',
`pet_id` int(11) unsigned NOT NULL default '0',
`homun_id` int(11) unsigned NOT NULL default '0',
`elemental_id` int(11) unsigned NOT NULL default '0'
`hair` tinyint(4) unsigned NOT NULL default '0',
`hair_color` smallint(5) unsigned NOT NULL default '0',
`clothes_color` smallint(5) unsigned NOT NULL default '0',
@ -131,6 +132,29 @@ CREATE TABLE IF NOT EXISTS `charlog` (
`hair_color` int(11) NOT NULL default '0'
) ENGINE=MyISAM;
--
-- Table structure for table `elemental`
--
CREATE TABLE IF NOT EXISTS `elemental` (
`ele_id` int(11) unsigned NOT NULL auto_increment,
`char_id` int(11) NOT NULL,
`class` mediumint(9) unsigned NOT NULL default '0',
`mode` int(11) unsigned NOT NULL default '1',
`hp` int(12) NOT NULL default '1',
`sp` int(12) NOT NULL default '1',
`max_hp` mediumint(8) unsigned NOT NULL default '0',
`max_sp` mediumint(6) unsigned NOT NULL default '0',
`str` smallint(4) unsigned NOT NULL default '0',
`agi` smallint(4) unsigned NOT NULL default '0',
`vit` smallint(4) unsigned NOT NULL default '0',
`int` smallint(4) unsigned NOT NULL default '0',
`dex` smallint(4) unsigned NOT NULL default '0',
`luk` smallint(4) unsigned NOT NULL default '0',
`life_time` int(11) NOT NULL default '0',
PRIMARY KEY (`ele_id`)
) ENGINE=MyISAM;
--
-- Table structure for table `friends`
--

View File

@ -0,0 +1,26 @@
-- Adds 'I' to `type` in `zenylog`
ALTER TABLE `char` ADD COLUMN `elemental_id` int(11) unsigned NOT NULL default '0';
--
-- Table structure for table `elemental`
--
CREATE TABLE IF NOT EXISTS `elemental` (
`ele_id` int(11) unsigned NOT NULL auto_increment,
`char_id` int(11) NOT NULL,
`class` mediumint(9) unsigned NOT NULL default '0',
`mode` int(11) unsigned NOT NULL default '1',
`hp` int(12) NOT NULL default '1',
`sp` int(12) NOT NULL default '1',
`max_hp` mediumint(8) unsigned NOT NULL default '0',
`max_sp` mediumint(6) unsigned NOT NULL default '0',
`str` smallint(4) unsigned NOT NULL default '0',
`agi` smallint(4) unsigned NOT NULL default '0',
`vit` smallint(4) unsigned NOT NULL default '0',
`int` smallint(4) unsigned NOT NULL default '0',
`dex` smallint(4) unsigned NOT NULL default '0',
`luk` smallint(4) unsigned NOT NULL default '0',
`life_time` int(11) NOT NULL default '0',
PRIMARY KEY (`ele_id`)
) ENGINE=MyISAM;

View File

@ -25,8 +25,8 @@ COMMON_SQL_OBJ = ../common/obj_sql/sql.o
COMMON_H = ../common/sql.h
CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \
obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o
CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h
obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o
CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)

View File

@ -16,6 +16,7 @@
#include "int_guild.h"
#include "int_homun.h"
#include "int_mercenary.h"
#include "int_elemental.h"
#include "int_party.h"
#include "int_storage.h"
#include "char.h"
@ -471,7 +472,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->option != cp->option) ||
(p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) ||
(p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) ||
(p->shield != cp->shield) || (p->head_top != cp->head_top) ||
(p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) ||
(p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
(p->rename != cp->rename) || (p->robe != cp->robe)
)
@ -480,7 +481,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
"`base_exp`='%u', `job_exp`='%u', `zeny`='%d',"
"`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d',"
"`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d',"
"`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',"
"`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d',"
"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
"`delete_date`='%lu',`robe`='%d'"
@ -489,7 +490,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
p->base_exp, p->job_exp, p->zeny,
p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point,
p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id,
p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, p->ele_id,
p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
@ -969,7 +970,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT "
"`char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`,"
"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`hair`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
"`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
@ -1004,28 +1005,29 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 26, SQLDT_INT, &p->guild_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 27, SQLDT_INT, &p->pet_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 28, SQLDT_INT, &p->hom_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_SHORT, &p->hair, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p->weapon, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p->shield, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT, &p->head_top, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_INT, &p->partner_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 44, SQLDT_INT, &p->father, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 45, SQLDT_INT, &p->mother, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->child, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->fame, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_SHORT, &p->robe, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_INT, &p->ele_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p->weapon, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT, &p->shield, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p->head_top, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 44, SQLDT_INT, &p->partner_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 45, SQLDT_INT, &p->father, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL)
)
{
SqlStmt_ShowDebug(stmt);

164
src/char/int_elemental.c Normal file
View File

@ -0,0 +1,164 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include "../common/mmo.h"
#include "../common/malloc.h"
#include "../common/strlib.h"
#include "../common/showmsg.h"
#include "../common/socket.h"
#include "../common/utils.h"
#include "../common/sql.h"
#include "char.h"
#include "inter.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool mapif_elemental_save(struct s_elemental* ele) {
bool flag = true;
if( ele->elemental_id == 0 ) { // Create new DB entry
if( SQL_ERROR == Sql_Query(sql_handle,
"INSERT INTO `elemental` (`char_id`,`class`,`mode`,`hp`,`sp`,`max_hp`,`max_sp`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`life_time`)"
"VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%u')",
ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->str, ele->agi, ele->vit, ele->int_, ele->dex, ele->luk, ele->life_time) )
{
Sql_ShowDebug(sql_handle);
flag = false;
}
else
ele->elemental_id = (int)Sql_LastInsertId(sql_handle);
} else if( SQL_ERROR == Sql_Query(sql_handle,
"UPDATE `elemental` SET `char_id` = '%d', `class` = '%d', `mode` = '%d', `hp` = '%d', `sp` = '%d',"
"`max_hp` = '%d', `max_sp` = '%d', `str` = '%d', `agi` = '%d', `vit` = '%d', `int` = '%d', `dex` = '%d',"
"`luk` = '%d', `life_time` = '%u' WHERE `ele_id` = '%d'",
ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->str, ele->agi,
ele->vit, ele->int_, ele->dex, ele->luk, ele->life_time, ele->elemental_id) )
{ // Update DB entry
Sql_ShowDebug(sql_handle);
flag = false;
}
return flag;
}
bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) {
char* data;
memset(ele, 0, sizeof(struct s_elemental));
ele->elemental_id = ele_id;
ele->char_id = char_id;
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `mode`, `hp`, `sp`, `max_hp`, `max_sp`, `str`, `agi`, `vit`, `int`, `dex`,"
"`luk`, `life_time` FROM `elemental` WHERE `ele_id` = '%d' AND `char_id` = '%d'",
ele_id, char_id) ) {
Sql_ShowDebug(sql_handle);
return false;
}
if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) {
Sql_FreeResult(sql_handle);
return false;
}
Sql_GetData(sql_handle, 0, &data, NULL); ele->class_ = atoi(data);
Sql_GetData(sql_handle, 1, &data, NULL); ele->mode = atoi(data);
Sql_GetData(sql_handle, 2, &data, NULL); ele->hp = atoi(data);
Sql_GetData(sql_handle, 3, &data, NULL); ele->sp = atoi(data);
Sql_GetData(sql_handle, 4, &data, NULL); ele->max_hp = atoi(data);
Sql_GetData(sql_handle, 5, &data, NULL); ele->max_sp = atoi(data);
Sql_GetData(sql_handle, 6, &data, NULL); ele->str = atoi(data);
Sql_GetData(sql_handle, 7, &data, NULL); ele->agi = atoi(data);
Sql_GetData(sql_handle, 8, &data, NULL); ele->vit = atoi(data);
Sql_GetData(sql_handle, 9, &data, NULL); ele->int_ = atoi(data);
Sql_GetData(sql_handle, 10, &data, NULL); ele->dex = atoi(data);
Sql_GetData(sql_handle, 11, &data, NULL); ele->luk = atoi(data);
Sql_GetData(sql_handle, 12, &data, NULL); ele->life_time = atoi(data);
Sql_FreeResult(sql_handle);
if( save_log )
ShowInfo("Elemental loaded (%d - %d).\n", ele->elemental_id, ele->char_id);
return true;
}
bool mapif_elemental_delete(int ele_id) {
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `elemental` WHERE `ele_id` = '%d'", ele_id) ) {
Sql_ShowDebug(sql_handle);
return false;
}
return true;
}
#ifndef TXT_SQL_CONVERT
static void mapif_elemental_send(int fd, struct s_elemental *ele, unsigned char flag) {
int size = sizeof(struct s_elemental) + 5;
WFIFOHEAD(fd,size);
WFIFOW(fd,0) = 0x387c;
WFIFOW(fd,2) = size;
WFIFOB(fd,4) = flag;
memcpy(WFIFOP(fd,5),ele,sizeof(struct s_elemental));
WFIFOSET(fd,size);
}
static void mapif_parse_elemental_create(int fd, struct s_elemental* ele) {
bool result = mapif_elemental_save(ele);
mapif_elemental_send(fd, ele, result);
}
static void mapif_parse_elemental_load(int fd, int ele_id, int char_id) {
struct s_elemental ele;
bool result = mapif_elemental_load(ele_id, char_id, &ele);
mapif_elemental_send(fd, &ele, result);
}
static void mapif_elemental_deleted(int fd, unsigned char flag) {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x387d;
WFIFOB(fd,2) = flag;
WFIFOSET(fd,3);
}
static void mapif_parse_elemental_delete(int fd, int ele_id) {
bool result = mapif_elemental_delete(ele_id);
mapif_elemental_deleted(fd, result);
}
static void mapif_elemental_saved(int fd, unsigned char flag) {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x387e;
WFIFOB(fd,2) = flag;
WFIFOSET(fd,3);
}
static void mapif_parse_elemental_save(int fd, struct s_elemental* ele) {
bool result = mapif_elemental_save(ele);
mapif_elemental_saved(fd, result);
}
int inter_elemental_sql_init(void) {
return 0;
}
void inter_elemental_sql_final(void) {
return;
}
/*==========================================
* Inter Packets
*------------------------------------------*/
int inter_elemental_parse_frommap(int fd) {
unsigned short cmd = RFIFOW(fd,0);
switch( cmd ) {
case 0x307c: mapif_parse_elemental_create(fd, (struct s_elemental*)RFIFOP(fd,4)); break;
case 0x307d: mapif_parse_elemental_load(fd, (int)RFIFOL(fd,2), (int)RFIFOL(fd,6)); break;
case 0x307e: mapif_parse_elemental_delete(fd, (int)RFIFOL(fd,2)); break;
case 0x307f: mapif_parse_elemental_save(fd, (struct s_elemental*)RFIFOP(fd,4)); break;
default:
return 0;
}
return 1;
}
#endif //TXT_SQL_CONVERT

15
src/char/int_elemental.h Normal file
View File

@ -0,0 +1,15 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _INT_ELEMENTAL_SQL_H_
#define _INT_ELEMENTAL_SQL_H_
struct s_elemental;
int inter_elemental_sql_init(void);
void inter_elemental_sql_final(void);
int inter_elemental_parse_frommap(int fd);
bool mapif_elemental_delete(int ele_id);
#endif /* _INT_ELEMENTAL_SQL_H_ */

View File

@ -19,6 +19,7 @@
#include "int_mail.h"
#include "int_auction.h"
#include "int_quest.h"
#include "int_elemental.h"
#include <stdio.h>
#include <string.h>
@ -50,7 +51,7 @@ int inter_recv_packet_length[] = {
-1, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040-
-1,-1,10,10, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus]
6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish]
-1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3070- Mercenary packets [Zephyrus]
-1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil]
48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3080-
-1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
};
@ -295,6 +296,7 @@ int inter_init_sql(const char *file)
inter_pet_sql_init();
inter_homunculus_sql_init();
inter_mercenary_sql_init();
inter_elemental_sql_init();
inter_accreg_sql_init();
inter_mail_sql_init();
inter_auction_sql_init();
@ -313,6 +315,7 @@ void inter_final(void)
inter_pet_sql_final();
inter_homunculus_sql_final();
inter_mercenary_sql_final();
inter_elemental_sql_init();
inter_mail_sql_final();
inter_auction_sql_final();
@ -723,6 +726,7 @@ int inter_parse_frommap(int fd)
|| inter_pet_parse_frommap(fd)
|| inter_homunculus_parse_frommap(fd)
|| inter_mercenary_parse_frommap(fd)
|| inter_elemental_parse_frommap(fd)
|| inter_mail_parse_frommap(fd)
|| inter_auction_parse_frommap(fd)
|| inter_quest_parse_frommap(fd)

View File

@ -154,6 +154,14 @@
#define MAX_MERCSKILL 40
#define MAX_MERCENARY_CLASS 44
//Elemental System
#define MAX_ELEMENTALSKILL 42
#define EL_SKILLBASE 8401
#define MAX_ELESKILLTREE 3
#define MAX_ELEMENTAL_CLASS 12
#define EL_CLASS_BASE 2114
#define EL_CLASS_MAX (EL_CLASS_BASE+MAX_ELEMENTAL_CLASS-1)
enum item_types {
IT_HEALING = 0,
IT_UNKNOWN, //1
@ -292,6 +300,15 @@ struct s_mercenary {
unsigned int life_time;
};
struct s_elemental {
int elemental_id;
int char_id;
short class_;
int mode;
int hp, sp, max_hp, max_sp, str, agi, vit, int_, dex, luk;
int life_time;
};
struct s_friend {
int account_id;
int char_id;
@ -324,7 +341,7 @@ struct mmo_charstatus {
short manner;
unsigned char karma;
short hair,hair_color,clothes_color;
int party_id,guild_id,pet_id,hom_id,mer_id;
int party_id,guild_id,pet_id,hom_id,mer_id,ele_id;
int fame;
// Mercenary Guilds Rank

View File

@ -31,7 +31,7 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
storage.o skill.o atcommand.o battle.o battleground.o \
intif.o trade.o party.o vending.o guild.o pet.o \
log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \
buyingstore.o searchstore.o duel.o pc_groups.o
buyingstore.o searchstore.o duel.o pc_groups.o elemental.o
MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
obj_sql/mapreg_sql.o
MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
@ -41,7 +41,7 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \
buyingstore.h searchstore.h duel.h pc_groups.h \
config/core.h config/renewal.h config/secure.h config/const.h \
config/classes/general.h config/classes/swordsman.h
config/classes/general.h config/classes/swordsman.h elemental.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)

View File

@ -34,6 +34,7 @@
#include "homunculus.h"
#include "mail.h"
#include "mercenary.h"
#include "elemental.h"
#include "party.h"
#include "guild.h"
#include "script.h"
@ -3764,6 +3765,7 @@ ACMD_FUNC(reloadmobdb)
read_petdb();
merc_reload();
read_mercenarydb();
reload_elementaldb();
clif_displaymessage(fd, msg_txt(98)); // Monster database has been reloaded.
return 0;
@ -3777,6 +3779,7 @@ ACMD_FUNC(reloadskilldb)
nullpo_retr(-1, sd);
skill_reload();
merc_skill_reload();
reload_elemental_skilldb();
read_mercenary_skilldb();
clif_displaymessage(fd, msg_txt(99)); // Skill database has been reloaded.

View File

@ -18,6 +18,7 @@
#include "skill.h"
#include "homunculus.h"
#include "mercenary.h"
#include "elemental.h"
#include "mob.h"
#include "itemdb.h"
#include "clif.h"
@ -103,6 +104,7 @@ int battle_gettarget(struct block_list* bl)
case BL_PET: return ((struct pet_data*)bl)->target_id;
case BL_HOM: return ((struct homun_data*)bl)->ud.target;
case BL_MER: return ((struct mercenary_data*)bl)->ud.target;
case BL_ELEM: return ((struct elemental_data*)bl)->ud.target;
}
return 0;
}
@ -299,8 +301,7 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
}
ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
if (sc && sc->count)
{
if (sc && sc->count) {
if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE)
ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND)
@ -308,8 +309,27 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER)
ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
}
if( atk_elem == ELE_FIRE && tsc && tsc->count && tsc->data[SC_SPIDERWEB] )
{
if( target && target->type == BL_SKILL ) {
if( atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN ) {
struct skill_unit *su = (struct skill_unit*)target;
struct skill_unit_group *sg;
struct block_list *src;
int x,y;
if( !su || !su->alive || (sg = su->group) == NULL || !sg || sg->val3 == -1 ||
(src = map_id2bl(su->val2)) == NULL || status_isdead(src) )
return 0;
if( sg->unit_id != UNT_FIREWALL ) {
x = sg->val3 >> 16;
y = sg->val3 & 0xffff;
skill_unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1);
sg->val3 = -1;
sg->limit = DIFF_TICK(gettick(),sg->tick)+300;
}
}
}
if( atk_elem == ELE_FIRE && tsc && tsc->count && tsc->data[SC_SPIDERWEB] ){
tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
damage <<= 1; // double damage
@ -932,6 +952,8 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
case W_DAGGER:
if((skill = pc_checkskill(sd,SM_SWORD)) > 0)
damage += (skill * 4);
if((skill = pc_checkskill(sd,GN_TRAINING_SWORD)) > 0)
damage += skill * 10;
break;
case W_2HSWORD:
#ifdef RENEWAL
@ -1486,15 +1508,27 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
if(sd && pc_checkskill(sd,AS_SONICACCEL)>0)
hitrate += hitrate * 50 / 100;
break;
case MC_CARTREVOLUTION:
case GN_CART_TORNADO:
case GN_CARTCANNON:
if( sd && pc_checkskill(sd, GN_REMODELING_CART) )
hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4;
break;
case GC_VENOMPRESSURE:
hitrate += 10 + 4 * skill_lv;
break;
}
// Weaponry Research hidden bonus
if (sd && (skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0)
hitrate += hitrate * ( 2 * skill ) / 100;
if( sd ) {
// Weaponry Research hidden bonus
if ((skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0)
hitrate += hitrate * ( 2 * skill ) / 100;
if( (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) &&
(skill = pc_checkskill(sd, GN_TRAINING_SWORD))>0 )
hitrate += 3 * skill;
}
hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
if(rnd()%100 >= hitrate)
@ -2238,6 +2272,76 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
case WM_SOUND_OF_DESTRUCTION:
skillratio += 400;
break;
case GN_CART_TORNADO:
if( sd )
skillratio += 50 * skill_lv + pc_checkskill(sd, GN_REMODELING_CART) * 100 - 100;
if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
if( sc && sc->data[SC_GN_CARTBOOST] )
skillratio += 10 * sc->data[SC_GN_CARTBOOST]->val1;
break;
case GN_CARTCANNON:
if( sd ) skillratio += 250 + 50 * skill_lv + pc_checkskill(sd, GN_REMODELING_CART) * (sstatus->int_ / 2);
if( sc && sc->data[SC_GN_CARTBOOST] )
skillratio += 10 * sc->data[SC_GN_CARTBOOST]->val1;
break;
case GN_SPORE_EXPLOSION:
skillratio += 200 + 100 * skill_lv;
break;
case GN_CRAZYWEED_ATK:
skillratio += 400 + 100 * skill_lv;
break;
case GN_SLINGITEM_RANGEMELEEATK:
if( sd ) {
switch( sd->itemid ) {
case 13260: // Apple Bomob
case 13261: // Coconut Bomb
case 13262: // Melon Bomb
case 13263: // Pinapple Bomb
skillratio += 400; // Unconfirded
break;
case 13264: // Banana Bomb 2000%
skillratio += 1900;
break;
case 13265: skillratio -= 75; break; // Black Lump 25%
case 13266: skillratio -= 25; break; // Hard Black Lump 75%
case 13267: skillratio += 100; break; // Extremely Hard Black Lump 200%
}
} else
skillratio += 300; // Bombs
break;
case SO_VARETYR_SPEAR: //Assumed Formula.
skillratio += -100 + 200 * ( sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 1 );
if( sc && sc->data[SC_BLAST_OPTION] )
skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100;
break;
// Physical Elemantal Spirits Attack Skills
case EL_CIRCLE_OF_FIRE:
case EL_FIRE_BOMB_ATK:
case EL_STONE_RAIN:
skillratio += 200;
break;
case EL_FIRE_WAVE_ATK:
skillratio += 500;
break;
case EL_TIDAL_WEAPON:
skillratio += 1400;
break;
case EL_WIND_SLASH:
skillratio += 100;
break;
case EL_HURRICANE:
skillratio += 600;
break;
case EL_TYPOON_MIS:
case EL_WATER_SCREW_ATK:
skillratio += 900;
break;
case EL_STONE_HAMMER:
skillratio += 400;
break;
case EL_ROCK_CRUSHER:
skillratio += 700;
break;
}
ATK_RATE(skillratio);
@ -2920,7 +3024,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
{
int i, nk;
short s_ele;
short s_ele = 0;
unsigned int skillratio = 100; //Skill dmg modifiers.
struct map_session_data *sd, *tsd;
@ -2954,16 +3058,38 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
//Initialize variables that will be used afterwards
s_ele = skill_get_ele(skill_num, skill_lv);
if( skill_num == SO_PSYCHIC_WAVE ) {
struct status_change *sc = status_get_sc(src);
if( sc && sc->count && ( sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] ||
sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ) ) {
if( sc->data[SC_HEATER_OPTION] ) s_ele = sc->data[SC_HEATER_OPTION]->val4;
else if( sc->data[SC_COOLER_OPTION] ) s_ele = sc->data[SC_COOLER_OPTION]->val4;
else if( sc->data[SC_BLAST_OPTION] ) s_ele = sc->data[SC_BLAST_OPTION]->val3;
else if( sc->data[SC_CURSED_SOIL_OPTION] ) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4;
} else {
//#HALP# I didn't get a clue on how to do this without unnecessary adding a overhead of status_change on every call while this is a per-skill case.
//, - so i duplicated this code. make yourself comfortable to fix if you have any better ideas.
//Initialize variables that will be used afterwards
s_ele = skill_get_ele(skill_num, skill_lv);
if (s_ele == -1) // pl=-1 : the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
else if (s_ele == -2) //Use status element
s_ele = status_get_attack_sc_element(src,status_get_sc(src));
else if( s_ele == -3 ) //Use random element
s_ele = rnd()%ELE_MAX;
}
} else {
//Initialize variables that will be used afterwards
s_ele = skill_get_ele(skill_num, skill_lv);
if (s_ele == -1) // pl=-1 : the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
else if (s_ele == -2) //Use status element
s_ele = status_get_attack_sc_element(src,status_get_sc(src));
else if( s_ele == -3 ) //Use random element
s_ele = rnd()%ELE_MAX;
if (s_ele == -1) // pl=-1 : the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
else if (s_ele == -2) //Use status element
s_ele = status_get_attack_sc_element(src,status_get_sc(src));
else if( s_ele == -3 ) //Use random element
s_ele = rnd()%ELE_MAX;
}
//Set miscellaneous data that needs be filled
if(sd) {
sd->state.arrow_atk = 0;
@ -3334,6 +3460,24 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
else
skillratio += 110 + 20 * skill_lv;
break;
// Magical Elemental Spirits Attack Skills
case EL_FIRE_MANTLE:
case EL_WATER_SCREW:
skillratio += 900;
break;
case EL_FIRE_ARROW:
case EL_ROCK_CRUSHER_ATK:
skillratio += 200;
break;
case EL_FIRE_BOMB:
case EL_ICE_NEEDLE:
case EL_HURRICANE_ATK:
skillratio += 400;
break;
case EL_FIRE_WAVE:
case EL_TYPOON_MIS_ATK:
skillratio += 1100;
break;
}
@ -3493,6 +3637,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
else if( map[target->m].flag.battleground )
ad.damage=battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
if( skill_num == SO_VARETYR_SPEAR ) { // Physical damage.
struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
ad.damage += wd.damage;
}
return ad;
}
@ -3675,7 +3826,15 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if (sd) md.damage = md.damage + status_get_hp(src);
status_set_sp(src, 0, 0);
break;
case GN_THORNS_TRAP:
md.damage = 100 + 200 * skill_lv + sstatus->int_;
break;
case GN_BLOOD_SUCKER:
md.damage = 200 + 100 * skill_lv + sstatus->int_;
break;
case GN_HELLS_PLANT_ATK:
md.damage = sstatus->int_ * 4 * skill_lv * (10 / (10 - pc_checkskill(sd,AM_CANNIBALIZE)));//Need accurate official formula. [Rytech]
break;
}
if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
@ -4168,24 +4327,38 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
map_freeblock_lock();
battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion);
if( tsc ) {
if( tsc->data[SC_DEVOTION] ) {
struct status_change_entry *sce = tsc->data[SC_DEVOTION];
struct block_list *d_bl = map_id2bl(sce->val1);
if( tsc && tsc->data[SC_DEVOTION] )
{
struct status_change_entry *sce = tsc->data[SC_DEVOTION];
struct block_list *d_bl = map_id2bl(sce->val1);
if( d_bl && (
(d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) ||
(d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
) && check_distance_bl(target, d_bl, sce->val3) )
{
clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0);
status_fix_damage(NULL, d_bl, damage, 0);
}
else
status_change_end(target, SC_DEVOTION, INVALID_TIMER);
if( d_bl && (
(d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) ||
(d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
) && check_distance_bl(target, d_bl, sce->val3) )
{
clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0);
status_fix_damage(NULL, d_bl, damage, 0);
}
else
status_change_end(target, SC_DEVOTION, INVALID_TIMER);
} else if( tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC ) {
struct elemental_data *ed = ((TBL_PC*)target)->ed;
if( ed ) {
clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6);
skill_attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag);
}
} else if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) {
struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);
if( e_bl && !status_isdead(e_bl) ) {
clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2);
status_damage(target,e_bl,damage,0,0,0);
// Just show damage in target.
clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 );
return ATK_NONE;
}
}
}
if (sc && sc->data[SC_AUTOSPELL] && rnd()%100 < sc->data[SC_AUTOSPELL]->val4) {
int sp = 0;
int skillid = sc->data[SC_AUTOSPELL]->val2;
@ -4314,6 +4487,10 @@ struct block_list* battle_get_master(struct block_list *src)
if (((TBL_MER*)src)->master)
src = (struct block_list*)((TBL_MER*)src)->master;
break;
case BL_ELEM:
if (((TBL_ELEM*)src)->master)
src = (struct block_list*)((TBL_ELEM*)src)->master;
break;
case BL_SKILL:
if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id)
src = map_id2bl(((TBL_SKILL*)src)->group->src_id);
@ -4409,6 +4586,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
//Valid targets with no special checks here.
case BL_MER:
case BL_HOM:
case BL_ELEM:
break;
//All else not specified is an invalid target.
default:

View File

@ -22,6 +22,7 @@
#include "homunculus.h"
#include "instance.h"
#include "mercenary.h"
#include "elemental.h"
#include "chrif.h"
#include "quest.h"
#include "storage.h"
@ -307,6 +308,8 @@ int chrif_save(struct map_session_data *sd, int flag)
merc_save(sd->hd);
if( sd->md && mercenary_get_lifetime(sd->md) > 0 )
mercenary_save(sd->md);
if( sd->ed && elemental_get_lifetime(sd->ed) > 0 )
elemental_save(sd->ed);
if( sd->save_quest )
intif_quest_save(sd);

View File

@ -36,6 +36,7 @@
#include "homunculus.h"
#include "instance.h"
#include "mercenary.h"
#include "elemental.h"
#include "log.h"
#include "clif.h"
#include "mail.h"
@ -273,7 +274,7 @@ static inline unsigned char clif_bl_type(struct block_list *bl) {
case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
case BL_HOM: return 0x8; //NPC_HOM_TYPE
case BL_MER: return 0x9; //NPC_MERSOL_TYPE
// case BL_ELEM: return 0xA; //NPC_ELEMENTAL_TYPE
case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE
default: return 0x1; //NPC_TYPE
}
}
@ -5193,44 +5194,60 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid , int
/// 4 = GN_MIX_COOKING
/// 5 = GN_MAKEBOMB
/// 6 = GN_S_PHARMACY
void clif_cooking_list(struct map_session_data *sd, int trigger)
void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, int qty, int list_type)
{
int fd;
int i, c;
int view;
nullpo_retv(sd);
fd = sd->fd;
WFIFOHEAD(fd, 6 + 2*MAX_SKILL_PRODUCE_DB);
WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB);
WFIFOW(fd,0) = 0x25a;
WFIFOW(fd,4) = 1; // list type
WFIFOW(fd,4) = list_type; // list type
c = 0;
for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ )
{
if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, 1) )
for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) {
if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) )
continue;
if( (view = itemdb_viewid(skill_produce_db[i].nameid)) > 0 )
WFIFOW(fd, 6+2*c)= view;
WFIFOW(fd, 6 + 2 * c) = view;
else
WFIFOW(fd, 6+2*c)= skill_produce_db[i].nameid;
WFIFOW(fd, 6 + 2 * c) = skill_produce_db[i].nameid;
c++;
}
WFIFOW(fd,2) = 6 + 2*c;
WFIFOSET(fd,WFIFOW(fd,2));
//TODO: replace with proper solution
if( c > 0 )
{
sd->menuskill_id = AM_PHARMACY;
if( skill_id == AM_PHARMACY ) { // Only send it while Cooking else check for c.
WFIFOW(fd,2) = 6 + 2 * c;
WFIFOSET(fd,WFIFOW(fd,2));
}
if( c > 0 ) {
sd->menuskill_id = skill_id;
sd->menuskill_val = trigger;
if( skill_id != AM_PHARMACY ) {
sd->menuskill_val2 = qty; // amount.
WFIFOW(fd,2) = 6 + 2 * c;
WFIFOSET(fd,WFIFOW(fd,2));
}
} else {
clif_menuskill_clear(sd);
if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking.
// It fails.
#if PACKETVER >= 20090922
clif_msg_skill(sd,skill_id,0x625);
#else
WFIFOW(fd,2) = 6 + 2 * c;
WFIFOSET(fd,WFIFOW(fd,2));
#endif
}
}
}
/// Notifies clients of a status change.
/// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)]
/// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs]
@ -8107,11 +8124,12 @@ void clif_refresh(struct map_session_data *sd)
clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
if(merc_is_hom_active(sd->hd))
clif_send_homdata(sd,SP_ACK,0);
if( sd->md )
{
if( sd->md ) {
clif_mercenary_info(sd);
clif_mercenary_skillblock(sd);
}
if( sd->ed )
clif_elemental_info(sd);
map_foreachinrange(clif_getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif_weather_check(sd);
if( sd->chatID )
@ -8255,6 +8273,9 @@ void clif_charnameack (int fd, struct block_list *bl)
// memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH);
// break;
return;
case BL_ELEM:
memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH);
break;
default:
ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id);
return;
@ -9082,14 +9103,22 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
}
if( sd->md )
{
if( sd->md ) {
map_addblock(&sd->md->bl);
clif_spawn(&sd->md->bl);
clif_mercenary_info(sd);
clif_mercenary_skillblock(sd);
}
if( sd->ed ) {
map_addblock(&sd->ed->bl);
clif_spawn(&sd->ed->bl);
clif_elemental_info(sd);
clif_elemental_updatestatus(sd,SP_HP);
clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.matk_max);
clif_elemental_updatestatus(sd,SP_SP);
}
if(sd->state.connect_new) {
int lv;
sd->state.connect_new = 0;
@ -10587,15 +10616,13 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
return; // On basilica only caster can use Basilica again to stop it.
if( sd->menuskill_id )
{
if( sd->menuskill_id == SA_TAMINGMONSTER )
sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture.
else if( sd->menuskill_id != SA_AUTOSPELL )
if( sd->menuskill_id ) {
if( sd->menuskill_id == SA_TAMINGMONSTER ) {
clif_menuskill_clear(sd); //Cancel pet capture.
} else if( sd->menuskill_id != SA_AUTOSPELL )
return; //Can't use skills while a menu is open.
}
if( sd->skillitem == skillnum )
{
if( sd->skillitem == skillnum ) {
if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
if( !(tmp&INF_SELF_SKILL) )
@ -10606,15 +10633,12 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
sd->skillitem = sd->skillitemlv = 0;
if( skillnum >= GD_SKILLBASE )
{
if( skillnum >= GD_SKILLBASE ) {
if( sd->state.gmaster_flag )
skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum);
else
skilllv = 0;
}
else
{
} else {
tmp = pc_checkskill(sd, skillnum);
if( skilllv > tmp )
skilllv = tmp;
@ -10661,10 +10685,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho
if( sd->ud.skilltimer != INVALID_TIMER )
return;
if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 )
{
if( sd->skillitem != skillnum )
{
if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
if( sd->skillitem != skillnum ) {
clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0);
return;
}
@ -10676,28 +10698,23 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho
if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
return; // On basilica only caster can use Basilica again to stop it.
if( sd->menuskill_id )
{
if( sd->menuskill_id == SA_TAMINGMONSTER )
sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture.
else if( sd->menuskill_id != SA_AUTOSPELL )
if( sd->menuskill_id ) {
if( sd->menuskill_id == SA_TAMINGMONSTER ) {
clif_menuskill_clear(sd); //Cancel pet capture.
} else if( sd->menuskill_id != SA_AUTOSPELL )
return; //Can't use skills while a menu is open.
}
pc_delinvincibletimer(sd);
if( sd->skillitem == skillnum )
{
if( sd->skillitem == skillnum ) {
if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
unit_skilluse_pos(&sd->bl, x, y, skillnum, skilllv);
}
else
{
} else {
int lv;
sd->skillitem = sd->skillitemlv = 0;
if( (lv = pc_checkskill(sd, skillnum)) > 0 )
{
if( (lv = pc_checkskill(sd, skillnum)) > 0 ) {
if( skilllv > lv )
skilllv = lv;
unit_skilluse_pos(&sd->bl, x, y, skillnum,skilllv);
@ -10759,9 +10776,8 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd)
if(skill_num != sd->menuskill_id)
return;
if( pc_cant_act(sd) )
{
sd->menuskill_id = sd->menuskill_val = 0;
if( pc_cant_act(sd) ) {
clif_menuskill_clear(sd);
return;
}
@ -10795,12 +10811,12 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
return;
}
if( skill_can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) )
skill_produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -10813,24 +10829,22 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
/// 4 = GN_MIX_COOKING
/// 5 = GN_MAKEBOMB
/// 6 = GN_S_PHARMACY
void clif_parse_Cooking(int fd,struct map_session_data *sd)
{
//int type = RFIFOW(fd,2);
void clif_parse_Cooking(int fd,struct map_session_data *sd) {
int type = RFIFOW(fd,2);
int nameid = RFIFOW(fd,4);
if( sd->menuskill_id != AM_PHARMACY ) {
int amount = sd->menuskill_val2?sd->menuskill_val2:1;
if( type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY )
return;
}
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
return;
}
if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, 1) )
skill_produce_mix(sd,0,nameid,0,0,0,1);
sd->menuskill_val = sd->menuskill_id = 0;
if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, amount) )
skill_produce_mix(sd,sd->menuskill_id,nameid,0,0,0,amount);
clif_menuskill_clear(sd);
}
@ -10843,11 +10857,11 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
return;
}
skill_repairweapon(sd,RFIFOW(fd,2));
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -10862,12 +10876,12 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
return;
}
idx = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
skill_weaponrefine(sd, idx-2);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -10952,13 +10966,12 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd)
if (sd->menuskill_id != MC_IDENTIFY)
return;
if( idx == -1 )
{// cancel pressed
sd->menuskill_val = sd->menuskill_id = 0;
if( idx == -1 ) {// cancel pressed
clif_menuskill_clear(sd);
return;
}
skill_identify(sd,idx-2);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -10969,7 +10982,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
return;
}
switch( sd->menuskill_id ) {
@ -10990,7 +11003,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd)
break;
}
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -11001,7 +11014,7 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd)
if (sd->menuskill_id != SA_AUTOSPELL)
return;
skill_autospell(sd,RFIFOL(fd,2));
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -12074,7 +12087,7 @@ void clif_parse_SelectEgg(int fd, struct map_session_data *sd)
return;
}
pet_select_egg(sd,RFIFOW(fd,2)-2);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -13038,7 +13051,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
// clif_misceffect2(&sd->bl, 0x1b0);
// clif_misceffect2(&sd->bl, 0x21f);
clif_feel_info(sd, i, 0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
@ -15051,6 +15064,94 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd)
sd->state.lesseffect = ( isLess != 0 );
}
/// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b*
void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) {
int n = (RFIFOW(fd,2)-12) / 4;
int type = RFIFOL(fd,4);
int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK
unsigned short* item_list = (unsigned short*)RFIFOP(fd,12);
if( sd->state.trading || sd->npc_shopid )
return;
if( flag == 0 || n == 0) {
clif_menuskill_clear(sd);
return; // Canceled by player.
}
if( sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL ) {
clif_menuskill_clear(sd);
return; // Prevent hacking.
}
switch( type ) {
case 0: // Change Material
skill_changematerial(sd,n,item_list);
break;
case 1: // Level 1: Pure to Rough
case 2: // Level 2: Rough to Pure
skill_elementalanalysis(sd,n,type,item_list);
break;
}
clif_menuskill_clear(sd);
return;
}
/*==========================================
* Elemental System
*==========================================*/
void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
struct elemental_data *ed;
struct status_data *status;
int fd;
if( sd == NULL || (ed = sd->ed) == NULL )
return;
fd = sd->fd;
status = &ed->battle_status;
WFIFOHEAD(fd,8);
WFIFOW(fd,0) = 0x81e;
WFIFOW(fd,2) = type;
switch( type ) {
case SP_HP:
WFIFOL(fd,4) = status->hp;
break;
case SP_MAXHP:
WFIFOL(fd,4) = status->max_hp;
break;
case SP_SP:
WFIFOL(fd,4) = status->sp;
break;
case SP_MAXSP:
WFIFOL(fd,4) = status->max_sp;
break;
}
WFIFOSET(fd,8);
}
void clif_elemental_info(struct map_session_data *sd) {
int fd;
struct elemental_data *ed;
struct status_data *status;
if( sd == NULL || (ed = sd->ed) == NULL )
return;
fd = sd->fd;
status = &ed->battle_status;
WFIFOHEAD(fd,22);
WFIFOW(fd, 0) = 0x81d;
WFIFOL(fd, 2) = ed->bl.id;
WFIFOL(fd, 6) = status->hp;
WFIFOL(fd,10) = status->max_hp;
WFIFOL(fd,14) = status->sp;
WFIFOL(fd,18) = status->max_sp;
WFIFOSET(fd,22);
}
/// Buying Store System
///
@ -15762,6 +15863,35 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
return 1;
}
/*===========================================
* Skill list for Four Elemental Analysis
* and Change Material skills.
*------------------------------------------*/
int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int skill_lv )
{
#if PACKETVER >= 20090922
int fd;
nullpo_ret(sd);
sd->menuskill_id = skill_id; // To prevent hacking.
sd->menuskill_val = skill_lv;
if( skill_id == GN_CHANGEMATERIAL )
skill_lv = 0; // Changematerial
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x7e3));
WFIFOW(fd,0) = 0x7e3;
WFIFOL(fd,2) = skill_lv;
WFIFOL(fd,4) = 0;
WFIFOSET(fd,packet_len(0x7e3));
#endif
return 1;
}
/**
* Sends a new status without a tick (currently used by the new mounts)
**/
@ -15826,11 +15956,11 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
if( pc_istrading(sd) ) {
clif_skill_fail(sd,sd->ud.skillid,0,0);
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
return;
}
skill_select_menu(sd,RFIFOL(fd,2),RFIFOW(fd,6));
sd->menuskill_val = sd->menuskill_id = 0;
clif_menuskill_clear(sd);
}
/*==========================================
@ -16202,13 +16332,13 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//#0x07C0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#if PACKETVER < 20090617
6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54,
#else // 0x7d9 changed
6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54,
#endif
0, 15, 8, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
0, 15, 8, 6, -1, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0,
//#0x0800
#if PACKETVER < 20091229
@ -16406,6 +16536,7 @@ static int packetdb_readdb(void)
{clif_parse_mercenary_action,"mermenu"},
{clif_parse_progressbar,"progressbar"},
{clif_parse_SkillSelectMenu,"skillselectmenu"},
{clif_parse_ItemListWindowSelected,"itemlistwindowselected"},
#if PACKETVER >= 20091229
{clif_parse_PartyBookingRegisterReq,"bookingregreq"},
{clif_parse_PartyBookingSearchReq,"bookingsearchreq"},

View File

@ -429,7 +429,7 @@ void clif_skill_warppoint(struct map_session_data* sd, short skill_num, short sk
void clif_skill_memomessage(struct map_session_data* sd, int type);
void clif_skill_teleportmessage(struct map_session_data *sd, int type);
void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid, int trigger);
void clif_cooking_list(struct map_session_data *sd, int trigger);
void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, int qty, int list_type);
void clif_produceeffect(struct map_session_data* sd,int flag,int nameid);
@ -714,35 +714,27 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor
**/
void clif_msgtable(int fd, int line);
void clif_msgtable_num(int fd, int line, int num);
/**
* Elemental Converter List
**/
int clif_elementalconverter_list(struct map_session_data *sd);
/**
* Rune Knight
**/
void clif_millenniumshield(struct map_session_data *sd, short shields );
/**
* Warlock
**/
int clif_spellbook_list(struct map_session_data *sd);
/**
* Mechanic
**/
int clif_magicdecoy_list(struct map_session_data *sd, int skill_lv, short x, short y);
/**
* Guilotine Cross
**/
int clif_poison_list(struct map_session_data *sd, int skill_lv);
/**
* Shadow Chaser
**/
int clif_autoshadowspell_list(struct map_session_data *sd);
/**
* New Mounts
**/
int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3);
int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3);
int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int skill_lv );
void clif_elemental_info(struct map_session_data *sd);
void clif_elemental_updatestatus(struct map_session_data *sd, int type);
/**
* Color Table
**/
@ -753,4 +745,7 @@ enum clif_colors {
};
unsigned long color_table[COLOR_MAX];
int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg);
#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
#endif /* _CLIF_H_ */

825
src/map/elemental.c Normal file
View File

@ -0,0 +1,825 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include "../common/cbasetypes.h"
#include "../common/malloc.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/nullpo.h"
#include "../common/mmo.h"
#include "../common/showmsg.h"
#include "../common/utils.h"
#include "log.h"
#include "clif.h"
#include "chrif.h"
#include "intif.h"
#include "itemdb.h"
#include "map.h"
#include "pc.h"
#include "status.h"
#include "skill.h"
#include "mob.h"
#include "pet.h"
#include "battle.h"
#include "party.h"
#include "guild.h"
#include "atcommand.h"
#include "script.h"
#include "npc.h"
#include "trade.h"
#include "unit.h"
#include "elemental.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; // Elemental Database
int elemental_search_index(int class_) {
int i;
ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental_db[i].class_ == class_);
return (i == MAX_ELEMENTAL_CLASS)?-1:i;
}
bool elemental_class(int class_) {
return (bool)(elemental_search_index(class_) > -1);
}
struct view_data * elemental_get_viewdata(int class_) {
int i = elemental_search_index(class_);
if( i < 0 )
return 0;
return &elemental_db[i].vd;
}
int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) {
struct s_elemental ele;
struct s_elemental_db *db;
int i;
nullpo_retr(1,sd);
if( (i = elemental_search_index(class_)) < 0 )
return 0;
db = &elemental_db[i];
memset(&ele,0,sizeof(struct s_elemental));
ele.char_id = sd->status.char_id;
ele.class_ = class_;
ele.mode = EL_MODE_PASSIVE; // Initial mode
ele.hp = db->status.max_hp;
ele.sp = db->status.max_sp;
ele.life_time = lifetime;
// Request Char Server to create this elemental
intif_elemental_create(&ele);
return 1;
}
int elemental_get_lifetime(struct elemental_data *ed) {
const struct TimerData * td;
if( ed == NULL || ed->summon_timer == INVALID_TIMER )
return 0;
td = get_timer(ed->summon_timer);
return (td != NULL) ? DIFF_TICK(td->tick, gettick()) : 0;
}
int elemental_save(struct elemental_data *ed) {
ed->elemental.hp = ed->battle_status.hp;
ed->elemental.sp = ed->battle_status.sp;
ed->elemental.life_time = elemental_get_lifetime(ed);
intif_elemental_save(&ed->elemental);
return 1;
}
static int elemental_summon_end(int tid, unsigned int tick, int id, intptr data) {
struct map_session_data *sd;
struct elemental_data *ed;
if( (sd = map_id2sd(id)) == NULL )
return 1;
if( (ed = sd->ed) == NULL )
return 1;
if( ed->summon_timer != tid ) {
ShowError("elemental_summon_end %d != %d.\n", ed->summon_timer, tid);
return 0;
}
ed->summon_timer = INVALID_TIMER;
elemental_delete(ed, 0); // Elemental's summon time is over.
return 0;
}
void elemental_summon_stop(struct elemental_data *ed) {
nullpo_retv(ed);
if( ed->summon_timer != INVALID_TIMER )
delete_timer(ed->summon_timer, elemental_summon_end);
ed->summon_timer = INVALID_TIMER;
}
int elemental_delete(struct elemental_data *ed, int reply) {
struct map_session_data *sd;
nullpo_ret(ed);
sd = ed->master;
ed->elemental.life_time = 0;
elemental_clean_effect(ed);
elemental_summon_stop(ed);
if( !sd )
return unit_free(&ed->bl, 0);
sd->ed = NULL;
sd->status.ele_id = 0;
return unit_remove_map(&ed->bl, 0);
}
void elemental_summon_init(struct elemental_data *ed) {
if( ed->summon_timer == INVALID_TIMER )
ed->summon_timer = add_timer(gettick() + ed->elemental.life_time, elemental_summon_end, ed->master->bl.id, 0);
ed->regen.state.block = 0;
}
int elemental_data_received(struct s_elemental *ele, bool flag) {
struct map_session_data *sd;
struct elemental_data *ed;
struct s_elemental_db *db;
int i = elemental_search_index(ele->class_);
if( (sd = map_charid2sd(ele->char_id)) == NULL )
return 0;
if( !flag || i < 0 ) { // Not created - loaded - DB info
sd->status.ele_id = 0;
return 0;
}
db = &elemental_db[i];
if( !sd->ed ) { // Initialize it after first summon.
sd->ed = ed = (struct elemental_data*)aCalloc(1,sizeof(struct elemental_data));
ed->bl.type = BL_ELEM;
ed->bl.id = npc_get_new_npc_id();
ed->master = sd;
ed->db = db;
memcpy(&ed->elemental, ele, sizeof(struct s_elemental));
status_set_viewdata(&ed->bl, ed->elemental.class_);
ed->vd->head_mid = 10; // Why?
status_change_init(&ed->bl);
unit_dataset(&ed->bl);
ed->ud.dir = sd->ud.dir;
ed->bl.m = sd->bl.m;
ed->bl.x = sd->bl.x;
ed->bl.y = sd->bl.y;
unit_calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
ed->bl.x = ed->ud.to_x;
ed->bl.y = ed->ud.to_y;
map_addiddb(&ed->bl);
status_calc_elemental(ed,1);
ed->last_thinktime = gettick();
ed->summon_timer = INVALID_TIMER;
ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode.
elemental_summon_init(ed);
} else {
memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental));
ed = sd->ed;
}
sd->status.ele_id = ele->elemental_id;
ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode.
if( ed->bl.prev == NULL && sd->bl.prev != NULL ) {
map_addblock(&ed->bl);
clif_spawn(&ed->bl);
clif_elemental_info(sd);
clif_elemental_updatestatus(sd,SP_HP);
clif_hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.matk_max);
clif_elemental_updatestatus(sd,SP_SP);
}
return 1;
}
int elemental_clean_single_effect(struct elemental_data *ed, int skill_num) {
struct block_list *bl;
sc_type type = status_skill2sc(skill_num);
nullpo_ret(ed);
bl = battle_get_master(&ed->bl);
if( type ) {
switch( type ) {
// Just remove status change.
case SC_PYROTECHNIC_OPTION:
case SC_HEATER_OPTION:
case SC_TROPIC_OPTION:
case SC_FIRE_CLOAK_OPTION:
case SC_AQUAPLAY_OPTION:
case SC_WATER_SCREEN_OPTION:
case SC_COOLER_OPTION:
case SC_CHILLY_AIR_OPTION:
case SC_GUST_OPTION:
case SC_WIND_STEP_OPTION:
case SC_BLAST_OPTION:
case SC_WATER_DROP_OPTION:
case SC_WIND_CURTAIN_OPTION:
case SC_WILD_STORM_OPTION:
case SC_PETROLOGY_OPTION:
case SC_SOLID_SKIN_OPTION:
case SC_CURSED_SOIL_OPTION:
case SC_STONE_SHIELD_OPTION:
case SC_UPHEAVAL_OPTION:
case SC_CIRCLE_OF_FIRE_OPTION:
case SC_TIDAL_WEAPON_OPTION:
if( bl ) status_change_end(bl,type,-1); // Master
status_change_end(&ed->bl,type-1,-1); // Elemental Spirit
break;
case SC_ZEPHYR:
if( bl ) status_change_end(bl,type,-1);
break;
}
}
if( skill_get_unit_id(skill_num,0) )
skill_clear_unitgroup(&ed->bl);
return 1;
}
int elemental_clean_effect(struct elemental_data *ed) {
struct map_session_data *sd;
nullpo_ret(ed);
// Elemental side
status_change_end(&ed->bl, SC_TROPIC, INVALID_TIMER);
status_change_end(&ed->bl, SC_HEATER, INVALID_TIMER);
status_change_end(&ed->bl, SC_AQUAPLAY, INVALID_TIMER);
status_change_end(&ed->bl, SC_COOLER, INVALID_TIMER);
status_change_end(&ed->bl, SC_CHILLY_AIR, INVALID_TIMER);
status_change_end(&ed->bl, SC_PYROTECHNIC, INVALID_TIMER);
status_change_end(&ed->bl, SC_FIRE_CLOAK, INVALID_TIMER);
status_change_end(&ed->bl, SC_WATER_DROP, INVALID_TIMER);
status_change_end(&ed->bl, SC_WATER_SCREEN, INVALID_TIMER);
status_change_end(&ed->bl, SC_GUST, INVALID_TIMER);
status_change_end(&ed->bl, SC_WIND_STEP, INVALID_TIMER);
status_change_end(&ed->bl, SC_BLAST, INVALID_TIMER);
status_change_end(&ed->bl, SC_WIND_CURTAIN, INVALID_TIMER);
status_change_end(&ed->bl, SC_WILD_STORM, INVALID_TIMER);
status_change_end(&ed->bl, SC_PETROLOGY, INVALID_TIMER);
status_change_end(&ed->bl, SC_SOLID_SKIN, INVALID_TIMER);
status_change_end(&ed->bl, SC_CURSED_SOIL, INVALID_TIMER);
status_change_end(&ed->bl, SC_STONE_SHIELD, INVALID_TIMER);
status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER);
status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER);
status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER);
skill_clear_unitgroup(&ed->bl);
if( (sd = ed->master) == NULL )
return 0;
// Master side
status_change_end(&sd->bl, SC_TROPIC_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_HEATER_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_AQUAPLAY_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_COOLER_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_CHILLY_AIR_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_PYROTECHNIC_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_FIRE_CLOAK_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_WATER_SCREEN_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_GUST_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_BLAST_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_WIND_CURTAIN_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_WILD_STORM_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_ZEPHYR, INVALID_TIMER);
status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_PETROLOGY_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_SOLID_SKIN_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_CURSED_SOIL_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_STONE_SHIELD_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_UPHEAVAL_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_CIRCLE_OF_FIRE_OPTION, INVALID_TIMER);
status_change_end(&sd->bl, SC_TIDAL_WEAPON_OPTION, INVALID_TIMER);
return 1;
}
int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) {
short skillnum, skilllv;
int i;
nullpo_ret(ed);
nullpo_ret(bl);
if( !ed->master )
return 0;
if( ed->target_id )
elemental_unlocktarget(ed); // Remove previous target.
ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE));
if( i == MAX_ELESKILLTREE )
return 0;
skillnum = ed->db->skill[i].id;
skilllv = ed->db->skill[i].lv;
if( elemental_skillnotok(skillnum, ed) )
return 0;
if( ed->ud.skilltimer != -1 )
return 0;
else if( DIFF_TICK(tick, ed->ud.canact_tick) < 0 )
return 0;
ed->target_id = ed->ud.skilltarget = bl->id; // Set new target
ed->last_thinktime = tick;
// Not in skill range.
if( !battle_check_range(&ed->bl,bl,skill_get_range(skillnum,skilllv)) ) {
// Try to walk to the target.
if( !unit_walktobl(&ed->bl, bl, skill_get_range(skillnum,skilllv), 2) )
elemental_unlocktarget(ed);
else {
// Walking, waiting to be in range. Client don't handle it, then we must handle it here.
int walk_dist = distance_bl(&ed->bl,bl) - skill_get_range(skillnum,skilllv);
ed->ud.skillid = skillnum;
ed->ud.skilllv = skilllv;
if( skill_get_inf(skillnum) & INF_GROUND_SKILL )
ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_pos, ed->bl.id, 0 );
else
ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_id, ed->bl.id, 0 );
}
return 1;
}
//Otherwise, just cast the skill.
if( skill_get_inf(skillnum) & INF_GROUND_SKILL )
unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv);
else
unit_skilluse_id(&ed->bl, bl->id, skillnum, skilllv);
// Reset target.
ed->target_id = 0;
return 1;
}
/*===============================================================
* Action that elemental perform after changing mode.
* Activates one of the skills of the new mode.
*-------------------------------------------------------------*/
int elemental_change_mode_ack(struct elemental_data *ed, int mode) {
struct block_list *bl = &ed->master->bl;
short skillnum, skilllv;
int i;
nullpo_ret(ed);
if( !bl )
return 0;
// Select a skill.
ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&mode));
if( i == MAX_ELESKILLTREE )
return 0;
skillnum = ed->db->skill[i].id;
skilllv = ed->db->skill[i].lv;
if( elemental_skillnotok(skillnum, ed) )
return 0;
if( ed->ud.skilltimer != -1 )
return 0;
else if( DIFF_TICK(gettick(), ed->ud.canact_tick) < 0 )
return 0;
ed->target_id = bl->id; // Set new target
ed->last_thinktime = gettick();
if( skill_get_inf(skillnum) & INF_GROUND_SKILL )
unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv);
else
unit_skilluse_id(&ed->bl,bl->id,skillnum,skilllv);
ed->target_id = 0; // Reset target after casting the skill to avoid continious attack.
return 1;
}
/*===============================================================
* Change elemental mode.
*-------------------------------------------------------------*/
int elemental_change_mode(struct elemental_data *ed, int mode) {
nullpo_ret(ed);
// Remove target
elemental_unlocktarget(ed);
// Removes the effects of the previous mode.
if(ed->elemental.mode != mode ) elemental_clean_effect(ed);
ed->battle_status.mode = ed->elemental.mode = mode;
// Normalize elemental mode to elemental skill mode.
if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill.
else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill.
else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill.
// Use a skill inmediately after every change mode.
if( mode != EL_SKILLMODE_AGGRESSIVE )
elemental_change_mode_ack(ed,mode);
return 1;
}
void elemental_damage(struct elemental_data *ed, struct block_list *src, int hp, int sp) {
if( hp )
clif_elemental_updatestatus(ed->master, SP_HP);
if( sp )
clif_elemental_updatestatus(ed->master, SP_SP);
}
void elemental_heal(struct elemental_data *ed, int hp, int sp) {
if( hp )
clif_elemental_updatestatus(ed->master, SP_HP);
if( sp )
clif_elemental_updatestatus(ed->master, SP_SP);
}
int elemental_dead(struct elemental_data *ed, struct block_list *src) {
elemental_delete(ed, 1);
return 0;
}
int elemental_unlocktarget(struct elemental_data *ed) {
nullpo_ret(ed);
ed->target_id = 0;
elemental_stop_attack(ed);
elemental_stop_walking(ed,1);
return 0;
}
int elemental_skillnotok(int skillid, struct elemental_data *ed) {
int i = skill_get_index(skillid);
nullpo_retr(1,ed);
if (i == 0)
return 1; // invalid skill id
if( ed->blockskill[i] > 0 )
return 1;
return skillnotok(skillid, ed->master);
}
int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) {
struct elemental_data *ed = sd->ed;
nullpo_ret(ed);
nullpo_ret(bl);
if( ed->bl.m != bl->m || !check_distance_bl(&ed->bl, bl, ed->db->range2) )
return 0;
if( !status_check_skilluse(&ed->bl, bl, 0, 0) )
return 0;
if( ed->target_id == 0 )
ed->target_id = bl->id;
return 1;
}
static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) {
struct elemental_data *ed;
struct block_list **target;
int dist;
nullpo_ret(bl);
ed = va_arg(ap,struct elemental_data *);
target = va_arg(ap,struct block_list**);
//If can't seek yet, not an enemy, or you can't attack it, skip.
if( (*target) == bl || !status_check_skilluse(&ed->bl, bl, 0, 0) )
return 0;
if( battle_check_target(&ed->bl,bl,BCT_ENEMY) <= 0 )
return 0;
switch( bl->type ) {
case BL_PC:
if( !map_flag_vs(ed->bl.m) )
return 0;
default:
dist = distance_bl(&ed->bl, bl);
if( ((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle_check_range(&ed->bl,bl,ed->db->range2) ) { //Pick closest target?
(*target) = bl;
ed->target_id = bl->id;
ed->min_chase = dist + ed->db->range3;
if( ed->min_chase > AREA_SIZE )
ed->min_chase = AREA_SIZE;
return 1;
}
break;
}
return 0;
}
static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) {
struct block_list *target = NULL;
int master_dist, view_range, mode;
nullpo_ret(ed);
nullpo_ret(sd);
if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL )
return 0;
if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME )
return 0;
ed->last_thinktime = tick;
if( ed->ud.skilltimer != -1 )
return 0;
if( ed->ud.walktimer != -1 && ed->ud.walkpath.path_pos <= 2 )
return 0; //No thinking when you just started to walk.
if(ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id)
return 0; //No thinking until be near the master.
if( ed->sc.count && ed->sc.data[SC_BLIND] )
view_range = 3;
else
view_range = ed->db->range2;
mode = status_get_mode(&ed->bl);
master_dist = distance_bl(&sd->bl, &ed->bl);
if( master_dist > AREA_SIZE ) { // Master out of vision range.
elemental_unlocktarget(ed);
unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,3);
return 0;
} else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase.
short x = sd->bl.x, y = sd->bl.y;
if( ed->target_id )
elemental_unlocktarget(ed);
if( ed->ud.walktimer != -1 && ed->ud.target == sd->bl.id )
return 0; //Already walking to him
if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 )
return 0; //Can't move yet.
if( map_search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1)
&& unit_walktoxy(&ed->bl, x, y, 0) )
return 0;
}
if( mode == EL_MODE_AGGRESSIVE ) {
target = map_id2bl(ed->ud.target);
if( !target )
map_foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, ed->db->range2, BL_CHAR, ed, &target, status_get_mode(&ed->bl));
if( !target ) { //No targets available.
elemental_unlocktarget(ed);
return 1;
}
if( battle_check_range(&ed->bl,target,ed->db->range2) && rand()%100 < 2 ) { // 2% chance to cast attack skill.
if( elemental_action(ed,target,tick) )
return 1;
}
//Attempt to attack.
//At this point we know the target is attackable, we just gotta check if the range matches.
if( ed->ud.target == target->id && ed->ud.attacktimer != -1 ) //Already locked.
return 1;
if( battle_check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage
unit_attack(&ed->bl,target->id,1);
return 1;
}
//Follow up if possible.
if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) )
elemental_unlocktarget(ed);
}
return 0;
}
static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
unsigned int tick = va_arg(ap,unsigned int);
if(sd->status.ele_id && sd->ed)
elemental_ai_sub_timer(sd->ed,sd,tick);
return 0;
}
static int elemental_ai_timer(int tid, unsigned int tick, int id, intptr data) {
map_foreachpc(elemental_ai_sub_foreachclient,tick);
return 0;
}
int read_elementaldb(void) {
FILE *fp;
char line[1024], *p;
char *str[26];
int i, j = 0, k = 0, ele;
struct s_elemental_db *db;
struct status_data *status;
sprintf(line, "%s/%s", db_path, "elemental_db.txt");
memset(elemental_db,0,sizeof(elemental_db));
fp = fopen(line, "r");
if( !fp ) {
ShowError("read_elementaldb : can't read elemental_db.txt\n");
return -1;
}
while( fgets(line, sizeof(line), fp) && j < MAX_ELEMENTAL_CLASS ) {
k++;
if( line[0] == '/' && line[1] == '/' )
continue;
i = 0;
p = strtok(line, ",");
while( p != NULL && i < 26 ) {
str[i++] = p;
p = strtok(NULL, ",");
}
if( i < 26 ) {
ShowError("read_elementaldb : Incorrect number of columns at elemental_db.txt line %d.\n", k);
continue;
}
db = &elemental_db[j];
db->class_ = atoi(str[0]);
strncpy(db->sprite, str[1], NAME_LENGTH);
strncpy(db->name, str[2], NAME_LENGTH);
db->lv = atoi(str[3]);
status = &db->status;
db->vd.class_ = db->class_;
status->max_hp = atoi(str[4]);
status->max_sp = atoi(str[5]);
status->rhw.range = atoi(str[6]);
status->rhw.atk = atoi(str[7]);
status->rhw.atk2 = status->rhw.atk + atoi(str[8]);
status->def = atoi(str[9]);
status->mdef = atoi(str[10]);
status->str = atoi(str[11]);
status->agi = atoi(str[12]);
status->vit = atoi(str[13]);
status->int_ = atoi(str[14]);
status->dex = atoi(str[15]);
status->luk = atoi(str[16]);
db->range2 = atoi(str[17]);
db->range3 = atoi(str[18]);
status->size = atoi(str[19]);
status->race = atoi(str[20]);
ele = atoi(str[21]);
status->def_ele = ele%10;
status->ele_lv = ele/20;
if( status->def_ele >= ELE_MAX ) {
ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1);
status->def_ele = ELE_NEUTRAL;
}
if( status->ele_lv < 1 || status->ele_lv > 4 ) {
ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
status->ele_lv = 1;
}
status->aspd_rate = 1000;
status->speed = atoi(str[22]);
status->adelay = atoi(str[23]);
status->amotion = atoi(str[24]);
status->dmotion = atoi(str[25]);
j++;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' elementals in '"CL_WHITE"db/elemental_db.txt"CL_RESET"'.\n",j);
return 0;
}
int read_elemental_skilldb(void) {
FILE *fp;
char line[1024], *p;
char *str[4];
struct s_elemental_db *db;
int i, j = 0, k = 0, class_;
int skillid, skilllv, skillmode;
sprintf(line, "%s/%s", db_path, "elemental_skill_db.txt");
fp = fopen(line, "r");
if( !fp ) {
ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n");
return -1;
}
while( fgets(line, sizeof(line), fp) ) {
k++;
if( line[0] == '/' && line[1] == '/' )
continue;
i = 0;
p = strtok(line, ",");
while( p != NULL && i < 4 ) {
str[i++] = p;
p = strtok(NULL, ",");
}
if( i < 4 ) {
ShowError("read_elemental_skilldb : Incorrect number of columns at elemental_skill_db.txt line %d.\n", k);
continue;
}
class_ = atoi(str[0]);
ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_);
if( i == MAX_ELEMENTAL_CLASS ) {
ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k);
continue;
}
skillid = atoi(str[1]);
if( skillid < EL_SKILLBASE || skillid >= EL_SKILLBASE + MAX_ELEMENTALSKILL ) {
ShowError("read_elemental_skilldb : Skill out of range, line %d.\n", k);
continue;
}
db = &elemental_db[i];
skilllv = atoi(str[2]);
skillmode = atoi(str[3]);
if( skillmode < EL_SKILLMODE_PASIVE || skillmode > EL_SKILLMODE_AGGRESSIVE ) {
ShowError("read_elemental_skilldb : Skillmode out of range, line %d.\n",k);
skillmode = EL_SKILLMODE_PASIVE;
continue;
}
ARR_FIND( 0, MAX_ELESKILLTREE, i, db->skill[i].id == 0 || db->skill[i].id == skillid );
if( i == MAX_ELESKILLTREE ) {
ShowWarning("Unable to load skill %d into Elemental %d's tree. Maximum number of skills per elemental has been reached.\n", skillid, class_);
continue;
}
db->skill[i].id = skillid;
db->skill[i].lv = skilllv;
db->skill[i].mode = skillmode;
j++;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/elemental_skill_db.txt"CL_RESET"'.\n",j);
return 0;
}
void reload_elementaldb(void) {
read_elementaldb();
reload_elemental_skilldb();
}
void reload_elemental_skilldb(void) {
read_elemental_skilldb();
}
int do_init_elemental(void) {
read_elementaldb();
read_elemental_skilldb();
add_timer_func_list(elemental_ai_timer,"elemental_ai_timer");
add_timer_interval(gettick()+MIN_ELETHINKTIME,elemental_ai_timer,0,0,MIN_ELETHINKTIME);
return 0;
}
void do_final_elemental(void) {
return;
}

95
src/map/elemental.h Normal file
View File

@ -0,0 +1,95 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _ELEMENTAL_H_
#define _ELEMENTAL_H_
#include "status.h" // struct status_data, struct status_change
#include "unit.h" // struct unit_data
#define MIN_ELETHINKTIME 100
#define MIN_ELEDISTANCE 2
#define MAX_ELEDISTANCE 6
#define EL_MODE_AGGRESSIVE (MD_CANMOVE|MD_AGGRESSIVE|MD_CANATTACK)
#define EL_MODE_ASSIST (MD_CANMOVE|MD_ASSIST)
#define EL_MODE_PASSIVE MD_CANMOVE
#define EL_SKILLMODE_PASIVE 0x1
#define EL_SKILLMODE_ASSIST 0x2
#define EL_SKILLMODE_AGGRESSIVE 0x4
struct elemental_skill {
unsigned short id, lv;
short mode;
};
struct s_elemental_db {
int class_;
char sprite[NAME_LENGTH], name[NAME_LENGTH];
unsigned short lv;
short range2, range3;
struct status_data status;
struct view_data vd;
struct elemental_skill skill[MAX_ELESKILLTREE];
};
extern struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS];
struct elemental_data {
struct block_list bl;
struct unit_data ud;
struct view_data *vd;
struct status_data base_status, battle_status;
struct status_change sc;
struct regen_data regen;
struct s_elemental_db *db;
struct s_elemental elemental;
char blockskill[MAX_SKILL];
struct map_session_data *master;
int summon_timer;
int skill_timer;
unsigned last_thinktime, last_linktime;
short min_chase;
int target_id, attacked_id;
};
bool elemental_class(int class_);
struct view_data * elemental_get_viewdata(int class_);
int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime);
int elemental_data_received(struct s_elemental *ele, bool flag);
int elemental_save(struct elemental_data *ed);
int elemental_change_mode_ack(struct elemental_data *ed, int mode);
int elemental_change_mode(struct elemental_data *ed, int mode);
void elemental_damage(struct elemental_data *ed, struct block_list *src, int hp, int sp);
void elemental_heal(struct elemental_data *ed, int hp, int sp);
int elemental_dead(struct elemental_data *ed, struct block_list *src);
int elemental_delete(struct elemental_data *ed, int reply);
void elemental_summon_stop(struct elemental_data *ed);
int elemental_get_lifetime(struct elemental_data *ed);
int elemental_unlocktarget(struct elemental_data *ed);
int elemental_skillnotok(int skillid, struct elemental_data *ed);
int elemental_set_target( struct map_session_data *sd, struct block_list *bl );
int elemental_clean_single_effect(struct elemental_data *ed, int skill_num);
int elemental_clean_effect(struct elemental_data *ed);
int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick);
#define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type)
#define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl)
int read_elemental_skilldb(void);
void reload_elementaldb(void);
void reload_elemental_skilldb(void);
int do_init_elemental(void);
void do_final_elemental(void);
#endif /* _ELEMENTAL_H_ */

View File

@ -21,6 +21,7 @@
#include "atcommand.h"
#include "mercenary.h"
#include "homunculus.h"
#include "elemental.h"
#include "mail.h"
#include "quest.h"
@ -40,7 +41,7 @@ static const int packet_len_table[]={
-1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
-1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus]
-1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
-1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3870 Mercenaries [Zephyrus]
-1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil]
11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
-1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
};
@ -1988,6 +1989,94 @@ int intif_parse_mercenary_saved(int fd)
return 0;
}
/*==========================================
* Elemental's System
*------------------------------------------*/
int intif_elemental_create(struct s_elemental *ele)
{
int size = sizeof(struct s_elemental) + 4;
if( CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,size);
WFIFOW(inter_fd,0) = 0x307c;
WFIFOW(inter_fd,2) = size;
memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental));
WFIFOSET(inter_fd,size);
return 0;
}
int intif_parse_elemental_received(int fd)
{
int len = RFIFOW(fd,2) - 5;
if( sizeof(struct s_elemental) != len )
{
if( battle_config.etc_log )
ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len);
return 0;
}
elemental_data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4));
return 0;
}
int intif_elemental_request(int ele_id, int char_id)
{
if (CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
WFIFOW(inter_fd,0) = 0x307d;
WFIFOL(inter_fd,2) = ele_id;
WFIFOL(inter_fd,6) = char_id;
WFIFOSET(inter_fd,10);
return 0;
}
int intif_elemental_delete(int ele_id)
{
if (CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
WFIFOW(inter_fd,0) = 0x307e;
WFIFOL(inter_fd,2) = ele_id;
WFIFOSET(inter_fd,6);
return 0;
}
int intif_parse_elemental_deleted(int fd)
{
if( RFIFOB(fd,2) != 1 )
ShowError("Elemental data delete failure\n");
return 0;
}
int intif_elemental_save(struct s_elemental *ele)
{
int size = sizeof(struct s_elemental) + 4;
if( CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,size);
WFIFOW(inter_fd,0) = 0x307f;
WFIFOW(inter_fd,2) = size;
memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental));
WFIFOSET(inter_fd,size);
return 0;
}
int intif_parse_elemental_saved(int fd)
{
if( RFIFOB(fd,2) != 1 )
ShowError("Elemental data save failure\n");
return 0;
}
//-----------------------------------------------------------------
// inter serverからの通信
// エラーがあれば0(false)を返すこと
@ -2076,7 +2165,11 @@ int intif_parse(int fd)
case 0x3870: intif_parse_mercenary_received(fd); break;
case 0x3871: intif_parse_mercenary_deleted(fd); break;
case 0x3872: intif_parse_mercenary_saved(fd); break;
// Elemental System
case 0x387c: intif_parse_elemental_received(fd); break;
case 0x387d: intif_parse_elemental_deleted(fd); break;
case 0x387e: intif_parse_elemental_saved(fd); break;
case 0x3880: intif_parse_CreatePet(fd); break;
case 0x3881: intif_parse_RecvPetData(fd); break;
case 0x3882: intif_parse_SavePetOk(fd); break;

View File

@ -11,6 +11,7 @@ struct guild_position;
struct s_pet;
struct s_homunculus;
struct s_mercenary;
struct s_elemental;
struct mail_message;
struct auction_data;
@ -97,6 +98,11 @@ int intif_Auction_register(struct auction_data *auction);
int intif_Auction_cancel(int char_id, unsigned int auction_id);
int intif_Auction_close(int char_id, unsigned int auction_id);
int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid);
// ELEMENTAL SYSTEM
int intif_elemental_create(struct s_elemental *ele);
int intif_elemental_request(int ele_id, int char_id);
int intif_elemental_delete(int ele_id);
int intif_elemental_save(struct s_elemental *ele);
int CheckForCharServer(void);

View File

@ -160,6 +160,7 @@ struct item_data* itemdb_exists(int nameid);
#define itemdb_is_poison(n) (n >= 12717 && n <= 12724)
#define itemid_isgemstone(id) ( (id) >= ITEMID_YELLOW_GEMSTONE && (id) <= ITEMID_BLUE_GEMSTONE )
#define itemdb_iscashfood(id) ( (id) >= 12202 && (id) <= 12207 )
#define itemdb_is_GNbomb(n) (n >= 13260 && n <= 13267)
const char* itemdb_typename(int type);
int itemdb_group_bonus(struct map_session_data* sd, int itemid);

View File

@ -41,6 +41,7 @@
#include "homunculus.h"
#include "instance.h"
#include "mercenary.h"
#include "elemental.h"
#include "atcommand.h"
#include "log.h"
#include "mail.h"
@ -1722,8 +1723,14 @@ int map_quit(struct map_session_data *sd)
// Return loot to owner
if( sd->pd ) pet_lootitem_drop(sd->pd, sd);
if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit.
if( sd->ed ) {
elemental_clean_effect(sd->ed);
unit_remove_map(&sd->ed->bl,CLR_TELEPORT);
}
unit_remove_map_pc(sd,CLR_TELEPORT);
if( map[sd->bl.m].instance_id )
@ -3588,6 +3595,7 @@ void do_final(void)
do_final_unit();
do_final_battleground();
do_final_duel();
do_final_elemental();
map_db->destroy(map_db, map_db_final);
@ -3914,7 +3922,8 @@ int do_init(int argc, char *argv[])
do_init_unit();
do_init_battleground();
do_init_duel();
do_init_elemental();
npc_event_do_oninit(); // npcÌOnInitƒCƒxƒ“ƒg?<3F>s
if( console )

View File

@ -233,12 +233,13 @@ enum bl_type {
BL_SKILL = 0x040,
BL_NPC = 0x080,
BL_CHAT = 0x100,
BL_ELEM = 0x200,
BL_ALL = 0xFFF,
};
//For common mapforeach calls. Since pets cannot be affected, they aren't included here yet.
#define BL_CHAR (BL_PC|BL_MOB|BL_HOM|BL_MER)
#define BL_CHAR (BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM)
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP };
@ -738,6 +739,7 @@ typedef struct skill_unit TBL_SKILL;
typedef struct pet_data TBL_PET;
typedef struct homun_data TBL_HOM;
typedef struct mercenary_data TBL_MER;
typedef struct elemental_data TBL_ELEM;
#define BL_CAST(type_, bl) \
( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) )

View File

@ -23,6 +23,7 @@
#include "mob.h"
#include "homunculus.h"
#include "mercenary.h"
#include "elemental.h"
#include "guild.h"
#include "itemdb.h"
#include "skill.h"
@ -1896,6 +1897,15 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
md->attacked_id = src->id;
break;
}
case BL_ELEM:
{
struct elemental_data *ele = (TBL_ELEM*)src;
if( ele->master )
char_id = ele->master->status.char_id;
if( damage )
md->attacked_id = src->id;
break;
}
default: //For all unhandled types.
md->attacked_id = src->id;
}

View File

@ -14,7 +14,7 @@
#include "pc.h" // struct map_session_data
#include "script.h" // set_var()
#include <pcre.h>
#include "pcre.h"
#include <stdio.h>
#include <stdlib.h>

View File

@ -29,6 +29,7 @@
#include "homunculus.h"
#include "instance.h"
#include "mercenary.h"
#include "elemental.h"
#include "npc.h" // fake_nd
#include "pet.h" // pet_unlocktarget()
#include "party.h" // party_search()
@ -1213,7 +1214,9 @@ int pc_reg_received(struct map_session_data *sd)
intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
if( sd->status.mer_id > 0 )
intif_mercenary_request(sd->status.mer_id, sd->status.char_id);
if( sd->status.ele_id > 0 )
intif_elemental_request(sd->status.ele_id, sd->status.char_id);
map_addiddb(&sd->bl);
map_delnickdb(sd->status.char_id, sd->status.name);
if (!chrif_auth_finished(sd))
@ -6155,6 +6158,9 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
if( sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support )
pet_target_check(sd,src,1);
if( sd->status.ele_id > 0 )
elemental_set_target(sd,src);
sd->canlog_tick = gettick();
}
@ -6189,6 +6195,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
if( sd->md )
merc_delete(sd->md, 3); // Your mercenary soldier has ran away.
if( sd->ed )
elemental_delete(sd->ed, 0);
// Leave duel if you die [LuzZza]
if(battle_config.duel_autoleave_when_die) {
if(sd->duel_group > 0)

View File

@ -205,7 +205,7 @@ struct map_session_data {
short cook_mastery; // range: [0,1999] [Inkfish]
unsigned char blockskill[MAX_SKILL];
int cloneskill_id, reproduceskill_id;
int menuskill_id, menuskill_val;
int menuskill_id, menuskill_val, menuskill_val2;
int invincible_timer;
unsigned int canlog_tick;
@ -377,6 +377,7 @@ struct map_session_data {
struct pet_data *pd;
struct homun_data *hd; // [blackhole89]
struct mercenary_data *md;
struct elemental_data *ed;
struct{
int m; //-1 - none, other: map index corresponding to map name.

View File

@ -7835,7 +7835,7 @@ BUILDIN_FUNC(cooking)
return 0;
trigger=script_getnum(st,2);
clif_cooking_list(sd, trigger);
clif_cooking_list(sd, trigger, AM_PHARMACY, 1, 1);
return 0;
}
/*==========================================

File diff suppressed because it is too large Load Diff

View File

@ -1705,49 +1705,49 @@ enum {
UNT_EVILLAND,
UNT_DARK_RUNNER, //TODO
UNT_DARK_TRANSFER, //TODO
UNT_EPICLESIS, //TODO
UNT_EARTHSTRAIN, //TODO
UNT_MANHOLE, //TODO
UNT_DIMENSIONDOOR, //TODO
UNT_CHAOSPANIC, //TODO
UNT_MAELSTROM, //TODO
UNT_BLOODYLUST, //TODO
UNT_FEINTBOMB, //TODO
UNT_MAGENTATRAP, //TODO
UNT_COBALTTRAP, //TODO
UNT_MAIZETRAP, //TODO
UNT_VERDURETRAP, //TODO
UNT_FIRINGTRAP, //TODO
UNT_ICEBOUNDTRAP, //TODO
UNT_ELECTRICSHOCKER, //TODO
UNT_CLUSTERBOMB, //TODO
UNT_REVERBERATION, //TODO
UNT_SEVERE_RAINSTORM, //TODO
UNT_FIREWALK, //TODO
UNT_ELECTRICWALK, //TODO
UNT_NETHERWORLD, //TODO
UNT_PSYCHIC_WAVE, //TODO
UNT_CLOUD_KILL, //TODO
UNT_POISONSMOKE, //TODO
UNT_NEUTRALBARRIER, //TODO
UNT_STEALTHFIELD, //TODO
UNT_WARMER, //TODO
UNT_THORNS_TRAP, //TODO
UNT_WALLOFTHORN, //TODO
UNT_DEMONIC_FIRE, //TODO
UNT_FIRE_EXPANSION_SMOKE_POWDER, //TODO
UNT_FIRE_EXPANSION_TEAR_GAS, //TODO
UNT_HELLS_PLANT, //TODO
UNT_VACUUM_EXTREME, //TODO
UNT_BANDING, //TODO
UNT_FIRE_MANTLE, //TODO
UNT_WATER_BARRIER, //TODO
UNT_ZEPHYR, //TODO
UNT_POWER_OF_GAIA, //TODO
UNT_FIRE_INSIGNIA, //TODO
UNT_WATER_INSIGNIA, //TODO
UNT_WIND_INSIGNIA, //TODO
UNT_EARTH_INSIGNIA, //TODO
UNT_EPICLESIS,
UNT_EARTHSTRAIN,
UNT_MANHOLE,
UNT_DIMENSIONDOOR,
UNT_CHAOSPANIC,
UNT_MAELSTROM,
UNT_BLOODYLUST,
UNT_FEINTBOMB,
UNT_MAGENTATRAP,
UNT_COBALTTRAP,
UNT_MAIZETRAP,
UNT_VERDURETRAP,
UNT_FIRINGTRAP,
UNT_ICEBOUNDTRAP,
UNT_ELECTRICSHOCKER,
UNT_CLUSTERBOMB,
UNT_REVERBERATION,
UNT_SEVERE_RAINSTORM,
UNT_FIREWALK,
UNT_ELECTRICWALK,
UNT_NETHERWORLD,
UNT_PSYCHIC_WAVE,
UNT_CLOUD_KILL,
UNT_POISONSMOKE,
UNT_NEUTRALBARRIER,
UNT_STEALTHFIELD,
UNT_WARMER,
UNT_THORNS_TRAP,
UNT_WALLOFTHORN,
UNT_DEMONIC_FIRE,
UNT_FIRE_EXPANSION_SMOKE_POWDER,
UNT_FIRE_EXPANSION_TEAR_GAS,
UNT_HELLS_PLANT,
UNT_VACUUM_EXTREME,
UNT_BANDING,
UNT_FIRE_MANTLE,
UNT_WATER_BARRIER,
UNT_ZEPHYR,
UNT_POWER_OF_GAIA,
UNT_FIRE_INSIGNIA,
UNT_WATER_INSIGNIA,
UNT_WIND_INSIGNIA,
UNT_EARTH_INSIGNIA,
UNT_POISON_MIST,
UNT_LAVA_SLIDE,
UNT_VOLCANIC_ASH,
@ -1823,4 +1823,9 @@ enum gx_poison {
* Auto Shadow Spell (Shadow Chaser)
**/
int skill_select_menu(struct map_session_data *sd,int flag,int skill_id);
int skill_elementalanalysis(struct map_session_data *sd, int n, int type, unsigned short *item_list); // Sorcerer Four Elemental Analisys.
int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list); // Genetic Change Material.
int skill_get_elemental_type(int skill_id, int skill_lv);
#endif /* _SKILL_H_ */

View File

@ -29,6 +29,7 @@
#include "unit.h"
#include "homunculus.h"
#include "mercenary.h"
#include "elemental.h"
#include "vending.h"
#include <time.h>
@ -645,28 +646,57 @@ void initChangeTables(void)
set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK );
set_sc( WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK );
set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITEDHUMMINGVOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE );
///**
// * Sorcerer
// **/
//set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
//set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
//set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
//set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
//set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
//set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
//set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
//set_sc( SO_ARRULLO , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE );
///**
// * Genetic
// **/
//set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED );
//set_sc( GN_THORNS_TRAP , SC_THORNSTRAP , SI_THORNTRAP , SCB_NONE );
//set_sc( GN_BLOOD_SUCKER , SC_BLOODSUCKER , SI_BLOODSUCKER , SCB_NONE );
//set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE );
//set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_SMOKEPOWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE );
//set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_TEARGAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
//set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT );
/**
* Sorcerer
**/
set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
set_sc( SO_DIAMONDDUST , SC_CRYSTALIZE , SI_COLD , SCB_NONE );//Will add flags in major balance update 8 [Rytech]
set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
set_sc( SO_ARRULLO , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE );
/**
* Genetic
**/
set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED );
set_sc( GN_THORNS_TRAP , SC_THORNSTRAP , SI_THORNTRAP , SCB_NONE );
set_sc( GN_BLOOD_SUCKER , SC_BLOODSUCKER , SI_BLOODSUCKER , SCB_NONE );
set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE );
set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_SMOKEPOWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE );
set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_TEARGAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT );
// Elemental Spirit summoner's 'side' status changes.
set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE );
set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL );
set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE );
set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL );
set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_MDEF|SCB_WATK|SCB_MATK|SCB_FLEE );
set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE );
set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL );
set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE );
set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP );
set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL );
set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED );
set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK );
set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK );
set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK );
set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK );
set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK );
set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK );
set_sc( EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_NONE );
set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_NONE );
set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_NONE );
set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_NONE );
set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_NONE );
set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE );
set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
// Storing the target job rather than simply SC_SPIRIT simplifies code later on.
SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST,
SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK,
@ -882,11 +912,20 @@ void initChangeTables(void)
StatusChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX;
StatusChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI;
StatusChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK;
StatusChangeFlagTable[SC_BOOST500] |= SCB_ASPD;
StatusChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK;
StatusChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK;
StatusChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP;
StatusChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP;
StatusChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN;
StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN;
StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD;
#ifdef RENEWAL_EDP
// renewal EDP increases your atk and weapon atk
StatusChangeFlagTable[SC_EDP] |= SCB_BATK|SCB_WATK;
#endif
if( !battle_config.display_hallucination ) //Disable Hallucination.
StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK;
}
@ -1077,6 +1116,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break;
case BL_HOM: merc_damage((TBL_HOM*)target,src,hp,sp); break;
case BL_MER: mercenary_damage((TBL_MER*)target,src,hp,sp); break;
case BL_ELEM: elemental_damage((TBL_ELEM*)target,src,hp,sp); break;
}
if( target->type == BL_PC && ((TBL_PC*)target)->disguise && src )
@ -1102,6 +1142,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break;
case BL_HOM: flag = merc_hom_dead((TBL_HOM*)target,src); break;
case BL_MER: flag = mercenary_dead((TBL_MER*)target,src); break;
case BL_ELEM: flag = elemental_dead((TBL_ELEM*)target,src); break;
default: //Unhandled case, do nothing to object.
flag = 0;
break;
@ -1239,6 +1280,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break;
case BL_HOM: merc_hom_heal((TBL_HOM*)bl,hp,sp); break;
case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break;
case BL_ELEM: elemental_heal((TBL_ELEM*)bl,hp,sp); break;
}
return hp+sp;
@ -1378,6 +1420,8 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
//on dead characters, said checks are left to skill.c [Skotlex]
if (target && status_isdead(target))
return 0;
if( src && (sc = status_get_sc(src)) && sc->data[SC_CRYSTALIZE] )
return 0;
}
if (skill_num == PA_PRESSURE && flag && target) {
@ -1394,12 +1438,11 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
&& (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_num))
return 0;
if (src) sc = status_get_sc(src);
if ( src ) sc = status_get_sc(src);
if(sc && sc->count)
{
if(sc->opt1 >0 && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE)
{ //Stuned/Frozen/etc
if( sc && sc->count ) {
if( sc->opt1 >0 && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE ) { //Stuned/Frozen/etc
if (flag != 1) //Can't cast, casted stuff can't damage.
return 0;
if (!(skill_get_inf(skill_num)&INF_GROUND_SKILL))
@ -1570,11 +1613,12 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
return 0;
case BL_HOM:
case BL_MER:
case BL_ELEM:
if( target->type == BL_HOM && skill_num && battle_config.hom_setting&0x1 && skill_get_inf(skill_num)&INF_SUPPORT_SKILL && battle_get_master(target) != src )
return 0; // Can't use support skills on Homunculus (only Master/Self)
if( target->type == BL_MER && (skill_num == PR_ASPERSIO || (skill_num >= SA_FLAMELAUNCHER && skill_num <= SA_SEISMICWEAPON)) && battle_get_master(target) != src )
return 0; // Can't use Weapon endow skills on Mercenary (only Master)
if( target->type == BL_MER && skill_num == AM_POTIONPITCHER )
if( skill_num == AM_POTIONPITCHER && ( target->type == BL_MER || target->type == BL_ELEM) )
return 0; // Can't use Potion Pitcher on Mercenaries
default:
//Check for chase-walk/hiding/cloaking opponents.
@ -2848,8 +2892,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
}
if(sc->count){
if(sc->data[SC_CONCENTRATE])
{ //Update the card-bonus data
if(sc->data[SC_CONCENTRATE]) { //Update the card-bonus data
sc->data[SC_CONCENTRATE]->val3 = sd->param_bonus[1]; //Agi
sc->data[SC_CONCENTRATE]->val4 = sd->param_bonus[4]; //Dex
}
@ -2869,20 +2912,38 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2;
sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2;
}
if(sc->data[SC_ARMOR_ELEMENT])
{ //This status change should grant card-type elemental resist.
if(sc->data[SC_ARMOR_ELEMENT]) { //This status change should grant card-type elemental resist.
sd->subele[ELE_WATER] += sc->data[SC_ARMOR_ELEMENT]->val1;
sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_ELEMENT]->val2;
sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_ELEMENT]->val3;
sd->subele[ELE_WIND] += sc->data[SC_ARMOR_ELEMENT]->val4;
}
if(sc->data[SC_ARMOR_RESIST])
{ // Undead Scroll
if(sc->data[SC_ARMOR_RESIST]) { // Undead Scroll
sd->subele[ELE_WATER] += sc->data[SC_ARMOR_RESIST]->val1;
sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_RESIST]->val2;
sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_RESIST]->val3;
sd->subele[ELE_WIND] += sc->data[SC_ARMOR_RESIST]->val4;
}
if( sc->data[SC_FIRE_CLOAK_OPTION] ) {
i = sc->data[SC_FIRE_CLOAK_OPTION]->val2;
sd->subele[ELE_FIRE] += i;
sd->subele[ELE_EARTH] -= i;
}
if( sc->data[SC_WATER_DROP_OPTION] ) {
i = sc->data[SC_WATER_DROP_OPTION]->val2;
sd->subele[ELE_WATER] += i;
sd->subele[ELE_WIND] -= i;
}
if( sc->data[SC_WIND_CURTAIN_OPTION] ) {
i = sc->data[SC_WIND_CURTAIN_OPTION]->val2;
sd->subele[ELE_WIND] += i;
sd->subele[ELE_WATER] -= i;
}
if( sc->data[SC_STONE_SHIELD_OPTION] ) {
i = sc->data[SC_STONE_SHIELD_OPTION]->val2;
sd->subele[ELE_EARTH] += i;
sd->subele[ELE_FIRE] -= i;
}
}
status_cpy(&sd->battle_status, status);
@ -3006,6 +3067,45 @@ int status_calc_homunculus_(struct homun_data *hd, bool first)
return 1;
}
int status_calc_elemental_(struct elemental_data *ed, bool first) {
struct status_data *status = &ed->base_status;
struct s_elemental *ele = &ed->elemental;
struct map_session_data *sd = ed->master;
if( !sd )
return 0;
status->str = ele->str;
status->agi = ele->agi;
status->vit = ele->vit;
status->dex = ele->dex;
status->int_ = ele->int_;
status->luk = ele->luk;
if( first ) {
memcpy(status, &ed->db->status, sizeof(struct status_data));
status->mode = MD_CANMOVE|MD_CANATTACK;
status->max_hp += 4000 + 500 * pc_checkskill(sd,SO_EL_SYMPATHY);
status->max_sp += 300 + 50 * pc_checkskill(sd,SO_EL_SYMPATHY);
status->hp = status->max_hp;
status->sp = status->max_sp;
status->str += sd->base_status.str * 25 / 100;
status->agi += sd->base_status.agi * 25 / 100;
status->vit += sd->base_status.vit * 25 / 100;
status->int_ += sd->base_status.int_ * 25 / 100;
status->def += sd->base_status.dex * 25 / 100;
status->luk += sd->base_status.luk * 25 / 100;
status_calc_misc(&ed->bl, status, ed->db->lv);
memcpy(&ed->battle_status,status,sizeof(struct status_data));
} else {
status_calc_misc(&ed->bl, status, ed->db->lv);
status_cpy(&ed->battle_status, status);
}
return 0;
}
static unsigned short status_calc_str(struct block_list *,struct status_change *,int);
static unsigned short status_calc_agi(struct block_list *,struct status_change *,int);
static unsigned short status_calc_vit(struct block_list *,struct status_change *,int);
@ -3107,25 +3207,26 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct
sregen->sp = cap_value(val, 0, SHRT_MAX);
}
if( bl->type == BL_HOM )
{
if( bl->type == BL_HOM ) {
struct homun_data *hd = (TBL_HOM*)bl;
if( (skill = merc_hom_checkskill(hd,HAMI_SKIN)) > 0 )
{
if( (skill = merc_hom_checkskill(hd,HAMI_SKIN)) > 0 ) {
val = regen->hp*(100+5*skill)/100;
regen->hp = cap_value(val, 1, SHRT_MAX);
}
if( (skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0 )
{
if( (skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0 ) {
val = regen->sp*(100+3*skill)/100;
regen->sp = cap_value(val, 1, SHRT_MAX);
}
}
else if( bl->type == BL_MER )
{
} else if( bl->type == BL_MER ) {
val = (status->max_hp * status->vit / 10000 + 1) * 6;
regen->hp = cap_value(val, 1, SHRT_MAX);
val = (status->max_sp * (status->int_ + 10) / 750) + 1;
regen->sp = cap_value(val, 1, SHRT_MAX);
} else if( bl->type == BL_ELEM ) {
val = (status->max_hp * status->vit / 10000 + 1) * 6;
regen->hp = cap_value(val, 1, SHRT_MAX);
val = (status->max_sp * (status->int_ + 10) / 750) + 1;
regen->sp = cap_value(val, 1, SHRT_MAX);
}
@ -3241,7 +3342,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
if(flag&SCB_VIT) {
status->vit = status_calc_vit(bl, sc, b_status->vit);
flag|=SCB_DEF2|SCB_MDEF2;
if( bl->type&(BL_PC|BL_HOM|BL_MER) )
if( bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM) )
flag |= SCB_MAXHP;
if( bl->type&BL_HOM )
flag |= SCB_DEF;
@ -3250,7 +3351,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
if(flag&SCB_INT) {
status->int_ = status_calc_int(bl, sc, b_status->int_);
flag|=SCB_MATK|SCB_MDEF2;
if( bl->type&(BL_PC|BL_HOM|BL_MER) )
if( bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM) )
flag |= SCB_MAXSP;
if( bl->type&BL_HOM )
flag |= SCB_MDEF;
@ -3582,15 +3683,14 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
status = status_get_status_data(bl);
memcpy(&b_status, status, sizeof(struct status_data));
if( flag&SCB_BASE )
{// calculate the object's base status too
switch( bl->type )
{
if( flag&SCB_BASE ) {// calculate the object's base status too
switch( bl->type ) {
case BL_PC: status_calc_pc_(BL_CAST(BL_PC,bl), first); break;
case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), first); break;
case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), first); break;
case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); break;
case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), first); break;
case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), first); break;
}
}
@ -3671,17 +3771,11 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
clif_updatestatus(sd,SP_HP);
if(b_status.sp != status->sp)
clif_updatestatus(sd,SP_SP);
}
else
if( bl->type == BL_HOM )
{
} else if( bl->type == BL_HOM ) {
TBL_HOM* hd = BL_CAST(BL_HOM, bl);
if( hd->master && memcmp(&b_status, status, sizeof(struct status_data)) != 0 )
clif_hominfo(hd->master,hd,0);
}
else
if( bl->type == BL_MER )
{
} else if( bl->type == BL_MER ) {
TBL_MER* md = BL_CAST(BL_MER, bl);
if( b_status.rhw.atk != status->rhw.atk || b_status.rhw.atk2 != status->rhw.atk2 )
clif_mercenary_updatestatus(md->master, SP_ATK1);
@ -3707,7 +3801,17 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
clif_mercenary_updatestatus(md->master, SP_HP);
if( b_status.sp != status->sp )
clif_mercenary_updatestatus(md->master, SP_SP);
}
} else if( bl->type == BL_ELEM ) {
TBL_ELEM* ed = BL_CAST(BL_ELEM, bl);
if( b_status.max_hp != status->max_hp )
clif_elemental_updatestatus(ed->master, SP_MAXHP);
if( b_status.max_sp != status->max_sp )
clif_elemental_updatestatus(ed->master, SP_MAXSP);
if( b_status.hp != status->hp )
clif_elemental_updatestatus(ed->master, SP_HP);
if( b_status.sp != status->sp )
clif_mercenary_updatestatus(ed->master, SP_SP);
}
}
/*==========================================
@ -4641,6 +4745,10 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
val = max( val, 75 );
if( sc->data[SC_CLOAKINGEXCEED] )
val = max( val, sc->data[SC_CLOAKINGEXCEED]->val3);
if( sc->data[SC_HOVERING] )
val = max( val, 10 );
if( sc->data[SC_GN_CARTBOOST] )
val = max( val, sc->data[SC_GN_CARTBOOST]->val2 );
if( sc->data[SC_GT_REVITALIZE] )
val = max( val, sc->data[SC_GT_REVITALIZE]->val2 );
if( sc->data[SC_SWINGDANCE] )
@ -5005,8 +5113,7 @@ static unsigned short status_calc_mode(struct block_list *bl, struct status_chan
return cap_value(mode,0,USHRT_MAX);
}
const char* status_get_name(struct block_list *bl)
{
const char* status_get_name(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
case BL_PC: return ((TBL_PC *)bl)->fakename[0] != '\0' ? ((TBL_PC*)bl)->fakename : ((TBL_PC*)bl)->status.name;
@ -5022,17 +5129,16 @@ const char* status_get_name(struct block_list *bl)
* Classを返す()
* 0
*------------------------------------------*/
int status_get_class(struct block_list *bl)
{
int status_get_class(struct block_list *bl) {
nullpo_ret(bl);
switch( bl->type )
{
case BL_PC: return ((TBL_PC*)bl)->status.class_;
case BL_MOB: return ((TBL_MOB*)bl)->vd->class_; //Class used on all code should be the view class of the mob.
case BL_PET: return ((TBL_PET*)bl)->pet.class_;
case BL_HOM: return ((TBL_HOM*)bl)->homunculus.class_;
case BL_MER: return ((TBL_MER*)bl)->mercenary.class_;
case BL_NPC: return ((TBL_NPC*)bl)->class_;
switch( bl->type ) {
case BL_PC: return ((TBL_PC*)bl)->status.class_;
case BL_MOB: return ((TBL_MOB*)bl)->vd->class_; //Class used on all code should be the view class of the mob.
case BL_PET: return ((TBL_PET*)bl)->pet.class_;
case BL_HOM: return ((TBL_HOM*)bl)->homunculus.class_;
case BL_MER: return ((TBL_MER*)bl)->mercenary.class_;
case BL_NPC: return ((TBL_NPC*)bl)->class_;
case BL_ELEM: return ((TBL_ELEM*)bl)->elemental.class_;
}
return 0;
}
@ -5040,8 +5146,7 @@ int status_get_class(struct block_list *bl)
* ()
* 0
*------------------------------------------*/
int status_get_lv(struct block_list *bl)
{
int status_get_lv(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
case BL_PC: return ((TBL_PC*)bl)->status.base_level;
@ -5049,6 +5154,7 @@ int status_get_lv(struct block_list *bl)
case BL_PET: return ((TBL_PET*)bl)->pet.level;
case BL_HOM: return ((TBL_HOM*)bl)->homunculus.level;
case BL_MER: return ((TBL_MER*)bl)->db->lv;
case BL_ELEM: return ((TBL_ELEM*)bl)->db->lv;
}
return 1;
}
@ -5060,6 +5166,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl)
case BL_PC: return &((TBL_PC*)bl)->regen;
case BL_HOM: return &((TBL_HOM*)bl)->regen;
case BL_MER: return &((TBL_MER*)bl)->regen;
case BL_ELEM: return &((TBL_ELEM*)bl)->regen;
default:
return NULL;
}
@ -5075,6 +5182,7 @@ struct status_data *status_get_status_data(struct block_list *bl)
case BL_PET: return &((TBL_PET*)bl)->status;
case BL_HOM: return &((TBL_HOM*)bl)->battle_status;
case BL_MER: return &((TBL_MER*)bl)->battle_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->battle_status;
default:
return &dummy_status;
}
@ -5089,6 +5197,7 @@ struct status_data *status_get_base_status(struct block_list *bl)
case BL_PET: return &((TBL_PET*)bl)->db->status;
case BL_HOM: return &((TBL_HOM*)bl)->base_status;
case BL_MER: return &((TBL_MER*)bl)->base_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->base_status;
default:
return NULL;
}
@ -5111,115 +5220,120 @@ unsigned short status_get_speed(struct block_list *bl)
return status_get_status_data(bl)->speed;
}
int status_get_party_id(struct block_list *bl)
{
int status_get_party_id(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
case BL_PC:
return ((TBL_PC*)bl)->status.party_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.party_id;
break;
case BL_MOB:
{
struct mob_data *md=(TBL_MOB*)bl;
if( md->master_id>0 )
{
struct map_session_data *msd;
if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL)
return msd->status.party_id;
return -md->master_id;
}
}
break;
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->status.party_id;
break;
case BL_MER:
if (((TBL_MER*)bl)->master)
return ((TBL_MER*)bl)->master->status.party_id;
break;
case BL_SKILL:
return ((TBL_SKILL*)bl)->group->party_id;
case BL_PC:
return ((TBL_PC*)bl)->status.party_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.party_id;
break;
case BL_MOB: {
struct mob_data *md=(TBL_MOB*)bl;
if( md->master_id > 0 ) {
struct map_session_data *msd;
if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL)
return msd->status.party_id;
return -md->master_id;
}
}
break;
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->status.party_id;
break;
case BL_MER:
if (((TBL_MER*)bl)->master)
return ((TBL_MER*)bl)->master->status.party_id;
break;
case BL_SKILL:
return ((TBL_SKILL*)bl)->group->party_id;
case BL_ELEM:
if (((TBL_ELEM*)bl)->master)
return ((TBL_ELEM*)bl)->master->status.party_id;
break;
}
return 0;
}
int status_get_guild_id(struct block_list *bl)
{
int status_get_guild_id(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
case BL_PC:
return ((TBL_PC*)bl)->status.guild_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.guild_id;
break;
case BL_MOB:
{
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
if (md->guardian_data) //Guardian's guild [Skotlex]
return md->guardian_data->guild_id;
if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL)
return msd->status.guild_id; //Alchemist's mobs [Skotlex]
}
break;
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->status.guild_id;
break;
case BL_MER:
if (((TBL_MER*)bl)->master)
return ((TBL_MER*)bl)->master->status.guild_id;
break;
case BL_NPC:
if (((TBL_NPC*)bl)->subtype == SCRIPT)
return ((TBL_NPC*)bl)->u.scr.guild_id;
break;
case BL_SKILL:
return ((TBL_SKILL*)bl)->group->guild_id;
case BL_PC:
return ((TBL_PC*)bl)->status.guild_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.guild_id;
break;
case BL_MOB: {
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
if (md->guardian_data) //Guardian's guild [Skotlex]
return md->guardian_data->guild_id;
if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL)
return msd->status.guild_id; //Alchemist's mobs [Skotlex]
}
break;
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->status.guild_id;
break;
case BL_MER:
if (((TBL_MER*)bl)->master)
return ((TBL_MER*)bl)->master->status.guild_id;
break;
case BL_NPC:
if (((TBL_NPC*)bl)->subtype == SCRIPT)
return ((TBL_NPC*)bl)->u.scr.guild_id;
break;
case BL_SKILL:
return ((TBL_SKILL*)bl)->group->guild_id;
case BL_ELEM:
if (((TBL_ELEM*)bl)->master)
return ((TBL_ELEM*)bl)->master->status.guild_id;
break;
}
return 0;
}
int status_get_emblem_id(struct block_list *bl)
{
int status_get_emblem_id(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
case BL_PC:
return ((TBL_PC*)bl)->guild_emblem_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->guild_emblem_id;
break;
case BL_MOB:
{
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
if (md->guardian_data) //Guardian's guild [Skotlex]
return md->guardian_data->emblem_id;
if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL)
return msd->guild_emblem_id; //Alchemist's mobs [Skotlex]
}
break;
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->guild_emblem_id;
break;
case BL_MER:
if (((TBL_MER*)bl)->master)
return ((TBL_MER*)bl)->master->guild_emblem_id;
break;
case BL_NPC:
if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) {
struct guild *g = guild_search(((TBL_NPC*)bl)->u.scr.guild_id);
if (g)
return g->emblem_id;
}
break;
case BL_PC:
return ((TBL_PC*)bl)->guild_emblem_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->guild_emblem_id;
break;
case BL_MOB: {
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
if (md->guardian_data) //Guardian's guild [Skotlex]
return md->guardian_data->emblem_id;
if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL)
return msd->guild_emblem_id; //Alchemist's mobs [Skotlex]
}
break;
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->guild_emblem_id;
break;
case BL_MER:
if (((TBL_MER*)bl)->master)
return ((TBL_MER*)bl)->master->guild_emblem_id;
break;
case BL_NPC:
if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) {
struct guild *g = guild_search(((TBL_NPC*)bl)->u.scr.guild_id);
if (g)
return g->emblem_id;
}
break;
case BL_ELEM:
if (((TBL_ELEM*)bl)->master)
return ((TBL_ELEM*)bl)->master->guild_emblem_id;
break;
}
return 0;
}
@ -5271,6 +5385,7 @@ struct view_data* status_get_viewdata(struct block_list *bl)
case BL_NPC: return ((TBL_NPC*)bl)->vd;
case BL_HOM: return ((TBL_HOM*)bl)->vd;
case BL_MER: return ((TBL_MER*)bl)->vd;
case BL_ELEM: return ((TBL_ELEM*)bl)->vd;
}
return NULL;
}
@ -5287,6 +5402,8 @@ void status_set_viewdata(struct block_list *bl, int class_)
vd = merc_get_hom_viewdata(class_);
else if (merc_class(class_))
vd = merc_get_viewdata(class_);
else if (elemental_class(class_))
vd = elemental_get_viewdata(class_);
else
vd = NULL;
@ -5394,6 +5511,15 @@ void status_set_viewdata(struct block_list *bl, int class_)
ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_);
}
break;
case BL_ELEM:
{
struct elemental_data *ed = (struct elemental_data*)bl;
if (vd)
ed->vd = vd;
else
ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_);
}
break;
}
vd = status_get_viewdata(bl);
if (vd && vd->cloth_color && (
@ -5405,15 +5531,15 @@ void status_set_viewdata(struct block_list *bl, int class_)
}
/// Returns the status_change data of bl or NULL if it doesn't exist.
struct status_change *status_get_sc(struct block_list *bl)
{
struct status_change *status_get_sc(struct block_list *bl) {
if( bl )
switch (bl->type) {
case BL_PC: return &((TBL_PC*)bl)->sc;
case BL_MOB: return &((TBL_MOB*)bl)->sc;
case BL_NPC: return &((TBL_NPC*)bl)->sc;
case BL_HOM: return &((TBL_HOM*)bl)->sc;
case BL_MER: return &((TBL_MER*)bl)->sc;
case BL_PC: return &((TBL_PC*)bl)->sc;
case BL_MOB: return &((TBL_MOB*)bl)->sc;
case BL_NPC: return &((TBL_NPC*)bl)->sc;
case BL_HOM: return &((TBL_HOM*)bl)->sc;
case BL_MER: return &((TBL_MER*)bl)->sc;
case BL_ELEM: return &((TBL_ELEM*)bl)->sc;
}
return NULL;
}
@ -9336,8 +9462,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
break;
case SC_BLOODSUCKER:
if( --(sce->val4) >= 0 )
{
if( --(sce->val4) >= 0 ) {
struct block_list *src = map_id2bl(sce->val2);
int damage;
if( !src || (src && (status_isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) )

View File

@ -592,6 +592,8 @@ typedef enum sc_type {
SC_SOULCOLD, //510
SC_HAWKEYES,
SC_ODINS_POWER,
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
@ -1038,7 +1040,7 @@ enum si_type {
SI_COLD = 437,
SI_GLOOMYDAY = 438,
SI_SONGOFMANA = 439,
SI_CLOUD_KILL = 440,
SI_CLOUDKILL = 440,
SI_DANCEWITHWUG = 441,
SI_RUSHWINDMILL = 442,
SI_ECHOSONG = 443,
@ -1059,10 +1061,10 @@ enum si_type {
SI_FREEZE_SP = 458,
SI_GN_TRAINING_SWORD = 459,
SI_GN_REMODELING_CART = 460,
SI_GN_CARTBOOST = 461,
SI_CARTSBOOST = 461,
SI_FIXEDCASTINGTM_REDUCE = 462,
SI_THORNS_TRAP = 463,
SI_BLOOD_SUCKER = 464,
SI_THORNTRAP = 463,
SI_BLOODSUCKER = 464,
SI_SPORE_EXPLOSION = 465,
SI_DEMONIC_FIRE = 466,
SI_FIRE_EXPANSION_SMOKE_POWDER = 467,
@ -1132,11 +1134,11 @@ enum si_type {
SI_STONE_SHIELD = 531,
SI_STONE_SHIELD_OPTION = 532,
SI_POWER_OF_GAIA = 533,
SI_EL_WAIT = 534,
SI_EL_PASSIVE = 535,
SI_EL_DEFENSIVE = 536,
SI_EL_OFFENSIVE = 537,
SI_EL_COST = 538,
// SI_EL_WAIT = 534,
// SI_EL_PASSIVE = 535,
// SI_EL_DEFENSIVE = 536,
// SI_EL_OFFENSIVE = 537,
// SI_EL_COST = 538,
SI_PYROTECHNIC = 539,
SI_PYROTECHNIC_OPTION = 540,
SI_HEATER = 541,
@ -1671,6 +1673,7 @@ int status_change_clear_buffs(struct block_list* bl, int type);
#define status_calc_pc(sd, first) status_calc_bl_(&(sd)->bl, SCB_ALL, first)
#define status_calc_homunculus(hd, first) status_calc_bl_(&(hd)->bl, SCB_ALL, first)
#define status_calc_mercenary(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)
#define status_calc_elemental(ed, first) status_calc_bl_(&(ed)->bl, SCB_ALL, first)
void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first);
int status_calc_mob_(struct mob_data* md, bool first);
@ -1678,6 +1681,7 @@ int status_calc_pet_(struct pet_data* pd, bool first);
int status_calc_pc_(struct map_session_data* sd, bool first);
int status_calc_homunculus_(struct homun_data *hd, bool first);
int status_calc_mercenary_(struct mercenary_data *md, bool first);
int status_calc_elemental_(struct elemental_data *ed, bool first);
void status_calc_misc(struct block_list *bl, struct status_data *status, int level);
void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen);

View File

@ -16,6 +16,7 @@
#include "homunculus.h"
#include "instance.h"
#include "mercenary.h"
#include "elemental.h"
#include "skill.h"
#include "clif.h"
#include "duel.h"
@ -50,6 +51,7 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
if( bl->type == BL_NPC) return &((struct npc_data*)bl)->ud;
if( bl->type == BL_HOM) return &((struct homun_data*)bl)->ud;
if( bl->type == BL_MER) return &((struct mercenary_data*)bl)->ud;
if( bl->type == BL_ELEM) return &((struct elemental_data*)bl)->ud;
return NULL;
}
@ -2006,148 +2008,155 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
skill_cleartimerskill(bl);
}
switch( bl->type )
{
case BL_PC:
{
struct map_session_data *sd = (struct map_session_data*)bl;
switch( bl->type ) {
case BL_PC: {
struct map_session_data *sd = (struct map_session_data*)bl;
//Leave/reject all invitations.
if(sd->chatID)
chat_leavechat(sd,0);
if(sd->trade_partner)
trade_tradecancel(sd);
vending_closevending(sd);
buyingstore_close(sd);
searchstore_close(sd);
if(sd->state.storage_flag == 1)
storage_storage_quit(sd,0);
else if (sd->state.storage_flag == 2)
storage_guild_storage_quit(sd,0);
sd->state.storage_flag = 0; //Force close it when being warped.
if(sd->party_invite>0)
party_reply_invite(sd,sd->party_invite,0);
if(sd->guild_invite>0)
guild_reply_invite(sd,sd->guild_invite,0);
if(sd->guild_alliance>0)
guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
if(sd->menuskill_id)
sd->menuskill_id = sd->menuskill_val = 0;
if( sd->touching_id )
npc_touchnext_areanpc(sd,true);
//Leave/reject all invitations.
if(sd->chatID)
chat_leavechat(sd,0);
if(sd->trade_partner)
trade_tradecancel(sd);
vending_closevending(sd);
buyingstore_close(sd);
searchstore_close(sd);
if(sd->state.storage_flag == 1)
storage_storage_quit(sd,0);
else if (sd->state.storage_flag == 2)
storage_guild_storage_quit(sd,0);
sd->state.storage_flag = 0; //Force close it when being warped.
if(sd->party_invite>0)
party_reply_invite(sd,sd->party_invite,0);
if(sd->guild_invite>0)
guild_reply_invite(sd,sd->guild_invite,0);
if(sd->guild_alliance>0)
guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
if(sd->menuskill_id)
sd->menuskill_id = sd->menuskill_val = 0;
if( sd->touching_id )
npc_touchnext_areanpc(sd,true);
sd->npc_shopid = 0;
sd->adopt_invite = 0;
sd->npc_shopid = 0;
sd->adopt_invite = 0;
if(sd->pvp_timer != INVALID_TIMER) {
delete_timer(sd->pvp_timer,pc_calc_pvprank_timer);
sd->pvp_timer = INVALID_TIMER;
sd->pvp_rank = 0;
}
if(sd->duel_group > 0)
duel_leave(sd->duel_group, sd);
if(pc_issit(sd)) {
pc_setstand(sd);
skill_sit(sd,0);
}
party_send_dot_remove(sd);//minimap dot fix [Kevin]
guild_send_dot_remove(sd);
bg_send_dot_remove(sd);
if( map[bl->m].users <= 0 || sd->state.debug_remove_map )
{// this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS]
if( sd->debug_file == NULL || !(sd->state.debug_remove_map) )
{
sd->debug_file = "";
sd->debug_line = 0;
sd->debug_func = "";
if(sd->pvp_timer != INVALID_TIMER) {
delete_timer(sd->pvp_timer,pc_calc_pvprank_timer);
sd->pvp_timer = INVALID_TIMER;
sd->pvp_rank = 0;
}
ShowDebug("unit_remove_map: unexpected state when removing player AID/CID:%d/%d"
" (active=%d connect_new=%d rewarp=%d changemap=%d debug_remove_map=%d)"
" from map=%s (users=%d)."
" Previous call from %s:%d(%s), current call from %s:%d(%s)."
" Please report this!!!\n",
sd->status.account_id, sd->status.char_id,
sd->state.active, sd->state.connect_new, sd->state.rewarp, sd->state.changemap, sd->state.debug_remove_map,
map[bl->m].name, map[bl->m].users,
sd->debug_file, sd->debug_line, sd->debug_func, file, line, func);
}
else
if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
map_removemobs(bl->m);
if( !(sd->sc.option&OPTION_INVISIBLE) )
{// decrement the number of active pvp players on the map
--map[bl->m].users_pvp;
}
if( map[bl->m].instance_id )
{
instance[map[bl->m].instance_id].users--;
instance_check_idle(map[bl->m].instance_id);
}
sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS]
sd->debug_file = file;
sd->debug_line = line;
sd->debug_func = func;
if(sd->duel_group > 0)
duel_leave(sd->duel_group, sd);
break;
}
case BL_MOB:
{
struct mob_data *md = (struct mob_data*)bl;
// Drop previous target mob_slave_keep_target: no.
if (!battle_config.mob_slave_keep_target)
md->target_id=0;
if(pc_issit(sd)) {
pc_setstand(sd);
skill_sit(sd,0);
}
party_send_dot_remove(sd);//minimap dot fix [Kevin]
guild_send_dot_remove(sd);
bg_send_dot_remove(sd);
md->attacked_id=0;
md->state.skillstate= MSS_IDLE;
if( map[bl->m].users <= 0 || sd->state.debug_remove_map )
{// this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS]
if( sd->debug_file == NULL || !(sd->state.debug_remove_map) )
{
sd->debug_file = "";
sd->debug_line = 0;
sd->debug_func = "";
}
ShowDebug("unit_remove_map: unexpected state when removing player AID/CID:%d/%d"
" (active=%d connect_new=%d rewarp=%d changemap=%d debug_remove_map=%d)"
" from map=%s (users=%d)."
" Previous call from %s:%d(%s), current call from %s:%d(%s)."
" Please report this!!!\n",
sd->status.account_id, sd->status.char_id,
sd->state.active, sd->state.connect_new, sd->state.rewarp, sd->state.changemap, sd->state.debug_remove_map,
map[bl->m].name, map[bl->m].users,
sd->debug_file, sd->debug_line, sd->debug_func, file, line, func);
}
else
if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
map_removemobs(bl->m);
if( !(sd->sc.option&OPTION_INVISIBLE) )
{// decrement the number of active pvp players on the map
--map[bl->m].users_pvp;
}
if( map[bl->m].instance_id )
{
instance[map[bl->m].instance_id].users--;
instance_check_idle(map[bl->m].instance_id);
}
sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS]
sd->debug_file = file;
sd->debug_line = line;
sd->debug_func = func;
break;
}
case BL_PET:
{
struct pet_data *pd = (struct pet_data*)bl;
if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) )
{ //If logging out, this is deleted on unit_free
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,CLR_OUTSIGHT);
map_freeblock_unlock();
return 0;
break;
}
case BL_MOB: {
struct mob_data *md = (struct mob_data*)bl;
// Drop previous target mob_slave_keep_target: no.
if (!battle_config.mob_slave_keep_target)
md->target_id=0;
break;
}
case BL_HOM:
{
struct homun_data *hd = (struct homun_data *)bl;
ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick.
if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) )
{ //If logging out, this is deleted on unit_free
clif_emotion(bl, E_SOB);
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,CLR_OUTSIGHT);
map_freeblock_unlock();
return 0;
md->attacked_id=0;
md->state.skillstate= MSS_IDLE;
break;
}
break;
}
case BL_MER:
{
struct mercenary_data *md = (struct mercenary_data *)bl;
ud->canact_tick = ud->canmove_tick;
if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) )
{
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,CLR_OUTSIGHT);
map_freeblock_unlock();
return 0;
case BL_PET: {
struct pet_data *pd = (struct pet_data*)bl;
if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) )
{ //If logging out, this is deleted on unit_free
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,CLR_OUTSIGHT);
map_freeblock_unlock();
return 0;
}
break;
}
break;
}
default: ;// do nothing
case BL_HOM: {
struct homun_data *hd = (struct homun_data *)bl;
ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick.
if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) )
{ //If logging out, this is deleted on unit_free
clif_emotion(bl, E_SOB);
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,CLR_OUTSIGHT);
map_freeblock_unlock();
return 0;
}
break;
}
case BL_MER: {
struct mercenary_data *md = (struct mercenary_data *)bl;
ud->canact_tick = ud->canmove_tick;
if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) )
{
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,CLR_OUTSIGHT);
map_freeblock_unlock();
return 0;
}
break;
}
case BL_ELEM: {
struct elemental_data *ed = (struct elemental_data *)bl;
ud->canact_tick = ud->canmove_tick;
if( elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) )
{
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
unit_free(bl,0);
map_freeblock_unlock();
return 0;
}
break;
}
default: break;// do nothing
}
/**
* BL_MOB is handled by mob_dead unless the monster is not dead.
@ -2391,6 +2400,24 @@ int unit_free(struct block_list *bl, clr_type clrtype)
merc_contract_stop(md);
break;
}
case BL_ELEM: {
struct elemental_data *ed = (TBL_ELEM*)bl;
struct map_session_data *sd = ed->master;
if( clrtype >= 0 ) {
if( elemental_get_lifetime(ed) > 0 )
elemental_save(ed);
else {
intif_elemental_delete(ed->elemental.elemental_id);
if( sd )
sd->status.ele_id = 0;
}
}
if( sd )
sd->ed = NULL;
elemental_summon_stop(ed);
break;
}
}
skill_clear_unitgroup(bl);

View File

@ -154,6 +154,7 @@
<ClInclude Include="..\src\common\utils.h" />
<ClInclude Include="..\src\char\char.h" />
<ClInclude Include="..\src\char\int_auction.h" />
<ClInclude Include="..\src\char\int_elemental.h" />
<ClInclude Include="..\src\char\int_guild.h" />
<ClInclude Include="..\src\char\int_homun.h" />
<ClInclude Include="..\src\char\int_mail.h" />
@ -187,6 +188,7 @@
<ClCompile Include="..\src\common\utils.c" />
<ClCompile Include="..\src\char\char.c" />
<ClCompile Include="..\src\char\int_auction.c" />
<ClCompile Include="..\src\char\int_elemental.c" />
<ClCompile Include="..\src\char\int_guild.c" />
<ClCompile Include="..\src\char\int_homun.c" />
<ClCompile Include="..\src\char\int_mail.c" />

View File

@ -164,6 +164,7 @@
<ClInclude Include="..\src\map\clif.h" />
<ClInclude Include="..\src\map\date.h" />
<ClInclude Include="..\src\map\duel.h" />
<ClInclude Include="..\src\map\elemental.h" />
<ClInclude Include="..\src\map\guild.h" />
<ClInclude Include="..\src\map\intif.h" />
<ClInclude Include="..\src\map\itemdb.h" />
@ -231,6 +232,7 @@
<ClCompile Include="..\src\map\clif.c" />
<ClCompile Include="..\src\map\date.c" />
<ClCompile Include="..\src\map\duel.c" />
<ClCompile Include="..\src\map\elemental.c" />
<ClCompile Include="..\src\map\guild.c" />
<ClCompile Include="..\src\map\intif.c" />
<ClCompile Include="..\src\map\itemdb.c" />

View File

@ -464,6 +464,14 @@
RelativePath="..\src\char\int_mercenary.h"
>
</File>
<File
RelativePath="..\src\char\int_elemental.c"
>
</File>
<File
RelativePath="..\src\char\int_elemental.h"
>
</File>
<File
RelativePath="..\src\char\int_party.c"
>

View File

@ -603,6 +603,14 @@
RelativePath="..\src\map\mercenary.h"
>
</File>
<File
RelativePath="..\src\map\elemental.c"
>
</File>
<File
RelativePath="..\src\map\elemental.h"
>
</File>
<File
RelativePath="..\src\map\mob.c"
>