From 0e533fa7ab32e74c69b1a4a51336b46d5178b08d Mon Sep 17 00:00:00 2001 From: Aleos Date: Tue, 10 Feb 2015 09:33:00 -0500 Subject: [PATCH] Revert "Skill DB clean ups" --- db/const.txt | 5 - db/pre-re/skill_db.txt | 19 +- db/re/skill_db.txt | 19 +- doc/script_commands.txt | 8 +- npc/merchants/buying_shops.txt | 2 +- npc/other/gympass.txt | 4 +- .../upgrades/upgrade_20150131_skillset.sql | 6 - src/char/char.c | 51 +- src/common/mmo.h | 18 +- src/map/atcommand.c | 43 +- src/map/battle.c | 13 +- src/map/chrif.c | 24 +- src/map/clif.c | 107 +-- src/map/clif.h | 6 +- src/map/elemental.c | 18 +- src/map/guild.c | 95 +- src/map/guild.h | 2 +- src/map/homunculus.c | 48 +- src/map/homunculus.h | 2 - src/map/itemdb.h | 4 - src/map/mercenary.c | 39 +- src/map/mercenary.h | 1 - src/map/mob.c | 9 +- src/map/npc.c | 20 +- src/map/pc.c | 617 ++++++------- src/map/pc.h | 28 +- src/map/script.c | 42 +- src/map/skill.c | 836 ++++++++---------- src/map/skill.h | 168 ++-- src/map/status.c | 50 +- src/map/unit.c | 14 +- 31 files changed, 1016 insertions(+), 1302 deletions(-) delete mode 100644 sql-files/upgrades/upgrade_20150131_skillset.sql diff --git a/db/const.txt b/db/const.txt index c8a3d6d375..fe3f82d58d 100644 --- a/db/const.txt +++ b/db/const.txt @@ -4644,10 +4644,5 @@ BSF_REM_ON_MADOGEAR 0x080 BSF_REM_ON_DAMAGED 0x100 BSF_PERMANENT 0x200 -SKILL_PERM 0 -SKILL_TEMP 1 -SKILL_TEMPLEVEL 2 -SKILL_PERM_GRANT 3 - false 0 true 1 diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 82f4da4e3d..ce122606e4 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -504,7 +504,7 @@ 357,0,6,4,0,0x1,0,5,1,no,0,0,0,weapon,0,0x0, LK_CONCENTRATION,Concentration 358,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_TENSIONRELAX,Relax 359,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_BERSERK,Frenzy -360,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_FURY,Fury +//360,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_FURY,Fury //**** // High Priest @@ -553,10 +553,10 @@ //**** // Whitesmith 384,0,0,4,0,0x1,0,10,1,yes,0,0,0,weapon,0,0x4000, WS_MELTDOWN,Shattering Strike -385,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATECOIN,Create Coins -386,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATENUGGET,Create Nuggets +//385,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATECOIN,Create Coins +//386,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATENUGGET,Create Nuggets 387,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x4000, WS_CARTBOOST,Cart Boost -388,9,6,2,0,0x1,0,5,1,no,0,0,0,none,0,0x0, WS_SYSTEMCREATE,Auto Attack System +//388,9,6,2,0,0x1,0,5,1,no,0,0,0,none,0,0x0, WS_SYSTEMCREATE,Auto Attack System //**** // Stalker @@ -768,11 +768,6 @@ 543,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0, NJ_NEN,Soul 544,-5,6,1,0,0x40,0,10,1,no,0,0,0,weapon,0,0x0, NJ_ISSEN,Final Strike -572,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_DEATHKNIGHT,SL_DEATHKNIGHT -573,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_COLLECTOR,SL_COLLECTOR -574,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_NINJA,SL_NINJA -575,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_GUNNER,SL_GUNNER - //**** // Additional NPC Skills (Episode 11.3) 653,0,8,4,0,0x6,5:7:9:11:13:5:7:9:11:13,10,1,no,0,0x2,0,magic,0,0x0, NPC_EARTHQUAKE,Earthquake @@ -823,12 +818,12 @@ 689,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x1000, CASH_BLESSING,Party Blessing 690,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x1000, CASH_INCAGI,Party Increase AGI 691,0,6,4,0,0x3,-1,5,1,yes,0,0x2,0,magic,0,0x0, CASH_ASSUMPTIO,Party Assumptio -692,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_CATCRY,Cat Cry +//692,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_CATCRY,Cat Cry 693,0,6,4,0,0x3,-1,1,1,yes,0,0x2,0,magic,0,0x0, ALL_PARTYFLEE,Party Flee //694,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_ANGEL_PROTECT,Angel's Protection -695,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_DREAM_SUMMERNIGHT,Summer Night Dream +//695,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_DREAM_SUMMERNIGHT,Summer Night Dream //696,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, NPC_CHANGEUNDEAD2,Change Undead -697,9,6,4,0,0x1,0,1,1,yes,0,0x2,0,magic,0,0x0, ALL_REVERSEORCISH,Reverse Orcish +//697,9,6,4,0,0x1,0,1,1,yes,0,0x2,0,magic,0,0x0, ALL_REVERSEORCISH,Reverse Orcish 698,0,6,4,0,0x01,0,1,1,no,0,0x2,0,none,0,0x0, ALL_WEWISH,Christmas Carol //699,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_SONKRAN,ALL_SONKRAN diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index 89269628bb..a33ba5dd59 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -504,7 +504,7 @@ 357,0,6,4,0,0x1,0,5,1,no,0,0,0,weapon,0,0x0, LK_CONCENTRATION,Concentration 358,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_TENSIONRELAX,Relax 359,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_BERSERK,Frenzy -360,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_FURY,Fury +//360,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, LK_FURY,Fury //**** // High Priest @@ -553,10 +553,10 @@ //**** // Whitesmith 384,0,0,4,0,0x1,0,10,1,yes,0,0,0,weapon,0,0x4000, WS_MELTDOWN,Shattering Strike -385,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATECOIN,Create Coins -386,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATENUGGET,Create Nuggets +//385,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATECOIN,Create Coins +//386,0,0,4,0,0x1,0,1,1,yes,0,0,0,none,0,0x0, WS_CREATENUGGET,Create Nuggets 387,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x4000, WS_CARTBOOST,Cart Boost -388,9,6,2,0,0x1,0,5,1,no,0,0,0,none,0,0x0, WS_SYSTEMCREATE,Auto Attack System +//388,9,6,2,0,0x1,0,5,1,no,0,0,0,none,0,0x0, WS_SYSTEMCREATE,Auto Attack System //**** // Stalker @@ -768,11 +768,6 @@ 543,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0, NJ_NEN,Soul 544,-5,8,1,0,0x40,0,10,1,no,0,0,0,misc,0,0x0, NJ_ISSEN,Final Strike -572,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_DEATHKNIGHT,SL_DEATHKNIGHT -573,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_COLLECTOR,SL_COLLECTOR -574,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_NINJA,SL_NINJA -575,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, SL_GUNNER,SL_GUNNER - //**** // Additional NPC Skills (Episode 11.3) 653,0,8,4,0,0x6,5:7:9:11:13:5:7:9:11:13,10,1,no,0,0x2,0,magic,0,0x0, NPC_EARTHQUAKE,Earthquake @@ -823,10 +818,10 @@ 689,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x0, CASH_BLESSING,Party Blessing 690,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x0, CASH_INCAGI,Party Increase AGI 691,0,6,4,0,0x3,-1,5,1,yes,0,0x2,0,magic,0,0x0, CASH_ASSUMPTIO,Party Assumptio -692,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_CATCRY,Cat Cry +//692,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_CATCRY,Cat Cry 693,0,6,4,0,0x3,-1,1,1,yes,0,0x2,0,magic,0,0x0, ALL_PARTYFLEE,Party Flee -694,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_ANGEL_PROTECT,Angel's Protection -695,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_DREAM_SUMMERNIGHT,Summer Night Dream +//694,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_ANGEL_PROTECT,Angel's Protection +//695,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, ALL_DREAM_SUMMERNIGHT,Summer Night Dream //696,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0, NPC_CHANGEUNDEAD2,Change Undead 697,9,6,4,0,0x1,0,1,1,yes,0,0x2,0,magic,0,0x0, ALL_REVERSEORCISH,Reverse Orcish 698,0,6,4,0,0x01,0,1,1,no,0,0x2,0,none,0,0x0, ALL_WEWISH,Christmas Carol diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 07a2f71965..552755f325 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5411,15 +5411,9 @@ Flag 2 means that the level parameter is to be interpreted as a stackable additional bonus to the skill level. If the character did not have that skill previously, they will now at 0+the level given. -Flag 3 is the same as flag 1 in that it saves to the database. However, these skills +Flag 4 is the same as flag 1 in that it saves to the database. However, these skills are ignored when any action is taken that adjusts the skill tree (reset/job change). -Flag contants: - 0 - SKILL_PERM - 1 - SKILL_TEMP - 2 - SKILL_TEMPLEVEL - 3 - SKILL_PERM_GRANT - // This will permanently give the character Stone Throw (TF_THROWSTONE,152), at // level 1. skill 152,1,0; diff --git a/npc/merchants/buying_shops.txt b/npc/merchants/buying_shops.txt index 802be147c7..3da03e54cc 100644 --- a/npc/merchants/buying_shops.txt +++ b/npc/merchants/buying_shops.txt @@ -225,7 +225,7 @@ alberta_in,58,52,4 script Purchasing Team#Buying 59,{ mes "Okay, you're now approved to open the Bulk Buyer Shop."; set Zeny,Zeny-10000; getitem 6377,5; //Buy_Stall_Permit - skill "ALL_BUYING_STORE",1,SKILL_PERM_GRANT; + skill "ALL_BUYING_STORE",1,4; next; mes "[Mr. Hugh]"; mes "Currently, only normal items ^8C2121EXCEPT^000000 equipment, certain potions, and hand-crafted items can be purchased in bulk, but this can still be very beneficial to you, depending on how you use it."; diff --git a/npc/other/gympass.txt b/npc/other/gympass.txt index b522012ecd..078e5bc71d 100644 --- a/npc/other/gympass.txt +++ b/npc/other/gympass.txt @@ -79,7 +79,7 @@ payon,173,141,4 script Ripped Cabus#GymPass 899,{ mes "training together like this."; delitem 7776,1; //Max_Weight_Up_Scroll set gympassmemory,.@add_carry; - skill "ALL_INCCARRY",.@add_carry,SKILL_PERM_GRANT; + skill "ALL_INCCARRY",.@add_carry,4; close; } else { @@ -135,7 +135,7 @@ payon,173,141,4 script Ripped Cabus#GymPass 899,{ mes "muscles grew back,"; mes "just like that! Try not to"; mes "wimp out again, okay?"; - skill "ALL_INCCARRY",gympassmemory,SKILL_PERM_GRANT; + skill "ALL_INCCARRY",gympassmemory,4; close; } else { diff --git a/sql-files/upgrades/upgrade_20150131_skillset.sql b/sql-files/upgrades/upgrade_20150131_skillset.sql deleted file mode 100644 index e60ea411aa..0000000000 --- a/sql-files/upgrades/upgrade_20150131_skillset.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Resetting all `lv` of skills that has `flag` >= 3 (the skill that its `learned_lv` has been changed by script or special case by `learned_lv` + SKILL_FLAG_REPLACED_LV_0) --- If there's ALL_INCCARRY and ALL_BUYING_STORE, set the `flag` to SKILL_FLAG_PERM_GRANTED (new value is 3), those are exclusive skills given in our official scripts! - -UPDATE `skill` SET `lv` = `flag` - 3 WHERE `flag` >= 3; -UPDATE `skill` SET `flag` = 0 WHERE `flag` >= 3; -UPDATE `skill` SET `flag` = 3 WHERE `id` = 681 OR `id` = 2535; diff --git a/src/char/char.c b/src/char/char.c index 1ad603ff65..3b04ffc990 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -434,6 +434,12 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ strcat(save_status, " memo"); } + //FIXME: is this neccessary? [ultramage] + for(i=0;iskill[i].lv != 0) && (p->skill[i].id == 0)) + p->skill[i].id = i; // Fix skill tree + + //skills if( memcmp(p->skill, cp->skill, sizeof(p->skill)) ) { @@ -938,6 +944,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) { //===================================================================================================== int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything) { int i,j; + char t_msg[128] = ""; struct mmo_charstatus* cp; StringBuf buf; SqlStmt* stmt; @@ -947,13 +954,11 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev struct point tmp_point; struct item tmp_item; struct s_skill tmp_skill; - uint16 skill_count = 0; struct s_friend tmp_friend; #ifdef HOTKEY_SAVING struct hotkey tmp_hotkey; int hotkey_num; #endif - StringBuf msg_buf; memset(p, 0, sizeof(struct mmo_charstatus)); @@ -1060,13 +1065,11 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev p->save_point.y = MAP_DEFAULT_Y; } - StringBuf_Init(&msg_buf); - StringBuf_AppendStr(&msg_buf, " status"); + strcat(t_msg, " status"); if (!load_everything) // For quick selection of data when displaying the char menu { SqlStmt_Free(stmt); - StringBuf_Destroy(&msg_buf); return 1; } @@ -1085,7 +1088,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev tmp_point.map = mapindex_name2id(point_map); memcpy(&p->memo_point[i], &tmp_point, sizeof(tmp_point)); } - StringBuf_AppendStr(&msg_buf, " memo"); + strcat(t_msg, " memo"); //read inventory //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `expire_time`, `favorite`, `unique_id`) @@ -1117,7 +1120,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->inventory[i], &tmp_item, sizeof(tmp_item)); - StringBuf_AppendStr(&msg_buf, " inventory"); + strcat(t_msg, " inventory"); //read cart //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, expire_time`, `unique_id`) @@ -1147,34 +1150,33 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->cart[i], &tmp_item, sizeof(tmp_item)); - StringBuf_AppendStr(&msg_buf, " cart"); + strcat(t_msg, " cart"); //read storage storage_fromsql(p->account_id, &p->storage); - StringBuf_AppendStr(&msg_buf, " storage"); + strcat(t_msg, " storage"); //read skill //`skill` (`char_id`, `id`, `lv`) if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.skill_db, MAX_SKILL) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_UINT16, &tmp_skill.id , 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UINT8 , &tmp_skill.lv , 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UINT8 , &tmp_skill.flag, 0, NULL, NULL) ) + || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) + || SQL_ERROR == SqlStmt_Execute(stmt) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id , 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UCHAR , &tmp_skill.lv , 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UCHAR , &tmp_skill.flag, 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); if( tmp_skill.flag != SKILL_FLAG_PERM_GRANTED ) tmp_skill.flag = SKILL_FLAG_PERMANENT; - for( i = 0; skill_count < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ ) { - if( tmp_skill.id > 0 && tmp_skill.id < MAX_SKILL_ID ) { - memcpy(&p->skill[i], &tmp_skill, sizeof(tmp_skill)); - skill_count++; - } + for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) + { + if( tmp_skill.id < ARRAYLENGTH(p->skill) ) + memcpy(&p->skill[tmp_skill.id], &tmp_skill, sizeof(tmp_skill)); else ShowWarning("mmo_char_fromsql: ignoring invalid skill (id=%u,lv=%u) of character %s (AID=%d,CID=%d)\n", tmp_skill.id, tmp_skill.lv, p->name, p->account_id, p->char_id); } - StringBuf_Printf(&msg_buf, " %d skills", skill_count); + strcat(t_msg, " skills"); //read friends //`friends` (`char_id`, `friend_account`, `friend_id`) @@ -1188,7 +1190,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev for( i = 0; i < MAX_FRIENDS && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->friends[i], &tmp_friend, sizeof(tmp_friend)); - StringBuf_AppendStr(&msg_buf, " friends"); + strcat(t_msg, " friends"); #ifdef HOTKEY_SAVING //read hotkeys @@ -1209,21 +1211,20 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev else ShowWarning("mmo_char_fromsql: ignoring invalid hotkey (hotkey=%d,type=%u,id=%u,lv=%u) of character %s (AID=%d,CID=%d)\n", hotkey_num, tmp_hotkey.type, tmp_hotkey.id, tmp_hotkey.lv, p->name, p->account_id, p->char_id); } - StringBuf_AppendStr(&msg_buf, " hotkeys"); + strcat(t_msg, " hotkeys"); #endif /* Mercenary Owner DataBase */ mercenary_owner_fromsql(char_id, p); - StringBuf_AppendStr(&msg_buf, " mercenary"); + strcat(t_msg, " mercenary"); - if (charserv_config.save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfuly! + if (charserv_config.save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly! SqlStmt_Free(stmt); StringBuf_Destroy(&buf); cp = idb_ensure(char_db_, char_id, char_create_charstatus); memcpy(cp, p, sizeof(struct mmo_charstatus)); - StringBuf_Destroy(&msg_buf); return 1; } diff --git a/src/common/mmo.h b/src/common/mmo.h index 4f77068cd3..375e86dd5a 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -54,7 +54,7 @@ #define MAX_BANK_ZENY SINT32_MAX ///Max zeny in Bank #define MAX_FAME 1000000000 ///Max fame points #define MAX_CART 100 ///Maximum item in cart -#define MAX_SKILL 1200 ///Maximum skill can be hold by Player, Homunculus, & Mercenary (skill list) AND skill_db limit +#define MAX_SKILL 5020 ///Maximum skill data #define GLOBAL_REG_NUM 256 ///Max permanent character variables per char #define ACCOUNT_REG_NUM 64 ///Max permanent local account variables per account #define ACCOUNT_REG2_NUM 16 ///Max permanent global account variables per account @@ -223,11 +223,10 @@ enum e_skill_flag SKILL_FLAG_PERMANENT, SKILL_FLAG_TEMPORARY, SKILL_FLAG_PLAGIARIZED, - SKILL_FLAG_PERM_GRANTED, // Permanent, granted through someway e.g. script - SKILL_FLAG_TMP_COMBO, //@FIXME for homunculus combo atm - - //! NOTE: This flag be the last flag, and don't change the value if not needed! - SKILL_FLAG_REPLACED_LV_0 = 10, // temporary skill overshadowing permanent skill of level 'N - SKILL_FLAG_REPLACED_LV_0', + SKILL_FLAG_REPLACED_LV_0, // temporary skill overshadowing permanent skill of level 'N - SKILL_FLAG_REPLACED_LV_0', + SKILL_FLAG_PERM_GRANTED, // permanent, granted through someway e.g. script + SKILL_FLAG_TMP_COMBO, //@FIXME for homon combo atm + //... }; enum e_mmo_charstatus_opt { @@ -237,9 +236,9 @@ enum e_mmo_charstatus_opt { }; struct s_skill { - uint16 id; - uint8 lv; - uint8 flag; // see enum e_skill_flag + unsigned short id; + unsigned char lv; + unsigned char flag; // see enum e_skill_flag }; struct global_reg { @@ -625,7 +624,6 @@ enum e_guild_skill { GD_MAX, }; -#define MAX_SKILL_ID GD_MAX //These mark the ID of the jobs, as expected by the client. [Skotlex] enum e_job { diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 98866be41b..bd87d013d3 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -32,7 +32,6 @@ #include "trade.h" #include "mapreg.h" #include "quest.h" -#include "pc.h" #include #include @@ -3251,7 +3250,7 @@ ACMD_FUNC(questskill) return -1; } - if (skill_id >= MAX_SKILL_ID) { + if (skill_id >= MAX_SKILL_DB) { clif_displaymessage(fd, msg_txt(sd,198)); // This skill number doesn't exist. return -1; } @@ -3264,7 +3263,7 @@ ACMD_FUNC(questskill) return -1; } - pc_skill(sd, skill_id, 1, ADDSKILL_PERMANENT); + pc_skill(sd, skill_id, 1, 0); clif_displaymessage(fd, msg_txt(sd,70)); // You have learned the skill. return 0; @@ -3275,7 +3274,7 @@ ACMD_FUNC(questskill) *------------------------------------------*/ ACMD_FUNC(lostskill) { - uint16 skill_id = 0, sk_idx = 0; + uint16 skill_id; nullpo_retr(-1, sd); if (!message || !*message || (skill_id = atoi(message)) <= 0) @@ -3295,7 +3294,7 @@ ACMD_FUNC(lostskill) return -1; } - if (!(sk_idx = skill_get_index(skill_id))) { + if (skill_id >= MAX_SKILL) { clif_displaymessage(fd, msg_txt(sd,198)); // This skill number doesn't exist. return -1; } @@ -3308,8 +3307,8 @@ ACMD_FUNC(lostskill) return -1; } - sd->status.skill[sk_idx].lv = 0; - sd->status.skill[sk_idx].flag = SKILL_FLAG_PERMANENT; + sd->status.skill[skill_id].lv = 0; + sd->status.skill[skill_id].flag = SKILL_FLAG_PERMANENT; clif_deleteskill(sd,skill_id); clif_displaymessage(fd, msg_txt(sd,71)); // You have forgotten the skill. @@ -5508,11 +5507,11 @@ ACMD_FUNC(skillid) { for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) { int idx = skill_get_index(db_data2i(data)); - if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_db[idx]->desc, message, skillen) == 0) { - sprintf(atcmd_output, msg_txt(sd,1164), db_data2i(data), skill_db[idx]->desc, key.str); // skill %d: %s (%s) + if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) { + sprintf(atcmd_output, msg_txt(sd,1164), db_data2i(data), skill_db[idx].desc, key.str); // skill %d: %s (%s) clif_displaymessage(fd, atcmd_output); - } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill_db[idx]->desc,message) ) ) { - snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(sd,1164), db_data2i(data), skill_db[idx]->desc, key.str); + } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill_db[idx].desc,message) ) ) { + snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(sd,1164), db_data2i(data), skill_db[idx].desc, key.str); } } @@ -5560,7 +5559,7 @@ ACMD_FUNC(useskill) return -1; } - if (SKILL_CHK_HOMUN(skill_id) + if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd && hom_is_active(sd->hd)) // (If used with @useskill, put the homunc as dest) bl = &sd->hd->bl; else @@ -5644,7 +5643,7 @@ ACMD_FUNC(skilltree) { if( ent->need[j].id && pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) { - sprintf(atcmd_output, msg_txt(sd,1170), ent->need[j].lv, skill_db[ent->need[j].id]->desc); // Player requires level %d of skill %s. + sprintf(atcmd_output, msg_txt(sd,1170), ent->need[j].lv, skill_db[ent->need[j].id].desc); // Player requires level %d of skill %s. clif_displaymessage(fd, atcmd_output); meets = 0; } @@ -9119,14 +9118,13 @@ ACMD_FUNC(unloadnpcfile) { return 0; } ACMD_FUNC(cart) { -#define MC_CART_MDFY(idx, x) \ - sd->status.skill[(idx)].id = x?MC_PUSHCART:0; \ - sd->status.skill[(idx)].lv = x?1:0; \ - sd->status.skill[(idx)].flag = x?SKILL_FLAG_TEMPORARY:SKILL_FLAG_PERMANENT; +#define MC_CART_MDFY(x) \ + sd->status.skill[MC_PUSHCART].id = x?MC_PUSHCART:0; \ + sd->status.skill[MC_PUSHCART].lv = x?1:0; \ + sd->status.skill[MC_PUSHCART].flag = x?SKILL_FLAG_TEMPORARY:SKILL_FLAG_PERMANENT; int val = atoi(message); bool need_skill = (pc_checkskill(sd, MC_PUSHCART) == 0); - uint16 sk_idx = 0; if( !message || !*message || val < 0 || val > MAX_CARTS ) { sprintf(atcmd_output, msg_txt(sd,1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>). @@ -9139,22 +9137,19 @@ ACMD_FUNC(cart) { return -1; } - if (!(sk_idx = skill_get_index(MC_PUSHCART))) - return -1; - if( need_skill ) { - MC_CART_MDFY(sk_idx,1); + MC_CART_MDFY(1); } if( !pc_setcart(sd, val) ) { if( need_skill ) { - MC_CART_MDFY(sk_idx,0); + MC_CART_MDFY(0); } return -1;/* @cart failed */ } if( need_skill ) { - MC_CART_MDFY(sk_idx,0); + MC_CART_MDFY(0); } clif_displaymessage(fd, msg_txt(sd,1392)); // Cart Added diff --git a/src/map/battle.c b/src/map/battle.c index af3ab24d64..084d9608ef 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1883,10 +1883,10 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list * struct s_skill_damage *damage = NULL; struct map_data *mapd = &map[m]; - if (!idx || !skill_db[idx]->damage.map) + if (!idx || !skill_db[idx].damage.map) return 0; - damage = &skill_db[idx]->damage; + damage = &skill_db[idx].damage; //check the adjustment works for specified type if (!battle_skill_damage_iscaster(damage->caster, src->type)) @@ -6945,12 +6945,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } } if (sd) { - uint16 r_skill = 0, sk_idx = 0; if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 && - (r_skill = (uint16)sc->data[SC__AUTOSHADOWSPELL]->val1) && (sk_idx = skill_get_index(r_skill)) && - sd->status.skill[sk_idx].id != 0 && sd->status.skill[sk_idx].flag == SKILL_FLAG_PLAGIARIZED ) + sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id != 0 && sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].flag == SKILL_FLAG_PLAGIARIZED ) { - int r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2; + int r_skill = sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id, + r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2; if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) { int type; @@ -7790,7 +7789,7 @@ static const struct _battle_data { { "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, }, { "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, }, { "character_size", &battle_config.character_size, 1|2, 0, 1|2, }, - { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_MOBSKILL_LEVEL, 1, MAX_MOBSKILL_LEVEL, }, + { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, }, { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, }, { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, }, { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, }, diff --git a/src/map/chrif.c b/src/map/chrif.c index e60dbfb729..4810b7f524 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -951,21 +951,19 @@ int chrif_changedsex(int fd) { if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) { int i; // remove specifical skills of Bard classes - for(i = BA_MUSICALLESSON; i <= BA_APPLEIDUN; i++) { - uint16 sk_idx = skill_get_index(i); - if (sd->status.skill[sk_idx].id > 0 && sd->status.skill[sk_idx].flag == SKILL_FLAG_PERMANENT) { - sd->status.skill_point += sd->status.skill[sk_idx].lv; - sd->status.skill[sk_idx].id = 0; - sd->status.skill[sk_idx].lv = 0; + for(i = 315; i <= 322; i++) { + if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { + sd->status.skill_point += sd->status.skill[i].lv; + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; } } // remove specifical skills of Dancer classes - for(i = DC_DANCINGLESSON; i <= DC_SERVICEFORYOU; i++) { - uint16 sk_idx = skill_get_index(i); - if (sd->status.skill[sk_idx].id > 0 && sd->status.skill[sk_idx].flag == SKILL_FLAG_PERMANENT) { - sd->status.skill_point += sd->status.skill[sk_idx].lv; - sd->status.skill[sk_idx].id = 0; - sd->status.skill[sk_idx].lv = 0; + for(i = 323; i <= 330; i++) { + if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { + sd->status.skill_point += sd->status.skill[i].lv; + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; } } clif_updatestatus(sd, SP_SKILLPOINT); @@ -1032,7 +1030,7 @@ int chrif_divorceack(uint32 char_id, int partner_id) { *------------------------------------------*/ int chrif_deadopt(int father_id, int mother_id, int child_id) { struct map_session_data* sd; - uint16 idx = skill_get_index(WE_CALLBABY); + int idx = skill_get_index(WE_CALLBABY); if( father_id && ( sd = map_charid2sd(father_id) ) != NULL && sd->status.child == child_id ) { sd->status.child = 0; diff --git a/src/map/clif.c b/src/map/clif.c index db7c3501c8..f121a50fbb 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1486,7 +1486,7 @@ int clif_homskillinfoblock(struct map_session_data *sd) { //[orn] struct homun_data *hd; int fd = sd->fd; - int i, len=4; + int i,j,len=4; WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL); hd = sd->hd; @@ -1498,17 +1498,15 @@ int clif_homskillinfoblock(struct map_session_data *sd) int id = hd->homunculus.hskill[i].id; if( id != 0 ){ int combo = (hd->homunculus.hskill[i].flag)&SKILL_FLAG_TMP_COMBO; - short idx = hom_skill_get_index(id); - if (idx == -1) - continue; + j = id - HM_SKILLBASE; WFIFOW(fd,len ) = id; WFIFOW(fd,len+2) = ((combo)?INF_SELF_SKILL:skill_get_inf(id)); WFIFOW(fd,len+4) = 0; - WFIFOW(fd,len+6) = hd->homunculus.hskill[idx].lv; - WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[idx].lv); - WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[idx].lv); + WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv; + WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[j].lv); + WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv); safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); - WFIFOB(fd,len+36) = (hd->homunculus.hskill[idx].lv < hom_skill_tree_get_max(id, hd->homunculus.class_))?1:0; + WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < hom_skill_tree_get_max(id, hd->homunculus.class_))?1:0; len+=37; } } @@ -1521,15 +1519,12 @@ int clif_homskillinfoblock(struct map_session_data *sd) void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn] struct homun_data *hd; - int fd; - short idx = -1; + int fd, idx; nullpo_retv(sd); + idx = skill_id - HM_SKILLBASE; - if ((idx = hom_skill_get_index(skill_id) == -1)) - return; - - fd = sd->fd; - hd = sd->hd; + fd=sd->fd; + hd=sd->hd; WFIFOHEAD(fd, packet_len(0x239)); WFIFOW(fd,0) = 0x239; @@ -4822,9 +4817,8 @@ void clif_skillinfoblock(struct map_session_data *sd) nullpo_retv(sd); - fd = sd->fd; - if (!fd) - return; + fd=sd->fd; + if (!fd) return; WFIFOHEAD(fd, MAX_SKILL * 37 + 4); WFIFOW(fd,0) = 0x10f; @@ -4868,30 +4862,28 @@ void clif_skillinfoblock(struct map_session_data *sd) /// Adds new skill to the skill tree (ZC_ADD_SKILL). /// 0111 .W .L .W .W .W .24B .B -void clif_addskill(struct map_session_data *sd, int skill_id) +void clif_addskill(struct map_session_data *sd, int id) { int fd; - uint16 idx = 0; nullpo_retv(sd); fd = sd->fd; - if (!fd || !(idx = skill_get_index(skill_id))) - return; + if (!fd) return; - if( sd->status.skill[idx].id <= 0 ) + if( sd->status.skill[id].id <= 0 ) return; WFIFOHEAD(fd, packet_len(0x111)); WFIFOW(fd,0) = 0x111; - WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = skill_get_inf(skill_id); - WFIFOW(fd,8) = sd->status.skill[idx].lv; - WFIFOW(fd,10) = skill_get_sp(skill_id,sd->status.skill[idx].lv); - WFIFOW(fd,12)= skill_get_range2(&sd->bl, skill_id,sd->status.skill[idx].lv); - safestrncpy((char*)WFIFOP(fd,14), skill_get_name(skill_id), NAME_LENGTH); - if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,38) = (sd->status.skill[idx].lv < skill_tree_get_max(skill_id, sd->status.class_))? 1:0; + WFIFOW(fd,2) = id; + WFIFOL(fd,4) = skill_get_inf(id); + WFIFOW(fd,8) = sd->status.skill[id].lv; + WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv); + WFIFOW(fd,12)= skill_get_range2(&sd->bl, id,sd->status.skill[id].lv); + safestrncpy((char*)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH); + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) + WFIFOB(fd,38) = (sd->status.skill[id].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,38) = 0; WFIFOSET(fd,packet_len(0x111)); @@ -4900,21 +4892,18 @@ void clif_addskill(struct map_session_data *sd, int skill_id) /// Deletes a skill from the skill tree (ZC_SKILLINFO_DELETE). /// 0441 .W -void clif_deleteskill(struct map_session_data *sd, int skill_id) +void clif_deleteskill(struct map_session_data *sd, int id) { #if PACKETVER >= 20081217 int fd; - uint16 idx = 0; nullpo_retv(sd); - fd = sd->fd; - if (!fd || !(idx = skill_get_index(skill_id))) - return; + if( !fd ) return; WFIFOHEAD(fd,packet_len(0x441)); WFIFOW(fd,0) = 0x441; - WFIFOW(fd,2) = skill_id; + WFIFOW(fd,2) = id; WFIFOSET(fd,packet_len(0x441)); #endif clif_skillinfoblock(sd); @@ -4923,7 +4912,7 @@ void clif_deleteskill(struct map_session_data *sd, int skill_id) /// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE). /// 010e .W .W .W .W .B void clif_skillup(struct map_session_data *sd, uint16 skill_id, int lv, int range, int upgradable) { - int fd; + int fd; nullpo_retv(sd); @@ -4941,22 +4930,19 @@ void clif_skillup(struct map_session_data *sd, uint16 skill_id, int lv, int rang /// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE2). /// 07e1 .W .L .W .W .W .B -void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf) +void clif_skillinfo(struct map_session_data *sd,int skill, int inf) { const int fd = sd->fd; - uint16 idx = skill_get_index(skill_id); - if (!idx) - return; WFIFOHEAD(fd,packet_len(0x7e1)); WFIFOW(fd,0) = 0x7e1; - WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = inf?inf:skill_get_inf(skill_id); - WFIFOW(fd,8) = sd->status.skill[idx].lv; - WFIFOW(fd,10) = skill_get_sp(skill_id,sd->status.skill[idx].lv); - WFIFOW(fd,12) = skill_get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv); - if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,14) = (sd->status.skill[idx].lv < skill_tree_get_max(skill_id, sd->status.class_))? 1:0; + WFIFOW(fd,2) = skill; + WFIFOL(fd,4) = inf?inf:skill_get_inf(skill); + WFIFOW(fd,8) = sd->status.skill[skill].lv; + WFIFOW(fd,10) = skill_get_sp(skill,sd->status.skill[skill].lv); + WFIFOW(fd,12) = skill_get_range2(&sd->bl,skill,sd->status.skill[skill].lv); + if( sd->status.skill[skill].flag == SKILL_FLAG_PERMANENT ) + WFIFOB(fd,14) = (sd->status.skill[skill].lv < skill_tree_get_max(skill, sd->status.class_))? 1:0; else WFIFOB(fd,14) = 0; WFIFOSET(fd,packet_len(0x7e1)); @@ -11380,12 +11366,12 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if (tmp&INF_GROUND_SKILL || !tmp) return; //Using a ground/passive skill on a target? WRONG. - if( SKILL_CHK_HOMUN(skill_id) ) { + if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL ) { clif_parse_UseSkillToId_homun(sd->hd, sd, tick, skill_id, skill_lv, target_id); return; } - if( SKILL_CHK_MERC(skill_id) ) { + if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) { clif_parse_UseSkillToId_mercenary(sd->md, sd, tick, skill_id, skill_lv, target_id); return; } @@ -11454,7 +11440,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) sd->skillitem = sd->skillitemlv = 0; - if( SKILL_CHK_GUILD(skill_id) ) { + if( skill_id >= GD_SKILLBASE ) { if( sd->state.gmaster_flag ) skill_lv = guild_checkskill(sd->guild, skill_id); else @@ -11481,12 +11467,12 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin if( !(skill_get_inf(skill_id)&INF_GROUND_SKILL) ) return; //Using a target skill on the ground? WRONG. - if( SKILL_CHK_HOMUN(skill_id) ) { + if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL ) { clif_parse_UseSkillToPos_homun(sd->hd, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); return; } - if( SKILL_CHK_MERC(skill_id) ) { + if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) { clif_parse_UseSkillToPos_mercenary(sd->md, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); return; } @@ -15695,18 +15681,15 @@ void clif_mercenary_skillblock(struct map_session_data *sd) WFIFOW(fd,0) = 0x29d; for( i = 0; i < MAX_MERCSKILL; i++ ) { - uint16 id; - short idx = -1; + int id, j; if( (id = md->db->skill[i].id) == 0 ) continue; - if ((idx = mercenary_skill_get_index(id)) == -1) - continue; - + j = id - MC_SKILLBASE; WFIFOW(fd,len) = id; WFIFOL(fd,len+2) = skill_get_inf(id); - WFIFOW(fd,len+6) = md->db->skill[idx].lv; - WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[idx].lv); - WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[idx].lv); + WFIFOW(fd,len+6) = md->db->skill[j].lv; + WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[j].lv); + WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[j].lv); safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; diff --git a/src/map/clif.h b/src/map/clif.h index 4a578b13fb..6907b6d11c 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -532,9 +532,9 @@ void clif_class_change(struct block_list *bl,int class_,int type); void clif_skillinfoblock(struct map_session_data *sd); void clif_skillup(struct map_session_data *sd, uint16 skill_id, int lv, int range, int upgradable); -void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf); -void clif_addskill(struct map_session_data *sd, int skill_id); -void clif_deleteskill(struct map_session_data *sd, int skill_id); +void clif_skillinfo(struct map_session_data *sd,int skill, int inf); +void clif_addskill(struct map_session_data *sd, int id); +void clif_deleteskill(struct map_session_data *sd, int id); void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime); void clif_skillcastcancel(struct block_list* bl); diff --git a/src/map/elemental.c b/src/map/elemental.c index 643dd456aa..5d7017ec5d 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -9,7 +9,6 @@ #include "../common/showmsg.h" #include "../common/random.h" #include "../common/strlib.h" -#include "../common/utils.h" #include "log.h" #include "clif.h" @@ -559,12 +558,13 @@ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 memset(&req,0,sizeof(req)); if( idx == 0 ) // invalid skill id + return req; + + if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) return req; - skill_lv = cap_value(skill_lv, 1, MAX_SKILL_LEVEL); - - req.hp = skill_db[idx]->require.hp[skill_lv-1]; - req.sp = skill_db[idx]->require.sp[skill_lv-1]; + req.hp = skill_db[idx].require.hp[skill_lv-1]; + req.sp = skill_db[idx].require.sp[skill_lv-1]; return req; } @@ -815,7 +815,6 @@ void read_elementaldb(void) { uint8 i; elemental_count = 0; - memset(elemental_db, 0, sizeof(elemental_db)); for(i = 0; i= EL_SKILLBASE + MAX_ELEMENTALSKILL ) { + ShowError("read_elemental_skilldb_sub: Skill out of range, line %d.\n", current); return false; } diff --git a/src/map/guild.c b/src/map/guild.c index 4ac3a0df1c..5e0b8c8cab 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -64,20 +64,6 @@ static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data struct npc_data **guild_flags; unsigned short guild_flags_count; -/** - * Get guild skill index in guild_skill_tree - * @param skill_id - * @return Index in skill_tree or -1 - **/ -static short guild_skill_get_index(uint16 skill_id) { - if (!SKILL_CHK_GUILD(skill_id)) - return -1; - skill_id -= GD_SKILLBASE; - if (skill_id >= MAX_GUILDSKILL) - return -1; - return skill_id; -} - /*========================================== * Retrieves and validates the sd pointer for this guild member [Skotlex] *------------------------------------------*/ @@ -98,41 +84,44 @@ static TBL_PC* guild_sd_check(int guild_id, uint32 account_id, uint32 char_id) { // Modified [Komurka] int guild_skill_get_max (int id) { - if ((id = guild_skill_get_index(id)) < 0) + if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL) return 0; - return guild_skill_tree[id].max; + return guild_skill_tree[id-GD_SKILLBASE].max; } // Retrive skill_lv learned by guild int guild_checkskill(struct guild *g, int id) { - if ((id = guild_skill_get_index(id)) < 0) + int idx = id - GD_SKILLBASE; + if (idx < 0 || idx >= MAX_GUILDSKILL) return 0; - return g->skill[id].lv; + return g->skill[idx].lv; } /*========================================== * guild_skill_tree.txt reading - from jA [Komurka] *------------------------------------------*/ static bool guild_read_guildskill_tree_db(char* split[], int columns, int current) {// ,,,,,,,,,,, - int k, skill_id = atoi(split[0]); - short idx = -1; + int k, id, skill_id; - if ((idx = guild_skill_get_index(skill_id)) < 0) { - ShowError("guild_read_guildskill_tree_db: Invalid Guild skill '%s'.\n", split[1]); + skill_id = atoi(split[0]); + id = skill_id - GD_SKILLBASE; + + if( id < 0 || id >= MAX_GUILDSKILL ) { + ShowWarning("guild_read_guildskill_tree_db: Invalid skill id %d.\n", skill_id); return false; } - guild_skill_tree[idx].id = skill_id; - guild_skill_tree[idx].max = atoi(split[1]); + guild_skill_tree[id].id = skill_id; + guild_skill_tree[id].max = atoi(split[1]); - if( guild_skill_tree[idx].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[idx].max == 0 ) {// enable guild's glory when required for emblems - guild_skill_tree[idx].max = 1; + if( guild_skill_tree[id].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max == 0 ) {// enable guild's glory when required for emblems + guild_skill_tree[id].max = 1; } for( k = 0; k < MAX_GUILD_SKILL_REQUIRE; k++ ) { - guild_skill_tree[idx].need[k].id = atoi(split[k*2+2]); - guild_skill_tree[idx].need[k].lv = atoi(split[k*2+3]); + guild_skill_tree[id].need[k].id = atoi(split[k*2+2]); + guild_skill_tree[id].need[k].lv = atoi(split[k*2+3]); } return true; @@ -142,13 +131,13 @@ static bool guild_read_guildskill_tree_db(char* split[], int columns, int curren * Guild skill check - from jA [Komurka] *------------------------------------------*/ int guild_check_skill_require(struct guild *g,int id) { - uint8 i; - short idx = -1; + int i; + int idx = id-GD_SKILLBASE; if(g == NULL) return 0; - if ((idx = guild_skill_get_index(id)) < 0) + if (idx < 0 || idx >= MAX_GUILDSKILL) return 0; for(i=0;istatus.guild_id == 0 || (g=sd->guild) == NULL || // no guild - strcmp(sd->status.name, g->master) ) // not the guild master - return; - - max = guild_skill_get_max(skill_id); + if( idx < 0 || idx >= MAX_GUILDSKILL || // not a guild skill + sd->status.guild_id == 0 || (g=sd->guild) == NULL || // no guild + strcmp(sd->status.name, g->master) ) // not the guild master + return 0; if( g->skill_point > 0 && - g->skill[idx].id != 0 && - g->skill[idx].lv < max ) + g->skill[idx].id != 0 && + g->skill[idx].lv < max ) intif_guild_skillup(g->guild_id, skill_id, sd->status.account_id, max); + + return 0; } /*==================================================== * Notification of guildskill skill_id increase request *---------------------------------------------------*/ int guild_skillupack(int guild_id,uint16 skill_id,uint32 account_id) { - struct map_session_data *sd = map_id2sd(account_id); - struct guild *g = guild_search(guild_id); + struct map_session_data *sd=map_id2sd(account_id); + struct guild *g=guild_search(guild_id); int i; - short idx = guild_skill_get_index(skill_id); - - if (g == NULL || idx == -1) + if(g==NULL) return 0; - if (sd != NULL) { - int lv = g->skill[idx].lv; + if( sd != NULL ) { + int lv = g->skill[skill_id-GD_SKILLBASE].lv; int range = skill_get_range(skill_id, lv); clif_skillup(sd,skill_id,lv,range,1); @@ -1312,14 +1297,14 @@ int guild_skillupack(int guild_id,uint16 skill_id,uint32 account_id) { case GD_GLORYWOUNDS: case GD_SOULCOLD: case GD_HAWKEYES: - guild_guildaura_refresh(sd,skill_id,g->skill[idx].lv); + guild_guildaura_refresh(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv); break; } } // Inform all members - for (i = 0; i < g->max_member; i++) - if ((sd = g->member[i].sd) != NULL) + for(i=0;imax_member;i++) + if((sd=g->member[i].sd)!=NULL) clif_guild_skillinfo(sd); return 0; diff --git a/src/map/guild.h b/src/map/guild.h index 94b842551d..36d8b93084 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -60,7 +60,7 @@ int guild_member_withdraw(int guild_id,uint32 account_id,uint32 char_id,int flag const char *name,const char *mes); int guild_expulsion(struct map_session_data *sd,int guild_id, uint32 account_id,uint32 char_id,const char *mes); -void guild_skillup(struct map_session_data* sd, uint16 skill_id); +int guild_skillup(struct map_session_data* sd, uint16 skill_id); void guild_block_skill(struct map_session_data *sd, int time); int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd); int guild_reply_reqalliance(struct map_session_data *sd,uint32 account_id,int flag); diff --git a/src/map/homunculus.c b/src/map/homunculus.c index cb3947023f..2577959fed 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -38,11 +38,10 @@ static struct view_data hom_viewdb[MAX_HOMUNCULUS_CLASS]; * @param skill_id * @return -1 if invalid skill or skill index for homunculus skill_tree */ -short hom_skill_get_index(uint16 skill_id) { - if (!SKILL_CHK_HOMUN(skill_id)) +static short hom_skill_get_index(int skill_id) { + if (!skill_get_index(skill_id)) return -1; - skill_id -= HM_SKILLBASE; - if (skill_id >= MAX_HOMUNSKILL) + if ((skill_id -= HM_SKILLBASE) < 0 || skill_id >= MAX_HOMUNSKILL) return -1; return skill_id; } @@ -125,8 +124,8 @@ int hom_class2mapid(int hom_class) void hom_addspiritball(TBL_HOM *hd, int max) { nullpo_retv(hd); - if (max > MAX_SPIRITBALL) - max = MAX_SPIRITBALL; + if (max > MAX_SKILL_LEVEL) + max = MAX_SKILL_LEVEL; if (hd->homunculus.spiritball < 0) hd->homunculus.spiritball = 0; @@ -153,8 +152,8 @@ void hom_delspiritball(TBL_HOM *hd, int count, int type) { } if (count <= 0) return; - if (count > MAX_SPIRITBALL) - count = MAX_SPIRITBALL; + if (count > MAX_SKILL_LEVEL) + count = MAX_SKILL_LEVEL; if (count > hd->homunculus.spiritball) count = hd->homunculus.spiritball; @@ -269,7 +268,7 @@ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve) /* load previous homunculus form skills first. */ if (hd->homunculus.prev_class != 0 && (c = hom_class2index(hd->homunculus.prev_class)) >= 0) { for (i = 0; i < MAX_SKILL_TREE && (skill_id = hskill_tree[c][i].id) > 0; i++) { - short idx = hom_skill_get_index(skill_id); + int idx = hom_skill_get_index(skill_id); if (idx < 0) continue; if (hd->homunculus.hskill[idx].id) @@ -297,7 +296,7 @@ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve) for (i = 0; i < MAX_SKILL_TREE && (skill_id = hskill_tree[c][i].id) > 0; i++) { int intimacy; - short idx = hom_skill_get_index(skill_id); + int idx = hom_skill_get_index(skill_id); if (idx < 0) continue; if (hd->homunculus.hskill[idx].id) @@ -332,7 +331,7 @@ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve) */ short hom_checkskill(struct homun_data *hd,uint16 skill_id) { - short idx = hom_skill_get_index(skill_id); + int idx = hom_skill_get_index(skill_id); if (idx < 0) // Invalid skill return 0; @@ -1461,9 +1460,8 @@ void read_homunculusdb(void) { */ static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) {// ,,[,],,,,,,,,,,, - uint16 skill_id; - uint8 i; - short class_idx, idx = -1; + int skill_id, class_idx; + int i, j; int minJobLevelPresent = 0; if (columns == 14) @@ -1471,27 +1469,29 @@ static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) // check for bounds [celest] if ((class_idx = hom_class2index(atoi(split[0]))) == -1) { - ShowWarning("read_homunculus_skilldb: Invalid homunculus class %d.\n", atoi(split[0])); + ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0])); return false; } - skill_id = atoi(split[1]); - if ((idx = hom_skill_get_index(skill_id)) == -1) { - ShowError("read_homunculus_skilldb: Invalid Homunculus skill '%s'.\n", split[1]); + skill_id = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] + // Search an empty line or a line with the same skill_id (stored in j) + ARR_FIND( 0, MAX_SKILL_TREE, j, !hskill_tree[class_idx][j].id || hskill_tree[class_idx][j].id == skill_id ); + if (j == MAX_SKILL_TREE) { + ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", skill_id, atoi(split[0])); return false; } - hskill_tree[class_idx][idx].id = skill_id; - hskill_tree[class_idx][idx].max = atoi(split[2]); + hskill_tree[class_idx][j].id = skill_id; + hskill_tree[class_idx][j].max = atoi(split[2]); if (minJobLevelPresent) - hskill_tree[class_idx][idx].joblv = atoi(split[3]); + hskill_tree[class_idx][j].joblv = atoi(split[3]); for (i = 0; i < MAX_HOM_SKILL_REQUIRE; i++) { - hskill_tree[class_idx][idx].need[i].id = atoi(split[3+i*2+minJobLevelPresent]); - hskill_tree[class_idx][idx].need[i].lv = atoi(split[3+i*2+minJobLevelPresent+1]); + hskill_tree[class_idx][j].need[i].id = atoi(split[3+i*2+minJobLevelPresent]); + hskill_tree[class_idx][j].need[i].lv = atoi(split[3+i*2+minJobLevelPresent+1]); } - hskill_tree[class_idx][idx].intimacylv = atoi(split[13+minJobLevelPresent]); + hskill_tree[class_idx][j].intimacylv = atoi(split[13+minJobLevelPresent]); return true; } diff --git a/src/map/homunculus.h b/src/map/homunculus.h index fbdf5bd2f5..f764dba5d6 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -159,8 +159,6 @@ void hom_delspiritball(TBL_HOM *hd, int count, int type); uint8 hom_get_intimacy_grade(struct homun_data *hd); -short hom_skill_get_index(uint16 skill_id); - void do_final_homunculus(void); void do_init_homunculus(void); diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 882c97ee71..4956786b60 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -325,12 +325,8 @@ enum e_item_ammo AMMO_KUNAI, AMMO_CANNONBALL, AMMO_THROWABLE_ITEM, ///Sling items - - MAX_AMMO_TYPE, }; -#define AMMO_TYPE_ALL ((1<= MAX_MERCSKILL) - return -1; - return skill_id; -} - /** * Create a new Mercenary for Player * @param sd The Player @@ -459,11 +445,14 @@ void mercenary_kills(struct mercenary_data *md){ * @return Skill Level or 0 if Mercenary doesn't have the skill **/ int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id) { - short idx = mercenary_skill_get_index(skill_id); + int i = skill_id - MC_SKILLBASE; - if( !md || !md->db || idx == -1) + if( !md || !md->db ) return 0; - return md->db->skill[idx].lv; + if( md->db->skill[i].id == skill_id ) + return md->db->skill[i].lv; + + return 0; } /** @@ -540,7 +529,6 @@ static bool mercenary_readdb_sub(char* str[], int columns, int current) void mercenary_readdb(void) { const char *filename[]={ "mercenary_db.txt",DBIMPORT"/mercenary_db.txt"}; uint8 i; - mercenary_count = 0; //Reset the counter memset(mercenary_db,0,sizeof(mercenary_db)); for(i = 0; i,, struct s_mercenary_db *db; - uint16 class_, skill_id, skill_lv; - uint8 i = 0; - short idx = -1; + uint16 i, class_, skill_id, skill_lv; class_ = atoi(str[0]); ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_); @@ -567,16 +553,18 @@ static bool mercenary_read_skilldb_sub(char* str[], int columns, int current) } skill_id = atoi(str[1]); - if( (idx = mercenary_skill_get_index(skill_id)) == -1 ) { - ShowError("read_mercenary_skilldb: Invalid Mercenary skill '%s'.\n", str[1]); + if( skill_id < MC_SKILLBASE || skill_id >= MC_SKILLBASE + MAX_MERCSKILL ) + { + ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skill_id); return false; } db = &mercenary_db[i]; skill_lv = atoi(str[2]); - db->skill[idx].id = skill_id; - db->skill[idx].lv = skill_lv; + i = skill_id - MC_SKILLBASE; + db->skill[i].id = skill_id; + db->skill[i].lv = skill_lv; return true; } @@ -587,7 +575,6 @@ static bool mercenary_read_skilldb_sub(char* str[], int columns, int current) void mercenary_read_skilldb(void){ const char *filename[]={ "mercenary_skill_db.txt",DBIMPORT"/mercenary_skill_db.txt"}; uint8 i; - for(i = 0; i=0 && i< MAX_MOBSKILL ;j--) { - uint16 skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id; - uint16 sk_idx = 0; - if (!skill_id || !(sk_idx = skill_get_index(skill_id)) || sd->status.skill[sk_idx].lv < 1 || + int skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id; + if (!skill_id || sd->status.skill[skill_id].lv < 1 || (skill_get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) || skill_get_nocast(skill_id)&16 ) @@ -3514,7 +3513,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons memset (&ms[i], 0, sizeof(struct mob_skill)); ms[i].skill_id = skill_id; - ms[i].skill_lv = sd->status.skill[sk_idx].lv; + ms[i].skill_lv = sd->status.skill[skill_id].lv; ms[i].state = MSS_ANY; ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5% ms[i].emotion = -1; @@ -4290,7 +4289,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) //Skill ID j = atoi(str[3]); - if (j <= 0 || j > MAX_SKILL_ID || !skill_get_index(j)) //fixed Lupus + if (j <= 0 || j > MAX_SKILL_DB) //fixed Lupus { if (mob_id < 0) ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j); diff --git a/src/map/npc.c b/src/map/npc.c index b577a31f91..1a3c894c2e 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -112,12 +112,12 @@ int npc_isnear_sub(struct block_list* bl, va_list args) { if (skill_id > 0) { //If skill_id > 0 that means is used for INF2_NO_NEARNPC [Cydh] uint16 idx = skill_get_index(skill_id); - if (idx > 0 && skill_db[idx]->unit_nonearnpc_type) { + if (idx > 0 && skill_db[idx].unit_nonearnpc_type) { while (1) { - if (skill_db[idx]->unit_nonearnpc_type&1 && nd->subtype == NPCTYPE_WARP) break; - if (skill_db[idx]->unit_nonearnpc_type&2 && nd->subtype == NPCTYPE_SHOP) break; - if (skill_db[idx]->unit_nonearnpc_type&4 && nd->subtype == NPCTYPE_SCRIPT) break; - if (skill_db[idx]->unit_nonearnpc_type&8 && nd->subtype == NPCTYPE_TOMB) break; + if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == NPCTYPE_WARP) break; + if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == NPCTYPE_SHOP) break; + if (skill_db[idx].unit_nonearnpc_type&4 && nd->subtype == NPCTYPE_SCRIPT) break; + if (skill_db[idx].unit_nonearnpc_type&8 && nd->subtype == NPCTYPE_TOMB) break; return 0; } } @@ -1687,9 +1687,8 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) // custom merchant shop exp bonus if( battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 ) { - uint16 sk_idx = skill_get_index(MC_DISCOUNT); - if( sd->status.skill[sk_idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) - skill = sd->status.skill[sk_idx].flag - SKILL_FLAG_REPLACED_LV_0; + if( sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0; if( skill > 0 ) { @@ -1851,9 +1850,8 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) // custom merchant shop exp bonus if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0) { - uint16 sk_idx = skill_get_index(MC_OVERCHARGE); - if( sd->status.skill[sk_idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) - skill = sd->status.skill[sk_idx].flag - SKILL_FLAG_REPLACED_LV_0; + if( sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0; if( skill > 0 ) { diff --git a/src/map/pc.c b/src/map/pc.c index 6f8ed3aba7..f7fea6464b 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -934,12 +934,12 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, clif_updatestatus(b_sd, SP_JOBEXP); // Baby Skills - pc_skill(b_sd, WE_BABY, 1, ADDSKILL_PERMANENT); - pc_skill(b_sd, WE_CALLPARENT, 1, ADDSKILL_PERMANENT); + pc_skill(b_sd, WE_BABY, 1, 0); + pc_skill(b_sd, WE_CALLPARENT, 1, 0); // Parents Skills - pc_skill(p1_sd, WE_CALLBABY, 1, ADDSKILL_PERMANENT); - pc_skill(p2_sd, WE_CALLBABY, 1, ADDSKILL_PERMANENT); + pc_skill(p1_sd, WE_CALLBABY, 1, 0); + pc_skill(p2_sd, WE_CALLBABY, 1, 0); return true; } @@ -1248,7 +1248,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ * Check if player have any item cooldowns on **/ pc_itemcd_do(sd,true); - pc_validate_skill(sd); #ifdef BOUND_ITEMS // Party bound item check @@ -1356,7 +1355,7 @@ void pc_reg_received(struct map_session_data *sd) if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) { sd->cloneskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM)); - if (sd->cloneskill_idx > 0) { + if (sd->cloneskill_idx >= 0) { sd->status.skill[sd->cloneskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM); sd->status.skill[sd->cloneskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM_LV); if (sd->status.skill[sd->cloneskill_idx].lv > i) @@ -1366,7 +1365,7 @@ void pc_reg_received(struct map_session_data *sd) } if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) { sd->reproduceskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_REPRODUCE)); - if (sd->reproduceskill_idx > 0) { + if (sd->reproduceskill_idx >= 0) { sd->status.skill[sd->reproduceskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE); sd->status.skill[sd->reproduceskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV); if (i < sd->status.skill[sd->reproduceskill_idx].lv) @@ -1449,20 +1448,21 @@ void pc_reg_received(struct map_session_data *sd) static int pc_calc_skillpoint(struct map_session_data* sd) { - uint16 i, skill_point = 0; + uint16 i, skill_point=0; nullpo_ret(sd); - for(i = 1; i < MAX_SKILL; i++) { - if( sd->status.skill[i].id && sd->status.skill[i].lv > 0) { - uint16 inf2 = skill_get_inf2(sd->status.skill[i].id); - if ((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && + for(i=1;i 0) { + uint16 inf2 = skill_get_inf2(i); + if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex] - ) - { + ) { if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - skill_point += sd->status.skill[i].lv; - else if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0) + skill_point += skill_lv; + else + if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0) skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); } } @@ -1471,57 +1471,6 @@ static int pc_calc_skillpoint(struct map_session_data* sd) return skill_point; } -static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) { - uint16 i = 0; - - if (!sd || !pc_has_permission(sd, PC_PERM_ALL_SKILL) || !SKILL_MAX_DB()) - return false; - - /** - * Dummy skills must NOT be added here otherwise they'll be displayed in the, - * skill tree and since they have no icons they'll give resource errors - * Get ALL skills except npc/guild ones. [Skotlex] - * Don't add SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] - **/ - for( i = 0; i < MAX_SKILL; i++ ) { - uint16 skill_id = skill_idx2id(i); - if (!skill_id || (skill_get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_GUILD_SKILL))) - continue; - switch (skill_id) { - case SM_SELFPROVOKE: - case AB_DUPLELIGHT_MELEE: - case AB_DUPLELIGHT_MAGIC: - case WL_CHAINLIGHTNING_ATK: - case WL_TETRAVORTEX_FIRE: - case WL_TETRAVORTEX_WATER: - case WL_TETRAVORTEX_WIND: - case WL_TETRAVORTEX_GROUND: - case WL_SUMMON_ATK_FIRE: - case WL_SUMMON_ATK_WIND: - case WL_SUMMON_ATK_WATER: - case WL_SUMMON_ATK_GROUND: - case LG_OVERBRAND_BRANDISH: - case LG_OVERBRAND_PLUSATK: - case WM_SEVERE_RAINSTORM_MELEE: - case RL_R_TRIP_PLUSATK: - case SG_DEVIL: - case MO_TRIPLEATTACK: - case RG_SNATCHER: - continue; - default: - { - uint8 lv = (uint8)skill_get_max(skill_id); - if (lv > 0) { - sd->status.skill[i].id = skill_id; - if (addlv) - sd->status.skill[i].lv = lv; - } - } - break; - } - } - return true; -} /*========================================== * Calculation of skill level. @@ -1529,8 +1478,8 @@ static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) { *------------------------------------------*/ void pc_calc_skilltree(struct map_session_data *sd) { - int i, flag; - int c = 0; + int i,flag; + int c=0; nullpo_retv(sd); i = pc_calc_skilltree_normalize_job(sd); @@ -1547,52 +1496,41 @@ void pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].id = 0; //First clear skills. /* permanent skills that must be re-checked */ if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) { - uint16 sk_id = skill_idx2id(i); - if (!sk_id) { - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; - continue; - } - switch (sk_id) { + switch( i ) { case NV_TRICKDEAD: if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) { - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } break; } } } - for( i = 0; i < MAX_SKILL; i++ ) { - uint16 skill_id = 0; - - // Restore original level of skills after deleting earned skills. - if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) { + for( i = 0; i < MAX_SKILL; i++ ) + { + if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) + { // Restore original level of skills after deleting earned skills. sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } - //Enable Bard/Dancer spirit linked skills. - if (!(skill_id = skill_idx2id(i)) || skill_id < DC_HUMMING || skill_id > DC_SERVICEFORYOU) - continue; - - if( &sd->sc && sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER ) { - //Link Dancer skills to bard. - if( sd->status.sex ) { + if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU ) + { //Enable Bard/Dancer spirit linked skills. + if( sd->status.sex ) + { //Link dancer skills to bard. if( sd->status.skill[i-8].lv < 10 ) continue; - sd->status.skill[i].id = skill_id; + sd->status.skill[i].id = i; sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } - //Link Bard skills to dancer. - else { + else + { //Link bard skills to dancer. if( sd->status.skill[i].lv < 10 ) continue; - sd->status.skill[i-8].id = skill_id - 8; + sd->status.skill[i-8].id = i - 8; sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } @@ -1602,84 +1540,105 @@ void pc_calc_skilltree(struct map_session_data *sd) // Removes Taekwon Ranker skill bonus if ((sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON) { uint16 c_ = pc_class2idx(JOB_TAEKWON); - for (i = 0; i < MAX_SKILL_TREE; i++) { - uint16 sk_id = skill_tree[c_][i].id; - uint16 sk_idx = 0; - - if (!sk_id || !(sk_idx = skill_get_index(skill_tree[c_][i].id))) - continue; - - if (sd->status.skill[sk_idx].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[sk_idx].flag != SKILL_FLAG_PERM_GRANTED) { - if (sk_id == NV_BASIC || sk_id == NV_FIRSTAID || sk_id == WE_CALLBABY) + uint16 x = skill_get_index(skill_tree[c_][i].id), skid = sd->status.skill[x].id; + if (skid && x > 0 && sd->status.skill[x].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[x].flag != SKILL_FLAG_PERM_GRANTED) { + if (skid == NV_BASIC || skid == NV_FIRSTAID || skid == WE_CALLBABY) continue; - sd->status.skill[sk_idx].id = 0; - sd->status.skill[sk_idx].lv = 0; - sd->status.skill[sk_idx].flag = SKILL_FLAG_PERMANENT; + sd->status.skill[x].id = 0; } } } - // Grant all skills - pc_grant_allskills(sd, false); + if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { + for( i = 0; i < MAX_SKILL; i++ ) { + switch(i) { + /** + * Dummy skills must be added here otherwise they'll be displayed in the, + * skill tree and since they have no icons they'll give resource errors + **/ + case SM_SELFPROVOKE: + case AB_DUPLELIGHT_MELEE: + case AB_DUPLELIGHT_MAGIC: + case WL_CHAINLIGHTNING_ATK: + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + case WL_SUMMON_ATK_FIRE: + case WL_SUMMON_ATK_WIND: + case WL_SUMMON_ATK_WATER: + case WL_SUMMON_ATK_GROUND: + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + case WM_SEVERE_RAINSTORM_MELEE: + case RL_R_TRIP_PLUSATK: + continue; + default: + break; + } + if( skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) + continue; //Only skills you can't have are npc/guild ones + if( skill_get_max(i) > 0 ) + sd->status.skill[i].id = i; + } + return; + } do { - uint16 skid = 0; - + short skid=0; flag = 0; - for (i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++) { - bool fail = false; - uint16 sk_idx = skill_get_index(skid); - - if (sd->status.skill[sk_idx].id) + for( i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ ) + { + int f; + if( sd->status.skill[skid].id ) continue; //Skill already known. - if (!battle_config.skillfree) { - uint8 j; + f = 1; + if(!battle_config.skillfree) { + int j; for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - uint16 sk_need_id = skill_tree[c][i].need[j].id; - uint16 sk_need_idx = 0; - - if (sk_need_id && (sk_need_idx = skill_get_index(sk_need_id))) { - short sk_need = 0; - - if (sd->status.skill[sk_need_idx].id == 0 || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_PLAGIARIZED) - sk_need = sk_need_id; //Not learned. - else if (sd->status.skill[sk_need_idx].flag >= SKILL_FLAG_REPLACED_LV_0) //Real learned level - sk_need = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; + int k; + if((k=skill_tree[c][i].need[j].id)) + { + if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED) + k = 0; //Not learned. else - sk_need = pc_checkskill(sd,sk_need_id); - - if (sk_need < skill_tree[c][i].need[j].lv) { - fail = true; + if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real learned level + k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; + else + k = pc_checkskill(sd,k); + if (k < skill_tree[c][i].need[j].lv) + { + f = 0; break; } } } - - if (sd->status.job_level < skill_tree[c][i].joblv) { //We need to get the actual class in this case + if( sd->status.job_level < skill_tree[c][i].joblv ) { //We need to get the actual class in this case int class_ = pc_mapid2jobid(sd->class_, sd->status.sex); class_ = pc_class2idx(class_); if (class_ == c || (class_ != c && sd->status.job_level < skill_tree[class_][i].joblv)) - fail = true; // job level requirement wasn't satisfied + f = 0; // job level requirement wasn't satisfied } } - if (!fail) { - int inf2 = skill_get_inf2(skid); + if( f ) { + int inf2; + inf2 = skill_get_inf2(skid); - if (!sd->status.skill[skid].lv && ( + if(!sd->status.skill[skid].lv && ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || inf2&INF2_WEDDING_SKILL || (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) )) continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. - sd->status.skill[sk_idx].id = skid; + sd->status.skill[skid].id = skid; if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed. - sd->status.skill[sk_idx].lv = 1; // need to manually specify a skill level - sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. + sd->status.skill[skid].lv = 1; // need to manually specify a skill level + sd->status.skill[skid].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. } flag = 1; // skill list has changed, perform another pass } @@ -1687,7 +1646,7 @@ void pc_calc_skilltree(struct map_session_data *sd) } while(flag); if( c > 0 && sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) { - unsigned short skid = 0; + short skid=0; /* Taekwon Ranker Bonus Skill Tree ============================================ - Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking. @@ -1695,28 +1654,25 @@ void pc_calc_skilltree(struct map_session_data *sd) - (sd->status.skill_point == 0) to wait until all skill points are assigned to avoid problems with Job Change quest. */ for( i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ ) { - uint16 sk_idx = 0; - if (!(sk_idx = skill_get_index(skid))) - continue; if( (skill_get_inf2(skid)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) continue; //Do not include Quest/Wedding skills. - if( sd->status.skill[sk_idx].id == 0 ) { //do we really want skid as index ? //Lighta - sd->status.skill[sk_idx].id = skid; - sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. + if( sd->status.skill[skid].id == 0 ) { //do we really want skid as index ? //Lighta + sd->status.skill[skid].id = skid; + sd->status.skill[skid].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. } else if( skid != NV_BASIC ) - sd->status.skill[sk_idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[sk_idx].lv; // Remember original level - sd->status.skill[sk_idx].lv = skill_tree_get_max(skid, sd->status.class_); + sd->status.skill[skid].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[skid].lv; // Remember original level + sd->status.skill[skid].lv = skill_tree_get_max(skid, sd->status.class_); } } } //Checks if you can learn a new skill after having leveled up a skill. -static void pc_check_skilltree(struct map_session_data *sd) +static void pc_check_skilltree(struct map_session_data *sd, int skill) { - int i, flag = 0; - int c = 0; + int i,id=0,flag; + int c=0; - if (battle_config.skillfree) + if(battle_config.skillfree) return; //Function serves no purpose if this is set i = pc_calc_skilltree_normalize_job(sd); @@ -1726,54 +1682,44 @@ static void pc_check_skilltree(struct map_session_data *sd) return; } c = pc_class2idx(c); - do { - uint16 skid = 0; - flag = 0; - for (i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ ) { - uint16 sk_idx = skill_get_index(skid); - bool fail = false; - uint8 j = 0; - - if (sd->status.skill[sk_idx].id) //Already learned + for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ ) + { + int j, f = 1; + if( sd->status.skill[id].id ) //Already learned continue; - - for (j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - uint16 sk_need_id = skill_tree[c][i].need[j].id; - uint16 sk_need_idx = 0; - - if (sk_need_id && (sk_need_idx = skill_get_index(sk_need_id))) { - short sk_need = sk_need_id; - - if (sd->status.skill[sk_need_idx].id == 0 || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_PLAGIARIZED) - sk_need = 0; //Not learned. - else if (sd->status.skill[sk_need_idx].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level - sk_need = sd->status.skill[sk_need_idx].flag - SKILL_FLAG_REPLACED_LV_0; + for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ){ + int k = skill_tree[c][i].need[j].id; + if( k != 0 ){ + if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED ) + k = 0; //Not learned. else - sk_need = pc_checkskill(sd,sk_need_id); - - if (sk_need < skill_tree[c][i].need[j].lv) { - fail = true; + if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; + else + k = pc_checkskill(sd,k); + if( k < skill_tree[c][i].need[j].lv ) + { + f = 0; break; } } } - - if( fail ) + if( !f ) continue; if( sd->status.job_level < skill_tree[c][i].joblv ) continue; - j = skill_get_inf2(skid); - if( !sd->status.skill[sk_idx].lv && ( + j = skill_get_inf2(id); + if( !sd->status.skill[id].lv && ( (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || j&INF2_WEDDING_SKILL || (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) ) ) continue; //Cannot be learned via normal means. - sd->status.skill[sk_idx].id = skid; + sd->status.skill[id].id = id; flag = 1; } } while(flag); @@ -1785,12 +1731,14 @@ void pc_clean_skilltree(struct map_session_data *sd) { uint16 i; for (i = 0; i < MAX_SKILL; i++){ - if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) { + if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) + { sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } - else if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0){ + else + if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0){ sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } @@ -3868,78 +3816,74 @@ void pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type * 2 - Like 1, except the level granted can stack with previously learned level. * 4 - Like 0, except the skill will ignore skill tree (saves through job changes and resets). *------------------------------------------*/ -bool pc_skill(TBL_PC* sd, uint16 skill_id, int level, enum e_addskill_type type) { - uint16 idx = 0; +int pc_skill(TBL_PC* sd, int id, int level, int flag) +{ nullpo_ret(sd); - if (!skill_id || !(idx = skill_get_index(skill_id))) { - ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", skill_id); - return false; + if( id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) { + ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id); + return 0; } - if (level > MAX_SKILL_LEVEL) { + if( level > MAX_SKILL_LEVEL ) { ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL); - return false; + return 0; } - if (type == ADDSKILL_TEMP_ADDLEVEL && sd->status.skill[idx].lv + level > MAX_SKILL_LEVEL) { - ShowWarning("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d. Set to max level.\n", level, MAX_SKILL_LEVEL, sd->status.skill[idx].lv); - level = MAX_SKILL_LEVEL - sd->status.skill[idx].lv; + if( flag == 2 && sd->status.skill[id].lv + level > MAX_SKILL_LEVEL ) { + ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[id].lv); + return 0; } - switch (type) { - case ADDSKILL_PERMANENT: //Set skill data overwriting whatever was there before. - sd->status.skill[idx].id = skill_id; - sd->status.skill[idx].lv = level; - sd->status.skill[idx].flag = SKILL_FLAG_PERMANENT; - if (level == 0) { //Remove skill. - sd->status.skill[idx].id = 0; - clif_deleteskill(sd,skill_id); + switch( flag ){ + case 0: //Set skill data overwriting whatever was there before. + sd->status.skill[id].id = id; + sd->status.skill[id].lv = level; + sd->status.skill[id].flag = SKILL_FLAG_PERMANENT; + if( level == 0 ) { //Remove skill. + sd->status.skill[id].id = 0; + clif_deleteskill(sd,id); } else - clif_addskill(sd,skill_id); - if (!skill_get_inf(skill_id)) //Only recalculate for passive skills. + clif_addskill(sd,id); + if( !skill_get_inf(id) ) //Only recalculate for passive skills. status_calc_pc(sd, SCO_NONE); break; - - case ADDSKILL_TEMP: //Item bonus skill. - if (sd->status.skill[idx].id != 0) { - if (sd->status.skill[idx].lv >= level) - return true; - if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) //Non-granted skill, store it's level. - sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; + case 1: //Item bonus skill. + if( sd->status.skill[id].id == id ) { + if( sd->status.skill[id].lv >= level ) + return 0; + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level. + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; } else { - sd->status.skill[idx].id = skill_id; - sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; + sd->status.skill[id].id = id; + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; } - sd->status.skill[idx].lv = level; + sd->status.skill[id].lv = level; break; - - case ADDSKILL_TEMP_ADDLEVEL: //Add skill bonus on top of what you had. - if (sd->status.skill[idx].id != 0) { - if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) - sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Store previous level. + case 2: //Add skill bonus on top of what you had. + if( sd->status.skill[id].id == id ) { + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level. } else { - sd->status.skill[idx].id = skill_id; - sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. + sd->status.skill[id].id = id; + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. } - sd->status.skill[idx].lv += level; + sd->status.skill[id].lv += level; break; - - case ADDSKILL_PERMANENT_GRANTED: //Permanent granted skills ignore the skill tree - sd->status.skill[idx].id = skill_id; - sd->status.skill[idx].lv = level; - sd->status.skill[idx].flag = SKILL_FLAG_PERM_GRANTED; - if (level == 0) { //Remove skill. - sd->status.skill[idx].id = 0; - clif_deleteskill(sd,skill_id); + case 4: //Permanent granted skills ignore the skill tree + sd->status.skill[id].id = id; + sd->status.skill[id].lv = level; + sd->status.skill[id].flag = SKILL_FLAG_PERM_GRANTED; + if( level == 0 ) { //Remove skill. + sd->status.skill[id].id = 0; + clif_deleteskill(sd,id); } else - clif_addskill(sd,skill_id); - if (!skill_get_inf(skill_id)) //Only recalculate for passive skills. + clif_addskill(sd,id); + if( !skill_get_inf(id) ) //Only recalculate for passive skills. status_calc_pc(sd, SCO_NONE); break; - - default: - return false; + default: //Unknown flag? + return 0; } - return true; + return 1; } /*========================================== * Append a card to an item ? @@ -5485,8 +5429,8 @@ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 sk int cooldown = 0, cooldownlen = ARRAYLENGTH(sd->skillcooldown); if (!idx) return 0; - if (skill_db[idx]->cooldown[skill_lv - 1]) - cooldown = skill_db[idx]->cooldown[skill_lv - 1]; + if (skill_db[idx].cooldown[skill_lv - 1]) + cooldown = skill_db[idx].cooldown[skill_lv - 1]; ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id); if (i < cooldownlen) { @@ -5499,23 +5443,24 @@ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 sk /*========================================== * Return player sd skill_lv learned for given skill *------------------------------------------*/ -uint8 pc_checkskill(struct map_session_data *sd, uint16 skill_id) +uint8 pc_checkskill(struct map_session_data *sd,uint16 skill_id) { - uint16 i = 0, idx = 0; - if (sd == NULL) - return 0; - if ((idx = skill_get_index(skill_id)) == 0) { - ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id); - return 0; - } - if (SKILL_CHK_GUILD(skill_id) ) { + if(sd == NULL) return 0; + if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) { struct guild *g; if( sd->status.guild_id>0 && (g=sd->guild)!=NULL) return guild_checkskill(g,skill_id); return 0; + } else if(skill_id >= ARRAYLENGTH(sd->status.skill) ) { + ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id); + return 0; } - return sd->status.skill[idx].lv; + + if(sd->status.skill[skill_id].id == skill_id) + return (sd->status.skill[skill_id].lv); + + return 0; } /** @@ -6687,57 +6632,52 @@ int pc_statusup2(struct map_session_data* sd, int type, int val) * Update skill_lv for player sd * Skill point allocation *------------------------------------------*/ -void pc_skillup(struct map_session_data *sd,uint16 skill_id) +int pc_skillup(struct map_session_data *sd,uint16 skill_id) { - uint16 idx = skill_get_index(skill_id); + nullpo_ret(sd); - nullpo_retv(sd); - - if (!idx) { - if (skill_id) - ShowError("pc_skillup: Player attempts to level up invalid skill '%d'\n", skill_id); - return; - } - - // Level up guild skill - if (SKILL_CHK_GUILD(skill_id)) { + if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) + { guild_skillup(sd, skill_id); - return; + return 0; } - // Level up homunculus skill - else if (sd->hd && SKILL_CHK_HOMUN(skill_id)) { - hom_skillup(sd->hd, skill_id); - return; - } - else { - if( sd->status.skill_point > 0 && - sd->status.skill[idx].id && - sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] - sd->status.skill[idx].lv < skill_tree_get_max(skill_id, sd->status.class_) ) - { - int lv, range, upgradable; - sd->status.skill[idx].lv++; - sd->status.skill_point--; - if( !skill_get_inf(skill_id) ) - status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills. - else if( sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) - pc_calc_skilltree(sd); // Required to grant all TK Ranker skills. - else - pc_check_skilltree(sd); // Check if a new skill can Lvlup - lv = sd->status.skill[idx].lv; - range = skill_get_range2(&sd->bl, skill_id, lv); - upgradable = (lv < skill_tree_get_max(sd->status.skill[idx].id, sd->status.class_)) ? 1 : 0; - clif_skillup(sd,skill_id,lv,range,upgradable); - clif_updatestatus(sd,SP_SKILLPOINT); - if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */ - clif_updatestatus(sd,SP_CARTINFO); - if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown - clif_skillinfoblock(sd); - } - else - ShowDebug("Skill Level up failed. ID:%d idx:%d (CID=%d. AID=%d)\n", skill_id, idx, sd->status.char_id, sd->status.account_id); + if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd ) + { + hom_skillup(sd->hd, skill_id); + return 0; } + + if(skill_id >= MAX_SKILL ) + return 0; + + if( sd->status.skill_point > 0 && + sd->status.skill[skill_id].id && + sd->status.skill[skill_id].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] + sd->status.skill[skill_id].lv < skill_tree_get_max(skill_id, sd->status.class_) ) + { + int lv,range, upgradable; + sd->status.skill[skill_id].lv++; + sd->status.skill_point--; + if( !skill_get_inf(skill_id) ) + status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills. + else if( sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) + pc_calc_skilltree(sd); // Required to grant all TK Ranker skills. + else + pc_check_skilltree(sd, skill_id); // Check if a new skill can Lvlup + + lv = sd->status.skill[skill_id].lv; + range = skill_get_range2(&sd->bl, skill_id, lv); + upgradable = (lv < skill_tree_get_max(sd->status.skill[skill_id].id, sd->status.class_)) ? 1 : 0; + clif_skillup(sd,skill_id,lv,range,upgradable); + clif_updatestatus(sd,SP_SKILLPOINT); + if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */ + clif_updatestatus(sd,SP_CARTINFO); + if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown + clif_skillinfoblock(sd); + } + + return 0; } /*========================================== @@ -6749,7 +6689,7 @@ int pc_allskillup(struct map_session_data *sd) nullpo_ret(sd); - for (i = 0; i < MAX_SKILL; i++) { + for(i=0;istatus.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; @@ -6758,23 +6698,34 @@ int pc_allskillup(struct map_session_data *sd) } } - if (!pc_grant_allskills(sd, true)) { - uint16 sk_id; - for (i = 0; i < MAX_SKILL_TREE && (sk_id = skill_tree[pc_class2idx(sd->status.class_)][i].id) > 0;i++){ - int inf2 = 0; - uint16 sk_idx = 0; - if (!sk_id || !(sk_idx = skill_get_index(sk_id))) - continue; - inf2 = skill_get_inf2(sk_id); + if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) + { //Get ALL skills except npc/guild ones. [Skotlex] + //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] + for(i=0;istatus.skill[i].lv = skill_get_max(i) ) )//Nonexistant skills should return a max of 0 anyway. + sd->status.skill[i].id = i; + } + } + } else { + int id; + for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){ + int inf2 = skill_get_inf2(id); if ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || - sk_id == SG_DEVIL + id==SG_DEVIL ) continue; //Cannot be learned normally. - sd->status.skill[sk_idx].id = sk_id; - sd->status.skill[sk_idx].lv = skill_tree_get_max(sk_id, sd->status.class_); // celest + sd->status.skill[id].id = id; + sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest } } status_calc_pc(sd,SCO_NONE); @@ -6814,8 +6765,8 @@ int pc_resetlvl(struct map_session_data* sd,int type) if(sd->status.class_ == JOB_NOVICE_HIGH) { sd->status.status_point=100; // not 88 [celest] // give platinum skills upon changing - pc_skill(sd,NV_FIRSTAID,1,ADDSKILL_PERMANENT); - pc_skill(sd,NV_TRICKDEAD,1,ADDSKILL_PERMANENT); + pc_skill(sd,142,1,0); + pc_skill(sd,143,1,0); } } @@ -6989,11 +6940,9 @@ int pc_resetskill(struct map_session_data* sd, int flag) for( i = 1; i < MAX_SKILL; i++ ) { - uint8 lv = sd->status.skill[i].lv; + int lv = sd->status.skill[i].lv; int inf2; - uint16 skill_id = skill_idx2id(i); - if (lv == 0 || skill_id == 0) - continue; + if (lv < 1) continue; inf2 = skill_get_inf2(i); @@ -7001,7 +6950,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) continue; // Don't reset trick dead if not a novice/baby - if( skill_id == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) + if( i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) { sd->status.skill[i].lv = 0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; @@ -7009,13 +6958,13 @@ int pc_resetskill(struct map_session_data* sd, int flag) } // do not reset basic skill - if( skill_id == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) + if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) continue; if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) continue; - if( flag&4 && !skill_ischangesex(skill_id) ) + if( flag&4 && !skill_ischangesex(i) ) continue; if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn ) @@ -8064,26 +8013,26 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper) pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd); } - if(sd->cloneskill_idx > 0) { + if(sd->cloneskill_idx >= 0) { if( sd->status.skill[sd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) { sd->status.skill[sd->cloneskill_idx].id = 0; sd->status.skill[sd->cloneskill_idx].lv = 0; sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT; clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM)); } - sd->cloneskill_idx = 0; + sd->cloneskill_idx = -1; pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM, 0); pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM_LV, 0); } - if(sd->reproduceskill_idx > 0) { + if(sd->reproduceskill_idx >= 0) { if( sd->status.skill[sd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) { sd->status.skill[sd->reproduceskill_idx].id = 0; sd->status.skill[sd->reproduceskill_idx].lv = 0; sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT; clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_REPRODUCE)); } - sd->reproduceskill_idx = 0; + sd->reproduceskill_idx = -1; pc_setglobalreg(sd,SKILL_VAR_REPRODUCE,0); pc_setglobalreg(sd,SKILL_VAR_REPRODUCE_LV,0); } @@ -11334,32 +11283,6 @@ uint64 pc_generate_unique_id(struct map_session_data *sd) { return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++; } -/** - * Validating skill from player after logged on - * @param sd - **/ -void pc_validate_skill(struct map_session_data *sd) { - if (sd) { - uint16 i = 0, count = 0; - struct s_skill tmp_skills[MAX_SKILL] = {{ 0 }}; - - memcpy(tmp_skills, sd->status.skill, sizeof(sd->status.skill)); - memset(sd->status.skill, 0, sizeof(sd->status.skill)); - - for (i = 0; i < MAX_SKILL; i++) { - uint16 idx = 0; - if (tmp_skills[i].id == 0 || tmp_skills[i].lv == 0) - continue; - if ((idx = skill_get_index(tmp_skills[i].id))) { - memcpy(&sd->status.skill[idx], &tmp_skills[i], sizeof(tmp_skills[i])); - count++; - } - else - ShowWarning("pc_validate_skill: Removing invalid skill '%d' from player (AID=%d CID=%d).\n", tmp_skills[i].id, sd->status.account_id, sd->status.char_id); - } - } -} - /*========================================== * pc Init/Terminate *------------------------------------------*/ diff --git a/src/map/pc.h b/src/map/pc.h index 55e00683b7..3032717c78 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -437,7 +437,7 @@ struct map_session_data { short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo] - int8 spiritball, spiritball_old; + short spiritball, spiritball_old; int spirit_timer[MAX_SPIRITBALL]; short talisman[ELE_POISON+1]; // There are actually 5 talisman Fire, Ice, Wind, Earth & Poison maybe because its color violet. int talisman_timer[ELE_POISON+1][10]; @@ -657,8 +657,6 @@ enum weapon_type { W_DOUBLE_SA, // sword + axe }; -#define WEAPON_TYPE_ALL ((1< defaults to 2 +/// +/// addtoskill ,, +/// addtoskill , +/// addtoskill "",, +/// addtoskill "", +/// +/// @see skill +BUILDIN_FUNC(addtoskill) +{ + int id; + int level; + int flag = 2; + TBL_PC* sd; + struct script_data *data; + + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source + + data = script_getdata(st, 2); + get_val(st, data); // Convert into value in case of a variable + id = ( data_isstring(data) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + level = script_getnum(st,3); + if( script_hasdata(st,4) ) + flag = script_getnum(st,4); + pc_skill(sd, id, level, flag); return SCRIPT_CMD_SUCCESS; } @@ -19348,7 +19376,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(autobonus2,"sii??"), BUILDIN_DEF(autobonus3,"siiv?"), BUILDIN_DEF(skill,"vi?"), - BUILDIN_DEF2(skill,"addtoskill","vi?"), // [Valaris] + BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] BUILDIN_DEF(guildskill,"vi"), BUILDIN_DEF(getskilllv,"v"), BUILDIN_DEF(getgdskilllv,"iv"), diff --git a/src/map/skill.c b/src/map/skill.c index fc95ac0df8..fad7c7b6a7 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -53,17 +53,10 @@ #define EL_SKILLRANGEMAX EL_SKILLRANGEMIN + MAX_ELEMENTALSKILL #define GD_SKILLRANGEMIN EL_SKILLRANGEMAX + 1 #define GD_SKILLRANGEMAX GD_SKILLRANGEMIN + MAX_GUILDSKILL + #if GD_SKILLRANGEMAX > 999 #error GD_SKILLRANGEMAX is greater than 999 #endif - - -static DBMap *skilldb_id2idx; /// Skill ID to Index lookup: skill_index = skill_get_index(skill_id) -struct s_skill_db **skill_db; /// Skill DB -static uint16 skill_num; /// Skill count, also as last index -#define skill_next_idx() ( skill_num++ ) /// Macro to get&increase last skill number/index -static uint16 skill_db_create(uint16 skill_id); - static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex] static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex] static DBMap* bowling_db = NULL; // int mob_id -> struct mob_data* @@ -78,6 +71,8 @@ struct skill_usave { uint16 skill_id, skill_lv; }; +struct s_skill_db skill_db[MAX_SKILL_DB]; + struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; static unsigned short skill_produce_count; @@ -142,15 +137,7 @@ static inline int splash_target(struct block_list* bl) { #endif } -uint16 SKILL_MAX_DB(void) { - return skill_num; -} - -/** - * Get skill id from name - * @param name - * @return Skill ID of the skill, or 0 if not found. - **/ +/// Returns the id of the skill, or 0 if not found. int skill_name2id(const char* name) { if( name == NULL ) return 0; @@ -158,60 +145,39 @@ int skill_name2id(const char* name) { return strdb_iget(skilldb_name2id, name); } -/** - * Get Skill ID from Skill Index - * @param idx - * @return Skill ID or 0 if not found - **/ -uint16 skill_idx2id(uint16 idx) { - if (idx < SKILL_MAX_DB() && skill_db[idx]) - return skill_db[idx]->nameid; - return 0; +/// Maps skill ids to skill db offsets. +/// Returns the skill's array index, or 0 (Unknown Skill). +int skill_get_index( uint16 skill_id ) { + // avoid ranges reserved for mapping guild/homun/mercenary skills + if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX) + || (skill_id >= HM_SKILLRANGEMIN && skill_id <= HM_SKILLRANGEMAX) + || (skill_id >= MC_SKILLRANGEMIN && skill_id <= MC_SKILLRANGEMAX) + || (skill_id >= EL_SKILLRANGEMIN && skill_id <= EL_SKILLRANGEMAX) ) + return 0; + + // map skill id to skill db index + if( skill_id >= GD_SKILLBASE ) + skill_id = GD_SKILLRANGEMIN + skill_id - GD_SKILLBASE; + else if( skill_id >= EL_SKILLBASE ) + skill_id = EL_SKILLRANGEMIN + skill_id - EL_SKILLBASE; + else if( skill_id >= MC_SKILLBASE ) + skill_id = MC_SKILLRANGEMIN + skill_id - MC_SKILLBASE; + else if( skill_id >= HM_SKILLBASE ) + skill_id = HM_SKILLRANGEMIN + skill_id - HM_SKILLBASE; + + // validate result + if( !skill_id || skill_id >= MAX_SKILL_DB ) + return 0; + + return skill_id; } -/** - * Get skill index from skill_db array. The index is also being used for skill lookup in mmo_charstatus::skill[] - * @param skill_id - * @param silent If Skill is undefined, show error message! - * @return Skill Index or 0 if not found/unset - **/ -int skill_get_index_( uint16 skill_id, bool silent ) { - uint16 idx = (uint16)uidb_iget(skilldb_id2idx, skill_id); - if (!idx && skill_id != 0 && !silent) - ShowError("Skill '%d' is undefined!\n", skill_id); - return idx; -} - -/** - * Check if skill is set yet. If not, create new one (for skill_db files reading purpose) - * @param skill_id - * @return Skill index - **/ -static uint16 skill_db_isset(uint16 skill_id, const char *func) { - uint16 idx = skill_get_index2(skill_id); - if (idx || idx == skill_id) - return idx; - ShowWarning("%s: Skill '%d' isn't created in 'skill_db.txt' yet. Creating dummy value...\n", func, skill_id); - idx = skill_db_create(skill_id); - return idx; -} - -/** - * Get Skill name - * @param skill_id - * @return AEGIS Skill name - **/ const char* skill_get_name( uint16 skill_id ) { - return skill_db[skill_get_index(skill_id)]->name; + return skill_db[skill_get_index(skill_id)].name; } -/** - * Get Skill name - * @param skill_id - * @return English Skill name - **/ const char* skill_get_desc( uint16 skill_id ) { - return skill_db[skill_get_index(skill_id)]->desc; + return skill_db[skill_get_index(skill_id)].desc; } /// out of bounds error checking [celest] @@ -220,87 +186,70 @@ static void skill_chk(uint16 *skill_id) { } // checks/adjusts level static void skill_chk2(uint16 *skill_lv) { - *skill_lv = cap_value(*skill_lv, 1, MAX_SKILL_LEVEL); + *skill_lv = (*skill_lv < 1) ? 1 : (*skill_lv > MAX_SKILL_LEVEL) ? MAX_SKILL_LEVEL : *skill_lv; } // checks/adjusts index. make sure we don't use negative index static void skill_chk3(int *idx) { if (*idx < 0) *idx = 0; } -#define skill_get(id,var) { skill_chk(&id); if (!id) return 0; return var; } -#define skill_get2(id, lv, arrvar) do {\ - int idx;\ - skill_chk(&(id));\ - if (!(id))\ - return 0;\ - idx = min((lv), MAX_SKILL_LEVEL) - 1;\ - if ((lv) > MAX_SKILL_LEVEL && (arrvar)[idx] > 1) {\ - int lv__ = (lv);\ - (lv) = skill_db[(id)]->max-1;\ - return ((arrvar)[(lv)] + ((lv__-(lv))/2));\ - }\ - return ((arrvar)[idx]);\ -} while(0) -#define skill_get3(id,x,var) { skill_chk(&id); if (!id) return 0; skill_chk3(&x); return var; } +#define skill_get(var,id) { skill_chk(&id); if(!id) return 0; return var; } +#define skill_get2(var,id,lv) { skill_chk(&id); if (!id) return 0; skill_chk2(&lv); return var; } +#define skill_get3(var,id,x) { skill_chk(&id); if (!id) return 0; skill_chk3(&x); return var; } // Skill DB -int skill_get_hit( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->hit); } -int skill_get_inf( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->inf); } -int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->element); } -int skill_get_nk( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->nk); } -int skill_get_max( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->max); } -int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->range); } -int skill_get_splash_( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->splash); } -int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->num); } -int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->cast); } -int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->delay); } -int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->walkdelay); } -int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->upkeep_time); } -int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->upkeep_time2); } -int skill_get_castdef( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->cast_def_rate); } -int skill_get_inf2( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->inf2); } -int skill_get_inf3( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->inf3); } -int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->castcancel); } -int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->maxcount); } -int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->blewcount); } -int skill_get_castnodex( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->castnodex); } -int skill_get_delaynodex( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->delaynodex); } -int skill_get_nocast ( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->nocast); } -int skill_get_type( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->skill_type); } -int skill_get_unit_id ( uint16 skill_id, int flag ) { skill_get (skill_id, skill_db[skill_id]->unit_id[flag]); } -int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->unit_interval); } -int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->unit_range); } -int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->unit_target&BCT_ALL); } -int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->unit_target&BL_ALL); } -int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->unit_flag); } -int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->unit_layout_type); } -int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->cooldown); } +int skill_get_hit( uint16 skill_id ) { skill_get (skill_db[skill_id].hit, skill_id); } +int skill_get_inf( uint16 skill_id ) { skill_get (skill_db[skill_id].inf, skill_id); } +int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].element[skill_lv-1], skill_id, skill_lv); } +int skill_get_nk( uint16 skill_id ) { skill_get (skill_db[skill_id].nk, skill_id); } +int skill_get_max( uint16 skill_id ) { skill_get (skill_db[skill_id].max, skill_id); } +int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].range[skill_lv-1], skill_id, skill_lv); } +int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill_db[skill_id].splash[skill_lv-1]>=0?skill_db[skill_id].splash[skill_lv-1]:AREA_SIZE), skill_id, skill_lv); } +int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].num[skill_lv-1], skill_id, skill_lv); } +int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cast[skill_lv-1], skill_id, skill_lv); } +int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].delay[skill_lv-1], skill_id, skill_lv); } +int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].walkdelay[skill_lv-1], skill_id, skill_lv); } +int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time[skill_lv-1], skill_id, skill_lv); } +int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time2[skill_lv-1], skill_id, skill_lv); } +int skill_get_castdef( uint16 skill_id ) { skill_get (skill_db[skill_id].cast_def_rate, skill_id); } +int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id); } +int skill_get_inf3( uint16 skill_id ) { skill_get (skill_db[skill_id].inf3, skill_id); } +int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id); } +int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].maxcount[skill_lv-1], skill_id, skill_lv); } +int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].blewcount[skill_lv-1], skill_id, skill_lv); } +int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].castnodex[skill_lv-1], skill_id, skill_lv); } +int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].delaynodex[skill_lv-1], skill_id, skill_lv); } +int skill_get_nocast ( uint16 skill_id ) { skill_get (skill_db[skill_id].nocast, skill_id); } +int skill_get_type( uint16 skill_id ) { skill_get (skill_db[skill_id].skill_type, skill_id); } +int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get3 (skill_db[skill_id].unit_id[flag], skill_id, flag); } +int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_interval, skill_id); } +int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ){ skill_get2 (skill_db[skill_id].unit_range[skill_lv-1], skill_id, skill_lv); } +int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BCT_ALL, skill_id); } +int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BL_ALL, skill_id); } +int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_flag, skill_id); } +int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].unit_layout_type[skill_lv-1], skill_id, skill_lv); } +int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cooldown[skill_lv-1], skill_id, skill_lv); } #ifdef RENEWAL_CAST -int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->fixed_cast); } +int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].fixed_cast[skill_lv-1], skill_id, skill_lv); } #endif // Skill requirements -int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.hp); } -int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.mhp); } -int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.sp); } -int skill_get_hp_rate( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.hp_rate); } -int skill_get_sp_rate( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.sp_rate); } -int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.zeny); } -int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->require.weapon); } -int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->require.ammo); } -int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.ammo_qty); } -int skill_get_state( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->require.state); } -int skill_get_status_count( uint16 skill_id ) { skill_get (skill_id, skill_db[skill_id]->require.status_count); } -int skill_get_spiritball( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_id, skill_lv, skill_db[skill_id]->require.spiritball); } -int skill_get_itemid( uint16 skill_id, int idx ) { skill_get3 (skill_id, idx, skill_db[skill_id]->require.itemid[idx]); } -int skill_get_itemqty( uint16 skill_id, int idx ) { skill_get3 (skill_id, idx, skill_db[skill_id]->require.amount[idx]); } -int skill_get_itemeq( uint16 skill_id, int idx ) { skill_get3 (skill_id, idx, skill_db[skill_id]->require.eqItem[idx]); } +int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.hp[skill_lv-1], skill_id, skill_lv); } +int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.mhp[skill_lv-1], skill_id, skill_lv); } +int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.sp[skill_lv-1], skill_id, skill_lv); } +int skill_get_hp_rate( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.hp_rate[skill_lv-1], skill_id, skill_lv); } +int skill_get_sp_rate( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.sp_rate[skill_lv-1], skill_id, skill_lv); } +int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.zeny[skill_lv-1], skill_id, skill_lv); } +int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_id].require.weapon, skill_id); } +int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].require.ammo, skill_id); } +int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].require.ammo_qty[skill_lv-1], skill_id, skill_lv); } +int skill_get_state( uint16 skill_id ) { skill_get (skill_db[skill_id].require.state, skill_id); } +//int skill_get_status( uint16 skill_id, int idx ) { skill_get3 (skill_db[skill_id].require.status[idx], skill_id, idx); } +int skill_get_status_count( uint16 skill_id ) { skill_get (skill_db[skill_id].require.status_count, skill_id); } +int skill_get_spiritball( uint16 skill_id, uint16 skill_lv ){ skill_get2 (skill_db[skill_id].require.spiritball[skill_lv-1], skill_id, skill_lv); } +int skill_get_itemid( uint16 skill_id, int idx ) { skill_get3 (skill_db[skill_id].require.itemid[idx], skill_id, idx); } +int skill_get_itemqty( uint16 skill_id, int idx ) { skill_get3 (skill_db[skill_id].require.amount[idx], skill_id, idx); } +int skill_get_itemeq( uint16 skill_id, int idx ) { skill_get3 (skill_db[skill_id].require.eqItem[idx], skill_id, idx); } -int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { - int splash = skill_get_splash_(skill_id, skill_lv); - if (splash < 0) - return AREA_SIZE; - return splash; -} int skill_tree_get_max(uint16 skill_id, int b_class) { @@ -506,14 +455,16 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk * @return 0 - Cannot be copied; 1 - Can be copied by Plagiarism 2 - Can be copied by Reproduce * @author Aru - for previous check; Jobbie for class restriction idea; Cydh expands the copyable skill */ -static int8 skill_isCopyable(struct map_session_data *sd, uint16 skill_idx) { +static char skill_isCopyable(struct map_session_data *sd, uint16 skill_id) { + uint16 idx = skill_get_index(skill_id); + // Only copy skill that player doesn't have or the skill is old clone - if (sd->status.skill[skill_idx].id != 0 && sd->status.skill[skill_idx].flag != SKILL_FLAG_PLAGIARIZED) + if (sd->status.skill[idx].id != 0 && sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED) return 0; // Check if the skill is copyable by class if (!pc_has_permission(sd,PC_PERM_ALL_SKILL)) { - uint16 job_allowed = skill_db[skill_idx]->copyable.joballowed; + uint16 job_allowed = skill_db[idx].copyable.joballowed; while (1) { if (job_allowed&0x01 && sd->status.class_ == JOB_ROGUE) break; if (job_allowed&0x02 && sd->status.class_ == JOB_STALKER) break; @@ -526,11 +477,11 @@ static int8 skill_isCopyable(struct map_session_data *sd, uint16 skill_idx) { } //Plagiarism only able to copy skill while SC_PRESERVE is not active and skill is copyable by Plagiarism - if (skill_db[skill_idx]->copyable.option&1 && pc_checkskill(sd,RG_PLAGIARISM) && !sd->sc.data[SC_PRESERVE]) + if (skill_db[idx].copyable.option&1 && pc_checkskill(sd,RG_PLAGIARISM) && !sd->sc.data[SC_PRESERVE]) return 1; //Reproduce can copy skill if SC__REPRODUCE is active and the skill is copyable by Reproduce - if (skill_db[skill_idx]->copyable.option&2 && pc_checkskill(sd,SC_REPRODUCE) && &sd->sc && sd->sc.data[SC__REPRODUCE] && sd->sc.data[SC__REPRODUCE]->val1) + if (skill_db[idx].copyable.option&2 && pc_checkskill(sd,SC_REPRODUCE) && &sd->sc && sd->sc.data[SC__REPRODUCE] && sd->sc.data[SC__REPRODUCE]->val1) return 2; return 0; @@ -2549,38 +2500,35 @@ bool skill_is_combo(uint16 skill_id) { void skill_combo_toogle_inf(struct block_list* bl, uint16 skill_id, int inf){ TBL_PC *sd = BL_CAST(BL_PC, bl); switch (skill_id) { - case MH_MIDNIGHT_FRENZY: - case MH_EQC: - { - int skill_id2 = ((skill_id==MH_EQC)?MH_TINDER_BREAKER:MH_SONIC_CRAW); - short idx = hom_skill_get_index(skill_id2); - int flag = (inf?SKILL_FLAG_TMP_COMBO:SKILL_FLAG_PERMANENT); - TBL_HOM *hd = BL_CAST(BL_HOM, bl); - if (idx == -1) - break; - sd = hd->master; - hd->homunculus.hskill[idx].flag= flag; - if(sd) clif_homskillinfoblock(sd); //refresh info //@FIXME we only want to refresh one skill - } - break; - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sd) clif_skillinfo(sd,MO_EXTREMITYFIST, inf); - break; - case TK_JUMPKICK: - if (sd) clif_skillinfo(sd,TK_JUMPKICK, inf); - break; - case MO_TRIPLEATTACK: - if (sd && pc_checkskill(sd, SR_DRAGONCOMBO) > 0) - clif_skillinfo(sd,SR_DRAGONCOMBO, inf); - break; - case SR_FALLENEMPIRE: - if (sd){ - clif_skillinfo(sd,SR_GATEOFHELL, inf); - clif_skillinfo(sd,SR_TIGERCANNON, inf); - } - break; + case MH_MIDNIGHT_FRENZY: + case MH_EQC:{ + int skill_id2 = ((skill_id==MH_EQC)?MH_TINDER_BREAKER:MH_SONIC_CRAW); + int idx = skill_id2 - HM_SKILLBASE; + int flag = (inf?SKILL_FLAG_TMP_COMBO:SKILL_FLAG_PERMANENT); + TBL_HOM *hd = BL_CAST(BL_HOM, bl); + sd = hd->master; + hd->homunculus.hskill[idx].flag= flag; + if(sd) clif_homskillinfoblock(sd); //refresh info //@FIXME we only want to refresh one skill + } + break; + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if (sd) clif_skillinfo(sd,MO_EXTREMITYFIST, inf); + break; + case TK_JUMPKICK: + if (sd) clif_skillinfo(sd,TK_JUMPKICK, inf); + break; + case MO_TRIPLEATTACK: + if (sd && pc_checkskill(sd, SR_DRAGONCOMBO) > 0) + clif_skillinfo(sd,SR_DRAGONCOMBO, inf); + break; + case SR_FALLENEMPIRE: + if (sd){ + clif_skillinfo(sd,SR_GATEOFHELL, inf); + clif_skillinfo(sd,SR_TIGERCANNON, inf); + } + break; } } @@ -2738,10 +2686,10 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s if (!(idx = skill_get_index(skill_id))) return; - switch (skill_isCopyable(tsd,idx)) { + switch (skill_isCopyable(tsd,skill_id)) { case 1: //Copied by Plagiarism { - if (tsd->cloneskill_idx > 0 && tsd->status.skill[tsd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED) { + if (tsd->cloneskill_idx >= 0 && tsd->status.skill[tsd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED) { tsd->status.skill[tsd->cloneskill_idx].id = 0; tsd->status.skill[tsd->cloneskill_idx].lv = 0; tsd->status.skill[tsd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT; @@ -2761,7 +2709,7 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s //Already did SC check //Skill level copied depends on Reproduce skill that used lv = (tsc) ? tsc->data[SC__REPRODUCE]->val1 : 1; - if( tsd->reproduceskill_idx > 0 && tsd->status.skill[tsd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) { + if( tsd->reproduceskill_idx >= 0 && tsd->status.skill[tsd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) { tsd->status.skill[tsd->reproduceskill_idx].id = 0; tsd->status.skill[tsd->reproduceskill_idx].lv = 0; tsd->status.skill[tsd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT; @@ -3235,7 +3183,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * map_freeblock_lock(); - if (bl->type == BL_PC && skill_id && skill_get_index(skill_id) > 0 && skill_db[skill_get_index(skill_id)]->copyable.option && //Only copy skill that copyable [Cydh] + if (bl->type == BL_PC && skill_id && skill_get_index(skill_id) > 0 && skill_db[skill_get_index(skill_id)].copyable.option && //Only copy skill that copyable [Cydh] dmg.flag&BF_SKILL && dmg.damage+dmg.damage2 > 0 && damage < status_get_hp(bl)) //Cannot copy skills if the blow will kill you. [Skotlex] skill_do_copy(src,bl,skill_id,skill_lv); @@ -3547,8 +3495,8 @@ static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 } //Check the additional range [Cydh] - if (isNearNPC && skill_db[skill_get_index(skill_id)]->unit_nonearnpc_range) - range += skill_db[skill_get_index(skill_id)]->unit_nonearnpc_range; + if (isNearNPC && skill_db[skill_get_index(skill_id)].unit_nonearnpc_range) + range += skill_db[skill_get_index(skill_id)].unit_nonearnpc_range; if (!isNearNPC) { //Doesn't check the NPC range //If the caster is a monster/NPC, only check for players. Otherwise just check characters @@ -3580,6 +3528,8 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int uint16 idx; int itemid[MAX_SKILL_ITEM_REQUIRE],amount[ARRAYLENGTH(itemid)],index[ARRAYLENGTH(itemid)]; + if( lv < 1 || lv > MAX_SKILL_LEVEL ) + return 0; nullpo_ret(bl); switch( bl->type ) @@ -3592,20 +3542,18 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int if( (idx = skill_get_index(skill)) == 0 ) return 0; - lv = cap_value(lv, 1, MAX_SKILL_LEVEL); - // Requirements for( i = 0; i < ARRAYLENGTH(itemid); i++ ) { - itemid[i] = skill_db[idx]->require.itemid[i]; - amount[i] = skill_db[idx]->require.amount[i]; + itemid[i] = skill_db[idx].require.itemid[i]; + amount[i] = skill_db[idx].require.amount[i]; } - hp = skill_db[idx]->require.hp[lv-1]; - sp = skill_db[idx]->require.sp[lv-1]; - hp_rate = skill_db[idx]->require.hp_rate[lv-1]; - sp_rate = skill_db[idx]->require.sp_rate[lv-1]; - state = skill_db[idx]->require.state; - if( (mhp = skill_db[idx]->require.mhp[lv-1]) > 0 ) + hp = skill_db[idx].require.hp[lv-1]; + sp = skill_db[idx].require.sp[lv-1]; + hp_rate = skill_db[idx].require.hp_rate[lv-1]; + sp_rate = skill_db[idx].require.sp_rate[lv-1]; + state = skill_db[idx].require.state; + if( (mhp = skill_db[idx].require.mhp[lv-1]) > 0 ) hp += (status->max_hp * mhp) / 100; if( hp_rate > 0 ) hp += (status->hp * hp_rate) / 100; @@ -6801,7 +6749,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) char temp[70]; - snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_get_index(skill_id)]->desc); + snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_get_index(skill_id)].desc); clif_disp_overhead(&md->bl,temp); } break; @@ -14150,9 +14098,8 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i return false; } } - - //if (skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL) - // return false; + if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) + return false; require = skill_get_requirement(sd,skill_id,skill_lv); @@ -15226,23 +15173,23 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 idx = skill_get_index(skill_id); if( idx == 0 ) // invalid skill id + return req; + if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) return req; - skill_lv = cap_value(skill_lv, 1, MAX_SKILL_LEVEL); - status = &sd->battle_status; - req.hp = skill_db[idx]->require.hp[skill_lv-1]; - hp_rate = skill_db[idx]->require.hp_rate[skill_lv-1]; + req.hp = skill_db[idx].require.hp[skill_lv-1]; + hp_rate = skill_db[idx].require.hp_rate[skill_lv-1]; if(hp_rate > 0) req.hp += (status->hp * hp_rate)/100; else req.hp += (status->max_hp * (-hp_rate))/100; - req.sp = skill_db[idx]->require.sp[skill_lv-1]; + req.sp = skill_db[idx].require.sp[skill_lv-1]; if((sd->skill_id_old == BD_ENCORE) && skill_id == sd->skill_id_dance) req.sp /= 2; - sp_rate = skill_db[idx]->require.sp_rate[skill_lv-1]; + sp_rate = skill_db[idx].require.sp_rate[skill_lv-1]; if(sp_rate > 0) req.sp += (status->sp * sp_rate)/100; else @@ -15272,7 +15219,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 req.sp -= req.sp * sc->data[SC_TELEKINESIS_INTENSE]->val2 / 100; } - req.zeny = skill_db[idx]->require.zeny[skill_lv-1]; + req.zeny = skill_db[idx].require.zeny[skill_lv-1]; if( sc && sc->data[SC__UNLUCKY] ) { if(sc->data[SC__UNLUCKY]->val1 < 3) @@ -15281,33 +15228,33 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 req.zeny += 1000; } - req.spiritball = skill_db[idx]->require.spiritball[skill_lv-1]; - req.state = skill_db[idx]->require.state; + req.spiritball = skill_db[idx].require.spiritball[skill_lv-1]; + req.state = skill_db[idx].require.state; - req.mhp = skill_db[idx]->require.mhp[skill_lv-1]; - req.weapon = skill_db[idx]->require.weapon; - req.ammo_qty = skill_db[idx]->require.ammo_qty[skill_lv-1]; + req.mhp = skill_db[idx].require.mhp[skill_lv-1]; + req.weapon = skill_db[idx].require.weapon; + req.ammo_qty = skill_db[idx].require.ammo_qty[skill_lv-1]; if (req.ammo_qty) - req.ammo = skill_db[idx]->require.ammo; + req.ammo = skill_db[idx].require.ammo; if (!req.ammo && skill_id && skill_isammotype(sd, skill_id)) { //Assume this skill is using the weapon, therefore it requires arrows. - req.ammo = AMMO_TYPE_ALL; //Enable use on all ammo types. + req.ammo = 0xFFFFFFFF; //Enable use on all ammo types. req.ammo_qty = 1; } - req.status_count = skill_db[idx]->require.status_count; - req.status = skill_db[idx]->require.status; - req.eqItem_count = skill_db[idx]->require.eqItem_count; - req.eqItem = skill_db[idx]->require.eqItem; + req.status_count = skill_db[idx].require.status_count; + req.status = skill_db[idx].require.status; + req.eqItem_count = skill_db[idx].require.eqItem_count; + req.eqItem = skill_db[idx].require.eqItem; switch( skill_id ) { /* Skill level-dependent checks */ case NC_SHAPESHIFT: case NC_REPAIR: //NOTE: Please make sure Magic_Gear_Fuel in the last position in skill_require_db.txt - req.itemid[1] = skill_db[idx]->require.itemid[MAX_SKILL_ITEM_REQUIRE-1]; - req.amount[1] = skill_db[idx]->require.amount[MAX_SKILL_ITEM_REQUIRE-1]; + req.itemid[1] = skill_db[idx].require.itemid[MAX_SKILL_ITEM_REQUIRE-1]; + req.amount[1] = skill_db[idx].require.amount[MAX_SKILL_ITEM_REQUIRE-1]; case GN_FIRE_EXPANSION: case SO_SUMMON_AGNI: case SO_SUMMON_AQUA: @@ -15318,8 +15265,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 case SO_WIND_INSIGNIA: case SO_EARTH_INSIGNIA: case WZ_FIREPILLAR: // no gems required at level 1-5 [celest] - req.itemid[0] = skill_db[idx]->require.itemid[min(skill_lv-1,MAX_SKILL_ITEM_REQUIRE-1)]; - req.amount[0] = skill_db[idx]->require.amount[min(skill_lv-1,MAX_SKILL_ITEM_REQUIRE-1)]; + req.itemid[0] = skill_db[idx].require.itemid[min(skill_lv-1,MAX_SKILL_ITEM_REQUIRE-1)]; + req.amount[0] = skill_db[idx].require.amount[min(skill_lv-1,MAX_SKILL_ITEM_REQUIRE-1)]; level_dependent = true; /* Normal skill requirements and gemstone checks */ @@ -15339,17 +15286,17 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 continue; break; case AB_ADORAMUS: - if( itemid_isgemstone(skill_db[idx]->require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2)) ) + if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2)) ) continue; break; case WL_COMET: - if( itemid_isgemstone(skill_db[idx]->require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0)) ) + if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0)) ) continue; break; } - req.itemid[i] = skill_db[idx]->require.itemid[i]; - req.amount[i] = skill_db[idx]->require.amount[i]; + req.itemid[i] = skill_db[idx].require.itemid[i]; + req.amount[i] = skill_db[idx].require.amount[i]; if( skill_id >= HT_SKIDTRAP && skill_id <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0){ int16 itIndex; @@ -15471,7 +15418,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 //Check if player is using the copied skill [Cydh] if (sd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED) { - uint16 req_opt = skill_db[idx]->copyable.req_opt; + uint16 req_opt = skill_db[idx].copyable.req_opt; if (req_opt&0x0001) req.hp = 0; if (req_opt&0x0002) req.mhp = 0; @@ -15505,7 +15452,7 @@ int skill_castfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv) { sd = BL_CAST(BL_PC, bl); // calculate base cast time (reduced by dex) - if( !(skill_get_castnodex(skill_id)&1) ) { + if( !(skill_get_castnodex(skill_id, skill_lv)&1) ) { int scale = battle_config.castrate_dex_scale - status_get_dex(bl); if( scale > 0 ) // not instant cast time = time * scale / battle_config.castrate_dex_scale; @@ -15514,7 +15461,7 @@ int skill_castfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv) { } // calculate cast time reduced by item/card bonuses - if( !(skill_get_castnodex(skill_id)&4) && sd ) + if( !(skill_get_castnodex(skill_id, skill_lv)&4) && sd ) { int i; if( sd->castrate != 100 ) @@ -15601,7 +15548,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 struct map_session_data *sd = BL_CAST(BL_PC,bl); int fixed = skill_get_fixed_cast(skill_id, skill_lv); short fixcast_r = 0; - uint8 i = 0, flag = skill_get_castnodex(skill_id); + uint8 i = 0, flag = skill_get_castnodex(skill_id, skill_lv); #define FIXEDCASTRATE2(val) ( FIXEDCASTRATE(fixcast_r,(val)) ) @@ -15731,7 +15678,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 *------------------------------------------*/ int skill_delayfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { - int delaynodex = skill_get_delaynodex(skill_id); + int delaynodex = skill_get_delaynodex(skill_id, skill_lv); int time = skill_get_delay(skill_id, skill_lv); struct map_session_data *sd; struct status_change *sc = status_get_sc(bl); @@ -17136,7 +17083,7 @@ struct skill_unit_group* skill_id2group(int group_id) { return (struct skill_unit_group*)idb_get(skillunit_group_db, group_id); } -static int skill_unit_group_newid = MAX_SKILL; /// Skill Unit Group ID +static int skill_unit_group_newid = MAX_SKILL_DB; /// Skill Unit Group ID /** * Returns a new group_id that isn't being used in skillunit_group_db. @@ -17144,14 +17091,14 @@ static int skill_unit_group_newid = MAX_SKILL; /// Skill Unit Group ID */ static int skill_get_new_group_id(void) { - if( skill_unit_group_newid >= MAX_SKILL && skill_id2group(skill_unit_group_newid) == NULL ) + if( skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL ) return skill_unit_group_newid++;// available {// find next id int base_id = skill_unit_group_newid; while( base_id != ++skill_unit_group_newid ) { - if( skill_unit_group_newid < MAX_SKILL ) - skill_unit_group_newid = MAX_SKILL; + if( skill_unit_group_newid < MAX_SKILL_DB ) + skill_unit_group_newid = MAX_SKILL_DB; if( skill_id2group(skill_unit_group_newid) == NULL ) return skill_unit_group_newid++;// available } @@ -18892,8 +18839,7 @@ void skill_spellbook (struct map_session_data *sd, unsigned short nameid) { } int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { - int lv, prob, aslvl = 0; - uint16 sk_idx = 0; + int id, lv, prob, aslvl = 0; nullpo_ret(sd); if (sd->sc.data[SC_STOP]) { @@ -18901,18 +18847,15 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); } - if (!skill_id || (sk_idx = skill_get_index(skill_id))) - return 0; - - if( !(skill_get_inf2(skill_id)&INF2_AUTOSHADOWSPELL) || sd->status.skill[sk_idx].id == 0 || sd->status.skill[sk_idx].flag != SKILL_FLAG_PLAGIARIZED ) { - clif_skill_fail(sd,SC_AUTOSHADOWSPELL,USESKILL_FAIL_LEVEL,0); + if( !(skill_get_inf2(sd->status.skill[skill_id].id)&INF2_AUTOSHADOWSPELL) || (id = sd->status.skill[skill_id].id) == 0 || sd->status.skill[skill_id].flag != SKILL_FLAG_PLAGIARIZED ) { + clif_skill_fail(sd,SC_AUTOSHADOWSPELL,0,0); return 0; } lv = (aslvl + 1) / 2; // The level the skill will be autocasted - lv = min(lv,sd->status.skill[sk_idx].lv); + lv = min(lv,sd->status.skill[skill_id].lv); prob = (aslvl >= 10) ? 15 : (30 - 2 * aslvl); // Probability at level 10 was increased to 15. - sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,skill_id,lv,prob,0,skill_get_time(SC_AUTOSHADOWSPELL,aslvl)); + sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill_get_time(SC_AUTOSHADOWSPELL,aslvl)); return 0; } @@ -19158,7 +19101,7 @@ int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[o { struct homun_data *hd = (TBL_HOM*) map_id2bl(id); - if (data <= 0 || data >= SKILL_MAX_DB()) + if (data <= 0 || data >= MAX_SKILL) return 0; if (hd) @@ -19190,7 +19133,7 @@ int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[or { struct mercenary_data *md = (TBL_MER*)map_id2bl(id); - if( data <= 0 || data >= SKILL_MAX_DB() ) + if( data <= 0 || data >= MAX_SKILL ) return 0; if( md ) @@ -19331,22 +19274,25 @@ void skill_init_unit_layout (void) { // afterwards add special ones pos = i; - for (i = 0; i < SKILL_MAX_DB(); i++) { - uint16 skill_id = 0; - if (!skill_db[i]) + for (i=0;iunit_id[0] || skill_db[i]->unit_layout_type[0] != -1) - continue; - skill_id = skill_idx2id(i); + if( i >= HM_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) { + int skill = i; - if( skill_id == EL_FIRE_MANTLE ) { - static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1}; - static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0}; - skill_unit_layout[pos].count = 8; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + if( i >= EL_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) { + skill -= EL_SKILLRANGEMIN; + skill += EL_SKILLBASE; + } + if( skill == EL_FIRE_MANTLE ) { + static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1}; + static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0}; + skill_unit_layout[pos].count = 8; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } } else { - switch (skill_id) { + switch (i) { case MG_FIREWALL: case WZ_ICEWALL: case WL_EARTHSTRAIN: @@ -19452,26 +19398,26 @@ void skill_init_unit_layout (void) { skill_unit_layout[pos].count = 4; memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1)); memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1)); - skill_db[i]->unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[j] = pos; //lv2/3 j++; pos++; skill_unit_layout[pos].count = 8; memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2)); memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2)); - skill_db[i]->unit_layout_type[j] = pos; - skill_db[i]->unit_layout_type[++j] = pos; + skill_db[i].unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[++j] = pos; //lv4/5 j++; pos++; skill_unit_layout[pos].count = 12; memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3)); memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3)); - skill_db[i]->unit_layout_type[j] = pos; - skill_db[i]->unit_layout_type[++j] = pos; + skill_db[i].unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[++j] = pos; //Fill in the rest using lv 5. for (;junit_layout_type[j] = pos; + skill_db[i].unit_layout_type[j] = pos; //Skip, this way the check below will fail and continue to the next skill. pos++; } @@ -19492,7 +19438,7 @@ void skill_init_unit_layout (void) { if (!skill_unit_layout[pos].count) continue; for (j=0;junit_layout_type[j] = pos; + skill_db[i].unit_layout_type[j] = pos; pos++; } @@ -19884,46 +19830,49 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) { static bool skill_parse_row_skilldb(char* split[], int columns, int current) {// id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index2(skill_id); - - if (!idx) { - if (SKILL_MAX_DB() >= MAX_SKILL) { - ShowError("Cannot add new skill. Limit is reached '%d' (mmo.h::MAX_SKILL).\n", MAX_SKILL); - return false; - } - idx = skill_db_create(skill_id); + uint16 idx; + if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX) + || (skill_id >= HM_SKILLRANGEMIN && skill_id <= HM_SKILLRANGEMAX) + || (skill_id >= MC_SKILLRANGEMIN && skill_id <= MC_SKILLRANGEMAX) + || (skill_id >= EL_SKILLRANGEMIN && skill_id <= EL_SKILLRANGEMAX) ) { + ShowWarning("skill_parse_row_skilldb: Skill id %d is forbidden (interferes with guild/homun/mercenary skill mapping)!\n", skill_id); + return false; } - skill_split_atoi(split[1],skill_db[idx]->range); - skill_db[idx]->hit = atoi(split[2]); - skill_db[idx]->inf = atoi(split[3]); - skill_split_atoi(split[4],skill_db[idx]->element); - skill_db[idx]->nk = (uint8)strtol(split[5], NULL, 0); - skill_split_atoi(split[6],skill_db[idx]->splash); - skill_db[idx]->max = atoi(split[7]); - skill_split_atoi(split[8],skill_db[idx]->num); + idx = skill_get_index(skill_id); + if( !idx ) // invalid skill id + return false; + + skill_split_atoi(split[1],skill_db[idx].range); + skill_db[idx].hit = atoi(split[2]); + skill_db[idx].inf = atoi(split[3]); + skill_split_atoi(split[4],skill_db[idx].element); + skill_db[idx].nk = (int)strtol(split[5], NULL, 0); + skill_split_atoi(split[6],skill_db[idx].splash); + skill_db[idx].max = atoi(split[7]); + skill_split_atoi(split[8],skill_db[idx].num); if( strcmpi(split[9],"yes") == 0 ) - skill_db[idx]->castcancel = true; + skill_db[idx].castcancel = 1; else - skill_db[idx]->castcancel = false; - skill_db[idx]->cast_def_rate = atoi(split[10]); - skill_db[idx]->inf2 = (unsigned int)strtol(split[11], NULL, 0); - skill_split_atoi(split[12],skill_db[idx]->maxcount); + skill_db[idx].castcancel = 0; + skill_db[idx].cast_def_rate = atoi(split[10]); + skill_db[idx].inf2 = (int)strtol(split[11], NULL, 0); + skill_split_atoi(split[12],skill_db[idx].maxcount); if( strcmpi(split[13],"weapon") == 0 ) - skill_db[idx]->skill_type = BF_WEAPON; + skill_db[idx].skill_type = BF_WEAPON; else if( strcmpi(split[13],"magic") == 0 ) - skill_db[idx]->skill_type = BF_MAGIC; + skill_db[idx].skill_type = BF_MAGIC; else if( strcmpi(split[13],"misc") == 0 ) - skill_db[idx]->skill_type = BF_MISC; + skill_db[idx].skill_type = BF_MISC; else - skill_db[idx]->skill_type = 0; - skill_split_atoi(split[14],skill_db[idx]->blewcount); - skill_db[idx]->inf3 = (unsigned int)strtol(split[15], NULL,0); - safestrncpy(skill_db[idx]->name, trim(split[16]), sizeof(skill_db[idx]->name)); - safestrncpy(skill_db[idx]->desc, trim(split[17]), sizeof(skill_db[idx]->desc)); + skill_db[idx].skill_type = 0; + skill_split_atoi(split[14],skill_db[idx].blewcount); + skill_db[idx].inf3 = (int)strtol(split[15], NULL,0); + safestrncpy(skill_db[idx].name, trim(split[16]), sizeof(skill_db[idx].name)); + safestrncpy(skill_db[idx].desc, trim(split[17]), sizeof(skill_db[idx].desc)); + strdb_iput(skilldb_name2id, skill_db[idx].name, skill_id); - strdb_iput(skilldb_name2id, skill_db[idx]->name, skill_id); return true; } @@ -19964,16 +19913,16 @@ uint8 skill_split_atoi2(char *str, int *val, const char *delim, int min_value, u } /// Clear status data from skill requirement -static void skill_destroy_requirement(uint16 idx) { - if (skill_db[idx]->require.status_count) - aFree(skill_db[idx]->require.status); - skill_db[idx]->require.status = NULL; - skill_db[idx]->require.status_count = 0; - - if (skill_db[idx]->require.eqItem_count) - aFree(skill_db[idx]->require.eqItem); - skill_db[idx]->require.eqItem = NULL; - skill_db[idx]->require.eqItem_count = 0; +static void skill_destroy_requirement(void) { + uint16 i; + for (i = 0; i < MAX_SKILL; i++) { + if (skill_db[i].require.status_count) + aFree(skill_db[i].require.status); + skill_db[i].require.status_count = 0; + if (skill_db[i].require.eqItem_count) + aFree(skill_db[i].require.eqItem); + skill_db[i].require.eqItem_count = 0; + } } /** @@ -19985,24 +19934,25 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current) char* p; uint16 skill_id = atoi(split[0]), idx, i; - idx = skill_db_isset(atoi(split[0]), __FUNCTION__); + if (!(idx = skill_get_index(skill_id))) // invalid skill id + return false; - skill_split_atoi(split[1],skill_db[idx]->require.hp); - skill_split_atoi(split[2],skill_db[idx]->require.mhp); - skill_split_atoi(split[3],skill_db[idx]->require.sp); - skill_split_atoi(split[4],skill_db[idx]->require.hp_rate); - skill_split_atoi(split[5],skill_db[idx]->require.sp_rate); - skill_split_atoi(split[6],skill_db[idx]->require.zeny); + skill_split_atoi(split[1],skill_db[idx].require.hp); + skill_split_atoi(split[2],skill_db[idx].require.mhp); + skill_split_atoi(split[3],skill_db[idx].require.sp); + skill_split_atoi(split[4],skill_db[idx].require.hp_rate); + skill_split_atoi(split[5],skill_db[idx].require.sp_rate); + skill_split_atoi(split[6],skill_db[idx].require.zeny); //Witch weapon type are required, see doc/item_db for weapon types (View column) p = split[7]; while (p) { int l = atoi(p); if( l == 99 ) { // Any weapon - skill_db[idx]->require.weapon = 0; + skill_db[idx].require.weapon = 0; break; } else - skill_db[idx]->require.weapon |= 1<require.ammo = AMMO_TYPE_ALL; + skill_db[idx].require.ammo = 0xFFFFFFFF; break; } else if( l ) // 0 stands for no requirement - skill_db[idx]->require.ammo |= 1<require.ammo_qty); + skill_split_atoi(split[9],skill_db[idx].require.ammo_qty); - if( strcmpi(split[10],"hidden") == 0 ) skill_db[idx]->require.state = ST_HIDDEN; - else if( strcmpi(split[10],"riding") == 0 ) skill_db[idx]->require.state = ST_RIDING; - else if( strcmpi(split[10],"falcon") == 0 ) skill_db[idx]->require.state = ST_FALCON; - else if( strcmpi(split[10],"cart") == 0 ) skill_db[idx]->require.state = ST_CART; - else if( strcmpi(split[10],"shield") == 0 ) skill_db[idx]->require.state = ST_SHIELD; - else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill_db[idx]->require.state = ST_RECOV_WEIGHT_RATE; - else if( strcmpi(split[10],"move_enable") == 0 ) skill_db[idx]->require.state = ST_MOVE_ENABLE; - else if( strcmpi(split[10],"water") == 0 ) skill_db[idx]->require.state = ST_WATER; - else if( strcmpi(split[10],"dragon") == 0 ) skill_db[idx]->require.state = ST_RIDINGDRAGON; - else if( strcmpi(split[10],"warg") == 0 ) skill_db[idx]->require.state = ST_WUG; - else if( strcmpi(split[10],"ridingwarg") == 0 ) skill_db[idx]->require.state = ST_RIDINGWUG; - else if( strcmpi(split[10],"mado") == 0 ) skill_db[idx]->require.state = ST_MADO; - else if( strcmpi(split[10],"elementalspirit") == 0 ) skill_db[idx]->require.state = ST_ELEMENTALSPIRIT; - else if( strcmpi(split[10],"peco") == 0 ) skill_db[idx]->require.state = ST_PECO; - else skill_db[idx]->require.state = ST_NONE; // Unknown or no state + if( strcmpi(split[10],"hidden") == 0 ) skill_db[idx].require.state = ST_HIDDEN; + else if( strcmpi(split[10],"riding") == 0 ) skill_db[idx].require.state = ST_RIDING; + else if( strcmpi(split[10],"falcon") == 0 ) skill_db[idx].require.state = ST_FALCON; + else if( strcmpi(split[10],"cart") == 0 ) skill_db[idx].require.state = ST_CART; + else if( strcmpi(split[10],"shield") == 0 ) skill_db[idx].require.state = ST_SHIELD; + else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill_db[idx].require.state = ST_RECOV_WEIGHT_RATE; + else if( strcmpi(split[10],"move_enable") == 0 ) skill_db[idx].require.state = ST_MOVE_ENABLE; + else if( strcmpi(split[10],"water") == 0 ) skill_db[idx].require.state = ST_WATER; + else if( strcmpi(split[10],"dragon") == 0 ) skill_db[idx].require.state = ST_RIDINGDRAGON; + else if( strcmpi(split[10],"warg") == 0 ) skill_db[idx].require.state = ST_WUG; + else if( strcmpi(split[10],"ridingwarg") == 0 ) skill_db[idx].require.state = ST_RIDINGWUG; + else if( strcmpi(split[10],"mado") == 0 ) skill_db[idx].require.state = ST_MADO; + else if( strcmpi(split[10],"elementalspirit") == 0 ) skill_db[idx].require.state = ST_ELEMENTALSPIRIT; + else if( strcmpi(split[10],"peco") == 0 ) skill_db[idx].require.state = ST_PECO; + else skill_db[idx].require.state = ST_NONE; // Unknown or no state //Status requirements //FIXME: Default entry should be -1/SC_ALL in skill_require_db.txt but it's 0/SC_STONE. trim(split[11]); if (split[11][0] != '\0' || atoi(split[11])) { int require[MAX_SKILL_STATUS_REQUIRE]; - if ((skill_db[idx]->require.status_count = skill_split_atoi2(split[11], require, ":", SC_STONE, ARRAYLENGTH(require)))) { - CREATE(skill_db[idx]->require.status, enum sc_type, skill_db[idx]->require.status_count); - for (i = 0; i < skill_db[idx]->require.status_count; i++) - skill_db[idx]->require.status[i] = (sc_type)require[i]; + if ((skill_db[idx].require.status_count = skill_split_atoi2(split[11], require, ":", SC_STONE, ARRAYLENGTH(require)))) { + CREATE(skill_db[idx].require.status, enum sc_type, skill_db[idx].require.status_count); + for (i = 0; i < skill_db[idx].require.status_count; i++) + skill_db[idx].require.status[i] = (sc_type)require[i]; } } - skill_split_atoi(split[12],skill_db[idx]->require.spiritball); + skill_split_atoi(split[12],skill_db[idx].require.spiritball); for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) { - skill_db[idx]->require.itemid[i] = atoi(split[13+ 2*i]); - skill_db[idx]->require.amount[i] = atoi(split[14+ 2*i]); + skill_db[idx].require.itemid[i] = atoi(split[13+ 2*i]); + skill_db[idx].require.amount[i] = atoi(split[14+ 2*i]); } //Equipped Item requirements. @@ -20065,10 +20015,10 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current) trim(split[33]); if (split[33][0] != '\0' || atoi(split[33])) { int require[MAX_SKILL_EQUIP_REQUIRE]; - if ((skill_db[idx]->require.eqItem_count = skill_split_atoi2(split[33], require, ":", 500, ARRAYLENGTH(require)))) { - CREATE(skill_db[idx]->require.eqItem, uint16, skill_db[idx]->require.eqItem_count); - for (i = 0; i < skill_db[idx]->require.eqItem_count; i++) - skill_db[idx]->require.eqItem[i] = require[i]; + if ((skill_db[idx].require.eqItem_count = skill_split_atoi2(split[33], require, ":", 500, ARRAYLENGTH(require)))) { + CREATE(skill_db[idx].require.eqItem, uint16, skill_db[idx].require.eqItem_count); + for (i = 0; i < skill_db[idx].require.eqItem_count; i++) + skill_db[idx].require.eqItem[i] = require[i]; } } return true; @@ -20079,16 +20029,19 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current) */ static bool skill_parse_row_castdb(char* split[], int columns, int current) { - uint16 idx = skill_db_isset(atoi(split[0]), __FUNCTION__); + uint16 idx = skill_get_index(atoi(split[0])); - skill_split_atoi(split[1],skill_db[idx]->cast); - skill_split_atoi(split[2],skill_db[idx]->delay); - skill_split_atoi(split[3],skill_db[idx]->walkdelay); - skill_split_atoi(split[4],skill_db[idx]->upkeep_time); - skill_split_atoi(split[5],skill_db[idx]->upkeep_time2); - skill_split_atoi(split[6],skill_db[idx]->cooldown); + if( !idx ) // invalid skill id + return false; + + skill_split_atoi(split[1],skill_db[idx].cast); + skill_split_atoi(split[2],skill_db[idx].delay); + skill_split_atoi(split[3],skill_db[idx].walkdelay); + skill_split_atoi(split[4],skill_db[idx].upkeep_time); + skill_split_atoi(split[5],skill_db[idx].upkeep_time2); + skill_split_atoi(split[6],skill_db[idx].cooldown); #ifdef RENEWAL_CAST - skill_split_atoi(split[7],skill_db[idx]->fixed_cast); + skill_split_atoi(split[7],skill_db[idx].fixed_cast); #endif return true; } @@ -20098,11 +20051,14 @@ static bool skill_parse_row_castdb(char* split[], int columns, int current) */ static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) { - uint16 idx = skill_db_isset(atoi(split[0]), __FUNCTION__); + uint16 idx = skill_get_index(atoi(split[0])); - skill_db[idx]->castnodex = atoi(split[1]); + if( !idx ) // invalid skill id + return false; + + skill_split_atoi(split[1],skill_db[idx].castnodex); if( split[2] ) // optional column - skill_db[idx]->delaynodex = atoi(split[2]); + skill_split_atoi(split[2],skill_db[idx].delaynodex); return true; } @@ -20112,9 +20068,12 @@ static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) */ static bool skill_parse_row_nocastdb(char* split[], int columns, int current) { - uint16 idx = skill_db_isset(atoi(split[0]), __FUNCTION__); + uint16 idx = skill_get_index(atoi(split[0])); - skill_db[idx]->nocast |= atoi(split[1]); + if( !idx ) // invalid skill id + return false; + + skill_db[idx].nocast |= atoi(split[1]); return true; } @@ -20124,39 +20083,42 @@ static bool skill_parse_row_nocastdb(char* split[], int columns, int current) */ static bool skill_parse_row_unitdb(char* split[], int columns, int current) { - uint16 idx = skill_db_isset(atoi(split[0]), __FUNCTION__); + uint16 idx = skill_get_index(atoi(split[0])); - skill_db[idx]->unit_id[0] = (uint16)strtol(split[1],NULL,16); - skill_db[idx]->unit_id[1] = (uint16)strtol(split[2],NULL,16); - skill_split_atoi(split[3],skill_db[idx]->unit_layout_type); - skill_split_atoi(split[4],skill_db[idx]->unit_range); - skill_db[idx]->unit_interval = atoi(split[5]); + if( !idx ) // invalid skill id + return false; - if( strcmpi(split[6],"noenemy")==0 ) skill_db[idx]->unit_target = BCT_NOENEMY; - else if( strcmpi(split[6],"friend")==0 ) skill_db[idx]->unit_target = BCT_NOENEMY; - else if( strcmpi(split[6],"party")==0 ) skill_db[idx]->unit_target = BCT_PARTY; - else if( strcmpi(split[6],"ally")==0 ) skill_db[idx]->unit_target = BCT_PARTY|BCT_GUILD; - else if( strcmpi(split[6],"guild")==0 ) skill_db[idx]->unit_target = BCT_GUILD; - else if( strcmpi(split[6],"all")==0 ) skill_db[idx]->unit_target = BCT_ALL; - else if( strcmpi(split[6],"enemy")==0 ) skill_db[idx]->unit_target = BCT_ENEMY; - else if( strcmpi(split[6],"self")==0 ) skill_db[idx]->unit_target = BCT_SELF; - else if( strcmpi(split[6],"sameguild")==0 ) skill_db[idx]->unit_target = BCT_GUILD|BCT_SAMEGUILD; - else if( strcmpi(split[6],"noone")==0 ) skill_db[idx]->unit_target = BCT_NOONE; - else skill_db[idx]->unit_target = strtol(split[6],NULL,16); + skill_db[idx].unit_id[0] = strtol(split[1],NULL,16); + skill_db[idx].unit_id[1] = strtol(split[2],NULL,16); + skill_split_atoi(split[3],skill_db[idx].unit_layout_type); + skill_split_atoi(split[4],skill_db[idx].unit_range); + skill_db[idx].unit_interval = atoi(split[5]); - skill_db[idx]->unit_flag = strtol(split[7],NULL,16); + if( strcmpi(split[6],"noenemy")==0 ) skill_db[idx].unit_target = BCT_NOENEMY; + else if( strcmpi(split[6],"friend")==0 ) skill_db[idx].unit_target = BCT_NOENEMY; + else if( strcmpi(split[6],"party")==0 ) skill_db[idx].unit_target = BCT_PARTY; + else if( strcmpi(split[6],"ally")==0 ) skill_db[idx].unit_target = BCT_PARTY|BCT_GUILD; + else if( strcmpi(split[6],"guild")==0 ) skill_db[idx].unit_target = BCT_GUILD; + else if( strcmpi(split[6],"all")==0 ) skill_db[idx].unit_target = BCT_ALL; + else if( strcmpi(split[6],"enemy")==0 ) skill_db[idx].unit_target = BCT_ENEMY; + else if( strcmpi(split[6],"self")==0 ) skill_db[idx].unit_target = BCT_SELF; + else if( strcmpi(split[6],"sameguild")==0 ) skill_db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD; + else if( strcmpi(split[6],"noone")==0 ) skill_db[idx].unit_target = BCT_NOONE; + else skill_db[idx].unit_target = strtol(split[6],NULL,16); - if (skill_db[idx]->unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) - skill_db[idx]->unit_target = BCT_NOENEMY; + skill_db[idx].unit_flag = strtol(split[7],NULL,16); + + if (skill_db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + skill_db[idx].unit_target = BCT_NOENEMY; //By default, target just characters. - skill_db[idx]->unit_target |= BL_CHAR; - if (skill_db[idx]->unit_flag&UF_NOPC) - skill_db[idx]->unit_target &= ~BL_PC; - if (skill_db[idx]->unit_flag&UF_NOMOB) - skill_db[idx]->unit_target &= ~BL_MOB; - if (skill_db[idx]->unit_flag&UF_SKILL) - skill_db[idx]->unit_target |= BL_SKILL; + skill_db[idx].unit_target |= BL_CHAR; + if (skill_db[idx].unit_flag&UF_NOPC) + skill_db[idx].unit_target &= ~BL_PC; + if (skill_db[idx].unit_flag&UF_NOMOB) + skill_db[idx].unit_target &= ~BL_MOB; + if (skill_db[idx].unit_flag&UF_SKILL) + skill_db[idx].unit_target |= BL_SKILL; return true; } @@ -20367,24 +20329,26 @@ static bool skill_parse_row_copyabledb(char* split[], int column, int current) else id = skill_name2id(split[0]); - id = skill_db_isset(id, __FUNCTION__); - + if ((id = skill_get_index(id)) == 0) { + ShowError("skill_parse_row_copyabledb: Invalid skill '%s'\n",split[0]); + return false; + } if ((option = atoi(split[1])) > 3) { ShowError("skill_parse_row_copyabledb: Invalid option '%s'\n",split[1]); return false; } // Import just for clearing/disabling from original data if (option == 0) { - memset(&skill_db[id]->copyable, 0, sizeof(skill_db[id]->copyable)); + memset(&skill_db[id].copyable, 0, sizeof(skill_db[id].copyable)); //ShowInfo("skill_parse_row_copyabledb: Skill %s removed from list.\n", split[0]); return true; } - skill_db[id]->copyable.option = option; - skill_db[id]->copyable.joballowed = 63; + skill_db[id].copyable.option = option; + skill_db[id].copyable.joballowed = 63; if (atoi(split[2])) - skill_db[id]->copyable.joballowed = cap_value(atoi(split[2]),1,63); - skill_db[id]->copyable.req_opt = cap_value(atoi(split[3]),0,(0x2000)-1); + skill_db[id].copyable.joballowed = cap_value(atoi(split[2]),1,63); + skill_db[id].copyable.req_opt = cap_value(atoi(split[3]),0,(0x2000)-1); return true; } @@ -20402,10 +20366,13 @@ static bool skill_parse_row_nonearnpcrangedb(char* split[], int column, int curr else id = skill_name2id(split[0]); - id = skill_db_isset(atoi(split[0]), __FUNCTION__); + if ((id = skill_get_index(id)) == 0) { // invalid skill id + ShowError("skill_parse_row_nonearnpcrangedb: Invalid skill '%s'\n",split[0]); + return false; + } - skill_db[id]->unit_nonearnpc_range = max(atoi(split[1]),0); - skill_db[id]->unit_nonearnpc_type = (atoi(split[2])) ? cap_value(atoi(split[2]),1,15) : 15; + skill_db[id].unit_nonearnpc_range = max(atoi(split[1]),0); + skill_db[id].unit_nonearnpc_type = (atoi(split[2])) ? cap_value(atoi(split[2]),1,15) : 15; return true; } @@ -20508,62 +20475,24 @@ static bool skill_parse_row_changematerialdb(char* split[], int columns, int cur static bool skill_parse_row_skilldamage(char* split[], int columns, int current) { uint16 skill_id = skill_name2id(split[0]), idx; - - idx = skill_db_isset(atoi(split[0]), __FUNCTION__); - - memset(&skill_db[idx]->damage,0,sizeof(struct s_skill_damage)); - skill_db[idx]->damage.caster |= atoi(split[1]); - skill_db[idx]->damage.map |= atoi(split[2]); - skill_db[idx]->damage.pc = cap_value(atoi(split[3]),-100,INT_MAX); + if ((idx = skill_get_index(skill_id)) == 0) { // invalid skill id + ShowWarning("skill_parse_row_skilldamage: Invalid skill '%s'. Skipping..",split[0]); + return false; + } + memset(&skill_db[idx].damage,0,sizeof(struct s_skill_damage)); + skill_db[idx].damage.caster |= atoi(split[1]); + skill_db[idx].damage.map |= atoi(split[2]); + skill_db[idx].damage.pc = cap_value(atoi(split[3]),-100,INT_MAX); if (split[3]) - skill_db[idx]->damage.mob = cap_value(atoi(split[4]),-100,INT_MAX); + skill_db[idx].damage.mob = cap_value(atoi(split[4]),-100,INT_MAX); if (split[4]) - skill_db[idx]->damage.boss = cap_value(atoi(split[5]),-100,INT_MAX); + skill_db[idx].damage.boss = cap_value(atoi(split[5]),-100,INT_MAX); if (split[5]) - skill_db[idx]->damage.other = cap_value(atoi(split[6]),-100,INT_MAX); + skill_db[idx].damage.other = cap_value(atoi(split[6]),-100,INT_MAX); return true; } #endif -/** - * Init dummy skill db also init Skill DB allocation - * @param skill_id - * @return Skill Index - **/ -static uint16 skill_db_create(uint16 skill_id) { - if (skill_num >= MAX_SKILL) { - ShowError("Cannot add more skill. Limit is reached '%d'. Change 'MAX_SKILL' in mmo.h\n", MAX_SKILL); - return 0; - } - if (!skill_num) - CREATE(skill_db, struct s_skill_db *, 1); - else - RECREATE(skill_db, struct s_skill_db *, skill_num+1); - - CREATE(skill_db[skill_num], struct s_skill_db, 1); - if (skill_id > 0) { - safestrncpy(skill_db[skill_num]->name, "UNKNOWN_SKILL", sizeof(skill_db[skill_num]->name)); - safestrncpy(skill_db[skill_num]->desc, "Unknown Skill", sizeof(skill_db[skill_num]->desc)); - } - skill_db[skill_num]->nameid = skill_id; - uidb_iput(skilldb_id2idx, skill_id, skill_num); - return skill_next_idx(); -} - -static void skill_db_destroy(void) { - uint16 i; - for (i = 0; i < SKILL_MAX_DB(); i++) { - if (skill_db[i]) { - skill_destroy_requirement(i); - aFree(skill_db[i]); - } - skill_db[i] = NULL; - } - skill_num = 0; - aFree(skill_db); - skill_db = NULL; -} - /*=============================== * DB reading. * skill_db.txt @@ -20585,12 +20514,9 @@ static void skill_readdb(void) //add other path here }; + // init skill db structures db_clear(skilldb_name2id); - db_clear(skilldb_id2idx); - - skill_db_destroy(); - skill_db_create(0); - + memset(skill_db,0,sizeof(skill_db)); memset(skill_produce_db,0,sizeof(skill_produce_db)); memset(skill_arrow_db,0,sizeof(skill_arrow_db)); memset(skill_abra_db,0,sizeof(skill_abra_db)); @@ -20599,6 +20525,9 @@ static void skill_readdb(void) memset(skill_changematerial_db,0,sizeof(skill_changematerial_db)); skill_produce_count = skill_arrow_count = skill_abra_count = skill_improvise_count = skill_changematerial_count = skill_spellbook_count = skill_magicmushroom_count = 0; + // load skill databases + safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name)); + safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc)); for(i=0; i= HM_SKILLBASE && (skill_id) < HM_SKILLBASE+MAX_HOMUNSKILL ) -#define SKILL_CHK_MERC(skill_id) ( (skill_id) >= MC_SKILLBASE && (skill_id) < MC_SKILLBASE+MAX_MERCSKILL ) -#define SKILL_CHK_ELEM(skill_id) ( (skill_id) >= EL_SKILLBASE && (skill_id) < EL_SKILLBASE+MAX_ELEMENTALSKILL ) -#define SKILL_CHK_GUILD(skill_id) ( (skill_id) >= GD_SKILLBASE && (skill_id) < GD_SKILLBASE+MAX_GUILDSKILL ) - #endif /* _SKILL_H_ */ diff --git a/src/map/status.c b/src/map/status.c index b11a15ac7a..bc3eb34d21 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -154,11 +154,11 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { uint16 idx = skill_get_index(skill_id); if( idx == 0 ) { - ShowError("set_sc: Unsupported skill id %d (SC: %d. Icon: %d)\n", skill_id, sc, icon); + ShowError("set_sc: Unsupported skill id %d\n", skill_id); return; } if( sc < 0 || sc >= SC_MAX ) { - ShowError("set_sc: Unsupported status change id %d (Skill: %d. Icon: %d)\n", sc, skill_id, icon); + ShowError("set_sc: Unsupported status change id %d\n", sc); return; } @@ -172,16 +172,6 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) SkillStatusChangeTable[idx] = sc; } -static void set_sc_with_vfx_noskill(sc_type sc, int icon, unsigned flag) { - if (sc > SC_NONE && sc < SC_MAX) { - if (StatusIconChangeTable[sc] == SI_BLANK) - StatusIconChangeTable[sc] = icon; - StatusChangeFlagTable[sc] |= flag; - } - if (icon > SI_BLANK && icon < SI_MAX) - StatusRelevantBLTypes[icon] |= BL_SCEFFECT; -} - void initChangeTables(void) { int i; @@ -801,6 +791,8 @@ void initChangeTables(void) set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE ); set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc_with_vfx( SC_MOONSTAR , SC_MOONSTAR , SI_MOONSTAR , SCB_NONE ); + set_sc_with_vfx( SC_SUPER_STAR , SC_SUPER_STAR , SI_SUPER_STAR , SCB_NONE ); /* Rebellion */ add_sc( RL_MASS_SPIRAL , SC_BLEEDING ); @@ -814,26 +806,24 @@ void initChangeTables(void) set_sc_with_vfx( RL_C_MARKER , SC_C_MARKER , SI_C_MARKER , SCB_FLEE ); set_sc_with_vfx( RL_AM_BLAST , SC_ANTI_M_BLAST , SI_ANTI_M_BLAST , SCB_NONE ); - set_sc_with_vfx_noskill( SC_MOONSTAR , SI_MOONSTAR , SCB_NONE ); - set_sc_with_vfx_noskill( SC_SUPER_STAR , SI_SUPER_STAR , SCB_NONE ); - set_sc_with_vfx_noskill( SC_ALL_RIDING , SI_ALL_RIDING , SCB_SPEED ); + set_sc_with_vfx( SC_ALL_RIDING , SC_ALL_RIDING , SI_ALL_RIDING , SCB_SPEED ); /* Storing the target job rather than simply SC_SPIRIT simplifies code later on */ - SkillStatusChangeTable[skill_get_index(SL_ALCHEMIST)] = (sc_type)MAPID_ALCHEMIST, - SkillStatusChangeTable[skill_get_index(SL_MONK)] = (sc_type)MAPID_MONK, - SkillStatusChangeTable[skill_get_index(SL_STAR)] = (sc_type)MAPID_STAR_GLADIATOR, - SkillStatusChangeTable[skill_get_index(SL_SAGE)] = (sc_type)MAPID_SAGE, - SkillStatusChangeTable[skill_get_index(SL_CRUSADER)] = (sc_type)MAPID_CRUSADER, - SkillStatusChangeTable[skill_get_index(SL_SUPERNOVICE)] = (sc_type)MAPID_SUPER_NOVICE, - SkillStatusChangeTable[skill_get_index(SL_KNIGHT)] = (sc_type)MAPID_KNIGHT, - SkillStatusChangeTable[skill_get_index(SL_WIZARD)] = (sc_type)MAPID_WIZARD, - SkillStatusChangeTable[skill_get_index(SL_PRIEST)] = (sc_type)MAPID_PRIEST, - SkillStatusChangeTable[skill_get_index(SL_BARDDANCER)] = (sc_type)MAPID_BARDDANCER, - SkillStatusChangeTable[skill_get_index(SL_ROGUE)] = (sc_type)MAPID_ROGUE, - SkillStatusChangeTable[skill_get_index(SL_ASSASIN)] = (sc_type)MAPID_ASSASSIN, - SkillStatusChangeTable[skill_get_index(SL_BLACKSMITH)] = (sc_type)MAPID_BLACKSMITH, - SkillStatusChangeTable[skill_get_index(SL_HUNTER)] = (sc_type)MAPID_HUNTER, - SkillStatusChangeTable[skill_get_index(SL_SOULLINKER)] = (sc_type)MAPID_SOUL_LINKER, + SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, + SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK, + SkillStatusChangeTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, + SkillStatusChangeTable[SL_SAGE] = (sc_type)MAPID_SAGE, + SkillStatusChangeTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, + SkillStatusChangeTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, + SkillStatusChangeTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, + SkillStatusChangeTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, + SkillStatusChangeTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, + SkillStatusChangeTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, + SkillStatusChangeTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, + SkillStatusChangeTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, + SkillStatusChangeTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, + SkillStatusChangeTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, + SkillStatusChangeTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, /* Status that don't have a skill associated */ StatusIconChangeTable[SC_WEIGHT50] = SI_WEIGHT50; diff --git a/src/map/unit.c b/src/map/unit.c index 04180f064a..ad1fcbed32 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1796,7 +1796,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui // Moved here to prevent Suffragium from ending if skill fails #ifndef RENEWAL_CAST - if (!(skill_get_castnodex(skill_id)&2)) + if (!(skill_get_castnodex(skill_id, skill_lv)&2)) casttime = skill_castfix_sc(src, casttime); #else casttime = skill_vfcastfix(src, casttime, skill_id, skill_lv); @@ -2013,7 +2013,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui // Moved here to prevent Suffragium from ending if skill fails #ifndef RENEWAL_CAST - if (!(skill_get_castnodex(skill_id)&2)) + if (!(skill_get_castnodex(skill_id, skill_lv)&2)) casttime = skill_castfix_sc(src, casttime); #else casttime = skill_vfcastfix(src, casttime, skill_id, skill_lv ); @@ -2035,11 +2035,11 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui // } // } - ud->skill_id = skill_id; - ud->skill_lv = skill_lv; - ud->skillx = skill_x; - ud->skilly = skill_y; - ud->skilltarget = 0; + ud->skill_id = skill_id; + ud->skill_lv = skill_lv; + ud->skillx = skill_x; + ud->skilly = skill_y; + ud->skilltarget = 0; if( sc ) { // These 3 status do not stack, so it's efficient to use if-else